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 "softbus_queue.h"
17 #include "softbus_adapter_mem.h"
18 #include "softbus_def.h"
19
20 #ifdef __cplusplus
21 #if __cplusplus
22 extern "C" {
23 #endif
24 #endif
25
26 #define IS_POWER_OF_2(x) ((((x) - 1) & (x)) == 0)
27 #define QUEUE_HEADER_MAGIC 0xccddddcc
28 #define QUEUE_SIZE_MAX 8192
29 #define CACHE_LINE_SIZE 64
30
QueueInit(LockFreeQueue * queue,uint32_t unitNum)31 int32_t QueueInit(LockFreeQueue* queue, uint32_t unitNum)
32 {
33 if (queue == NULL) {
34 return QUEUE_INVAL;
35 }
36 if (!IS_POWER_OF_2(unitNum)) {
37 return QUEUE_INVAL;
38 }
39
40 (void)memset_s(queue, sizeof(LockFreeQueue), 0, sizeof(LockFreeQueue));
41
42 queue->magic = QUEUE_HEADER_MAGIC;
43 queue->producer.size = unitNum;
44 queue->consumer.size = unitNum;
45 queue->producer.mask = unitNum - 1;
46 queue->consumer.mask = unitNum - 1;
47 queue->producer.head = 0;
48 queue->consumer.head = 0;
49 queue->producer.tail = 0;
50 queue->consumer.tail = 0;
51 queue->unitNum = unitNum;
52
53 return 0;
54 }
55
QueueSizeCalc(uint32_t unitNum,uint32_t * queueSize)56 int32_t QueueSizeCalc(uint32_t unitNum, uint32_t* queueSize)
57 {
58 uint32_t size;
59
60 if (queueSize == NULL) {
61 return QUEUE_INVAL;
62 }
63 if (unitNum > QUEUE_SIZE_MAX) {
64 return QUEUE_INVAL;
65 }
66
67 size = sizeof(uintptr_t) * unitNum + sizeof(LockFreeQueue);
68 *queueSize = ((size + CACHE_LINE_SIZE - 1) & (~(CACHE_LINE_SIZE - 1)));
69 return 0;
70 }
71
QueueCountGet(const LockFreeQueue * queue,uint32_t * count)72 int32_t QueueCountGet(const LockFreeQueue* queue, uint32_t* count)
73 {
74 uint32_t producerTail;
75 uint32_t consumerTail;
76 uint32_t mask;
77
78 if (queue == NULL || count == NULL) {
79 return QUEUE_INVAL;
80 }
81 producerTail = queue->producer.tail;
82 consumerTail = queue->consumer.tail;
83 mask = queue->producer.mask;
84
85 *count = ((producerTail - consumerTail) & mask);
86 return 0;
87 }
88
CreateQueue(uint32_t unitNum)89 NO_SANITIZE("cfi") LockFreeQueue* CreateQueue(uint32_t unitNum)
90 {
91 if (!IS_POWER_OF_2(unitNum)) {
92 return NULL;
93 }
94 uint32_t queueSize;
95 int ret = QueueSizeCalc(unitNum, &queueSize);
96 if (ret != 0) {
97 return NULL;
98 }
99 LockFreeQueue *queue = (LockFreeQueue *)SoftBusCalloc(queueSize);
100 if (queue == NULL) {
101 return NULL;
102 }
103 ret = QueueInit(queue, unitNum);
104 if (ret != 0) {
105 SoftBusFree(queue);
106 return NULL;
107 }
108 return queue;
109 }
110
111 #ifdef __cplusplus
112 #if __cplusplus
113 }
114 #endif /* __cplusplus */
115 #endif /* __cplusplus */