• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 <stdbool.h>
17 #include <stdint.h>
18 #include <string.h>
19 
20 #include "common_list.h"
21 #include "securec.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_ble_queue.h"
24 #include "softbus_conn_manager.h"
25 #include "softbus_def.h"
26 #include "softbus_errcode.h"
27 #include "softbus_log.h"
28 #include "softbus_queue.h"
29 #include "softbus_type_def.h"
30 
31 #define QUEUE_NUM_PER_PID 3
32 #define HIGH_PRIORITY_DEFAULT_LIMIT 32
33 #define MIDDLE_PRIORITY_DEFAULT_LIMIT 32
34 #define LOW_PRIORITY_DEFAULT_LIMIT 16
35 
36 typedef struct {
37     ListNode node;
38     int32_t pid;
39     LockFreeQueue *queue[QUEUE_NUM_PER_PID];
40 } BleQueue;
41 
42 typedef enum {
43     HIGH_PRIORITY = 0,
44     MIDDLE_PRIORITY,
45     LOW_PRIORITY,
46     PRIORITY_BOUNDARY
47 } QueuePriority;
48 
49 static const int32_t QUEUE_LIMIT[QUEUE_NUM_PER_PID] = {
50     HIGH_PRIORITY_DEFAULT_LIMIT,
51     MIDDLE_PRIORITY_DEFAULT_LIMIT,
52     LOW_PRIORITY_DEFAULT_LIMIT
53 };
54 static LIST_HEAD(g_bleQueueList);
55 static SoftBusMutex g_bleQueueLock;
56 static BleQueue *g_innerQueue = NULL;
57 static SoftBusCond g_sendCond;
58 
CreateBleQueue(int32_t pid)59 static BleQueue *CreateBleQueue(int32_t pid)
60 {
61     BleQueue *queue = (BleQueue *)SoftBusCalloc(sizeof(BleQueue));
62     if (queue == NULL) {
63         return NULL;
64     }
65     queue->pid = pid;
66     int i;
67     for (i = 0; i < QUEUE_NUM_PER_PID; i++) {
68         queue->queue[i] = CreateQueue(QUEUE_LIMIT[i]);
69         if (queue->queue[i] == NULL) {
70             goto ERR_RETURN;
71         }
72     }
73     return queue;
74 ERR_RETURN:
75     for (i--; i >= 0; i--) {
76         SoftBusFree(queue->queue[i]);
77     }
78     SoftBusFree(queue);
79     return NULL;
80 }
81 
DestroyBleQueue(BleQueue * queue)82 static void DestroyBleQueue(BleQueue *queue)
83 {
84     if (queue == NULL) {
85         return;
86     }
87     for (int i = 0; i < QUEUE_NUM_PER_PID; i++) {
88         SoftBusFree(queue->queue[i]);
89     }
90     SoftBusFree(queue);
91 }
92 
GetPriority(int32_t flag)93 static int GetPriority(int32_t flag)
94 {
95     switch (flag) {
96         case CONN_HIGH:
97             return HIGH_PRIORITY;
98         case CONN_MIDDLE:
99             return MIDDLE_PRIORITY;
100         default:
101             return LOW_PRIORITY;
102     }
103 }
104 
BleEnqueueNonBlock(const void * msg)105 int BleEnqueueNonBlock(const void *msg)
106 {
107     if (msg == NULL) {
108         return SOFTBUS_INVALID_PARAM;
109     }
110     SendQueueNode *queueNode = (SendQueueNode *)msg;
111     int32_t priority = GetPriority(queueNode->flag);
112     if (SoftBusMutexLock(&g_bleQueueLock) != EOK) {
113         return SOFTBUS_LOCK_ERR;
114     }
115     int32_t ret = SOFTBUS_ERR;
116     bool isListEmpty = true;
117     if (queueNode->pid == 0) {
118         ret = QueueMultiProducerEnqueue(g_innerQueue->queue[priority], msg);
119         goto END;
120     }
121 
122     if (!IsListEmpty(&g_bleQueueList)) {
123         isListEmpty = false;
124     }
125     LockFreeQueue *lockFreeQueue = NULL;
126     BleQueue *item = NULL;
127     LIST_FOR_EACH_ENTRY(item, &g_bleQueueList, BleQueue, node) {
128         if (item->pid == queueNode->pid) {
129             lockFreeQueue = item->queue[priority];
130             break;
131         }
132     }
133     if (lockFreeQueue == NULL) {
134         BleQueue *newQueue = CreateBleQueue(queueNode->pid);
135         if (newQueue == NULL) {
136             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "BleEnqueueNonBlock CreateBleQueue failed");
137             goto END;
138         }
139         ListTailInsert(&g_bleQueueList, &(newQueue->node));
140         lockFreeQueue = newQueue->queue[priority];
141     }
142     ret = QueueMultiProducerEnqueue(lockFreeQueue, msg);
143 END:
144     if (isListEmpty) {
145         (void)SoftBusCondBroadcast(&g_sendCond);
146     }
147     (void)SoftBusMutexUnlock(&g_bleQueueLock);
148     return ret;
149 }
150 
GetMsg(BleQueue * queue,void ** msg)151 static int GetMsg(BleQueue *queue, void **msg)
152 {
153     for (int i = 0; i < QUEUE_NUM_PER_PID; i++) {
154         if (QueueSingleConsumerDequeue(queue->queue[i], msg) == 0) {
155             return SOFTBUS_OK;
156         }
157     }
158     return SOFTBUS_ERR;
159 }
160 
BleDequeueBlock(void ** msg)161 int BleDequeueBlock(void **msg)
162 {
163     int32_t status = SOFTBUS_ERR;
164     BleQueue *item = NULL;
165     BleQueue *next = NULL;
166 
167     if (msg == NULL) {
168         return SOFTBUS_INVALID_PARAM;
169     }
170     if (SoftBusMutexLock(&g_bleQueueLock) != EOK) {
171         return SOFTBUS_LOCK_ERR;
172     }
173     do {
174         if (GetMsg(g_innerQueue, msg) == SOFTBUS_OK) {
175             status = SOFTBUS_OK;
176             break;
177         }
178         LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_bleQueueList, BleQueue, node) {
179             ListDelete(&(item->node));
180             if (GetMsg(item, msg) == SOFTBUS_OK) {
181                 ListTailInsert(&g_bleQueueList, &(item->node));
182                 status = SOFTBUS_OK;
183                 break;
184             }
185             DestroyBleQueue(item);
186         }
187         if (status == SOFTBUS_OK) {
188             break;
189         }
190         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "ble queue is empty, dequeue start wait...");
191         if (SoftBusCondWait(&g_sendCond, &g_bleQueueLock, NULL) != SOFTBUS_OK) {
192             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "BleSendCondWait failed");
193             status = SOFTBUS_ERR;
194             break;
195         }
196     } while (true);
197     (void)SoftBusMutexUnlock(&g_bleQueueLock);
198     return status;
199 }
200 
BleInnerQueueInit(void)201 int BleInnerQueueInit(void)
202 {
203     if (SoftBusMutexInit(&g_bleQueueLock, NULL) != 0) {
204         return SOFTBUS_ERR;
205     }
206     if (SoftBusCondInit(&g_sendCond) != SOFTBUS_OK) {
207         (void)SoftBusMutexDestroy(&g_bleQueueLock);
208         return SOFTBUS_ERR;
209     }
210     g_innerQueue = CreateBleQueue(0);
211     if (g_innerQueue == NULL) {
212         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "BleQueueInit CreateBleQueue(0) failed");
213         (void)SoftBusMutexDestroy(&g_bleQueueLock);
214         (void)SoftBusCondDestroy(&g_sendCond);
215         return SOFTBUS_ERR;
216     }
217     return SOFTBUS_OK;
218 }
219 
BleInnerQueueDeinit(void)220 void BleInnerQueueDeinit(void)
221 {
222     (void)SoftBusMutexDestroy(&g_bleQueueLock);
223     (void)SoftBusCondDestroy(&g_sendCond);
224     DestroyBleQueue(g_innerQueue);
225     g_innerQueue = NULL;
226 }