1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "comm_log.h"
17 #include "softbus_queue.h"
18 #include "softbus_adapter_mem.h"
19 #include "softbus_def.h"
20
21 #ifdef __cplusplus
22 #if __cplusplus
23 extern "C" {
24 #endif
25 #endif
26
27 #define IS_POWER_OF_2(x) ((((x) - 1) & (x)) == 0)
28 #define QUEUE_HEADER_MAGIC 0xccddddcc
29 #define QUEUE_SIZE_MAX 8192
30 #define CACHE_LINE_SIZE 64
31
QueueInit(LockFreeQueue * queue,uint32_t unitNum)32 int32_t QueueInit(LockFreeQueue* queue, uint32_t unitNum)
33 {
34 if (queue == NULL) {
35 COMM_LOGE(COMM_UTILS, "queue is null");
36 return QUEUE_INVAL;
37 }
38 if (unitNum < 1 || !IS_POWER_OF_2(unitNum)) {
39 COMM_LOGE(COMM_UTILS, "invalid param");
40 return QUEUE_INVAL;
41 }
42
43 (void)memset_s(queue, sizeof(LockFreeQueue), 0, sizeof(LockFreeQueue));
44
45 queue->magic = QUEUE_HEADER_MAGIC;
46 queue->producer.size = unitNum;
47 queue->consumer.size = unitNum;
48 queue->producer.mask = unitNum - 1;
49 queue->consumer.mask = unitNum - 1;
50 queue->producer.head = 0;
51 queue->consumer.head = 0;
52 queue->producer.tail = 0;
53 queue->consumer.tail = 0;
54 queue->unitNum = unitNum;
55
56 return 0;
57 }
58
QueueSizeCalc(uint32_t unitNum,uint32_t * queueSize)59 int32_t QueueSizeCalc(uint32_t unitNum, uint32_t* queueSize)
60 {
61 uint32_t size;
62
63 if (queueSize == NULL) {
64 COMM_LOGE(COMM_UTILS, "queueSize is null");
65 return QUEUE_INVAL;
66 }
67 if (unitNum > QUEUE_SIZE_MAX) {
68 COMM_LOGE(COMM_UTILS, "unitNum is invalid param unitNum=%{public}u", unitNum);
69 return QUEUE_INVAL;
70 }
71
72 size = sizeof(uintptr_t) * unitNum + sizeof(LockFreeQueue);
73 *queueSize = ((size + CACHE_LINE_SIZE - 1) & (~(CACHE_LINE_SIZE - 1)));
74 return 0;
75 }
76
QueueCountGet(const LockFreeQueue * queue,uint32_t * count)77 int32_t QueueCountGet(const LockFreeQueue* queue, uint32_t* count)
78 {
79 uint32_t producerTail;
80 uint32_t consumerTail;
81 uint32_t mask;
82
83 if (queue == NULL || count == NULL) {
84 COMM_LOGE(COMM_UTILS, "invalid param");
85 return QUEUE_INVAL;
86 }
87 producerTail = queue->producer.tail;
88 consumerTail = queue->consumer.tail;
89 mask = queue->producer.mask;
90
91 *count = ((producerTail - consumerTail) & mask);
92 return 0;
93 }
94
CreateQueue(uint32_t unitNum)95 LockFreeQueue* CreateQueue(uint32_t unitNum)
96 {
97 if (unitNum < 1 || !IS_POWER_OF_2(unitNum)) {
98 return NULL;
99 }
100 uint32_t queueSize;
101 int ret = QueueSizeCalc(unitNum, &queueSize);
102 if (ret != 0) {
103 return NULL;
104 }
105 LockFreeQueue *queue = (LockFreeQueue *)SoftBusCalloc(queueSize);
106 if (queue == NULL) {
107 COMM_LOGE(COMM_UTILS, "SoftBusCalloc fail");
108 return NULL;
109 }
110 ret = QueueInit(queue, unitNum);
111 if (ret != 0) {
112 COMM_LOGE(COMM_UTILS, "QueueInit fail");
113 SoftBusFree(queue);
114 return NULL;
115 }
116 return queue;
117 }
118
119 #ifdef __cplusplus
120 #if __cplusplus
121 }
122 #endif /* __cplusplus */
123 #endif /* __cplusplus */