• 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 
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 */