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