• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */