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
18 #include "common_list.h"
19 #include "securec.h"
20 #include "conn_log.h"
21 #include "softbus_adapter_mem.h"
22 #include "softbus_conn_ble_send_queue.h"
23 #include "softbus_conn_common.h"
24 #include "softbus_conn_manager.h"
25 #include "softbus_def.h"
26 #include "softbus_queue.h"
27 #define BLE_WAIT_TIME_SEC (600)
28
29 static LIST_HEAD(g_bleQueueList);
30 static SoftBusMutex g_bleQueueLock;
31 static ConnectionQueue *g_innerQueue = NULL;
32 static SoftBusCond g_sendCond;
33 static SoftBusCond g_sendWaitCond;
34
CreateBleQueue(int32_t pid)35 static ConnectionQueue *CreateBleQueue(int32_t pid)
36 {
37 ConnectionQueue *queue = (ConnectionQueue *)SoftBusCalloc(sizeof(ConnectionQueue));
38 if (queue == NULL) {
39 return NULL;
40 }
41 queue->pid = pid;
42 int32_t i;
43 for (i = 0; i < QUEUE_NUM_PER_PID; i++) {
44 queue->queue[i] = CreateQueue(GetQueueLimit(i));
45 if (queue->queue[i] == NULL) {
46 goto ERR_RETURN;
47 }
48 }
49 return queue;
50 ERR_RETURN:
51 for (i--; i >= 0; i--) {
52 SoftBusFree(queue->queue[i]);
53 }
54 SoftBusFree(queue);
55 return NULL;
56 }
57
DestroyBleQueue(ConnectionQueue * queue)58 static void DestroyBleQueue(ConnectionQueue *queue)
59 {
60 if (queue == NULL) {
61 return;
62 }
63 for (int32_t i = 0; i < QUEUE_NUM_PER_PID; i++) {
64 SoftBusFree(queue->queue[i]);
65 }
66 SoftBusFree(queue);
67 }
68
GetPriority(int32_t flag)69 static int32_t GetPriority(int32_t flag)
70 {
71 switch (flag) {
72 case CONN_HIGH:
73 return HIGH_PRIORITY;
74 case CONN_MIDDLE:
75 return MIDDLE_PRIORITY;
76 default:
77 return LOW_PRIORITY;
78 }
79 }
80
ConnBleEnqueueNonBlock(const void * msg)81 int32_t ConnBleEnqueueNonBlock(const void *msg)
82 {
83 CONN_CHECK_AND_RETURN_RET_LOGW(msg != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, "msg is null");
84 SendQueueNode *queueNode = (SendQueueNode *)msg;
85 int32_t priority = GetPriority(queueNode->flag);
86 if (SoftBusMutexLock(&g_bleQueueLock) != EOK) {
87 CONN_LOGE(CONN_BLE, "Lock failed");
88 return SOFTBUS_LOCK_ERR;
89 }
90 bool isListEmpty = true;
91 int32_t ret = SOFTBUS_CONN_BLE_INTERNAL_ERR;
92 if (queueNode->pid == 0) {
93 ret = WaitQueueLength(g_innerQueue->queue[priority], GetQueueLimit(priority), WAIT_QUEUE_BUFFER_PERIOD_LEN,
94 &g_sendWaitCond, &g_bleQueueLock);
95 if (ret == SOFTBUS_OK) {
96 ret = QueueMultiProducerEnqueue(g_innerQueue->queue[priority], msg);
97 }
98 goto END;
99 }
100 isListEmpty = IsListEmpty(&g_bleQueueList);
101 LockFreeQueue *lockFreeQueue = NULL;
102 ConnectionQueue *item = NULL;
103 LIST_FOR_EACH_ENTRY(item, &g_bleQueueList, ConnectionQueue, node) {
104 if (item->pid == queueNode->pid) {
105 lockFreeQueue = item->queue[priority];
106 break;
107 }
108 }
109 if (lockFreeQueue == NULL) {
110 ConnectionQueue *newQueue = CreateBleQueue(queueNode->pid);
111 if (newQueue == NULL) {
112 CONN_LOGE(CONN_BLE, "ConnBleEnqueueNonBlock CreateBleQueue failed");
113 goto END;
114 }
115 ListTailInsert(&g_bleQueueList, &(newQueue->node));
116 lockFreeQueue = newQueue->queue[priority];
117 } else {
118 ret = WaitQueueLength(
119 lockFreeQueue, GetQueueLimit(priority), WAIT_QUEUE_BUFFER_PERIOD_LEN, &g_sendWaitCond, &g_bleQueueLock);
120 if (ret != SOFTBUS_OK) {
121 goto END;
122 }
123 }
124 ret = QueueMultiProducerEnqueue(lockFreeQueue, msg);
125 END:
126 if (isListEmpty) {
127 (void)SoftBusCondBroadcast(&g_sendCond);
128 }
129 (void)SoftBusMutexUnlock(&g_bleQueueLock);
130 return ret;
131 }
132
ConnBleDequeueBlock(void ** msg)133 int32_t ConnBleDequeueBlock(void **msg)
134 {
135 bool isFull = false;
136 int32_t status = SOFTBUS_CONN_BLE_INTERNAL_ERR;
137 ConnectionQueue *item = NULL;
138 ConnectionQueue *next = NULL;
139 SoftBusSysTime waitTime = {0};
140 int32_t ret = SoftBusGetTime(&waitTime);
141 CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, CONN_BLE, "softbus get time failed");
142 waitTime.sec += BLE_WAIT_TIME_SEC;
143
144 CONN_CHECK_AND_RETURN_RET_LOGE(msg != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, "msg is null");
145 CONN_CHECK_AND_RETURN_RET_LOGE(
146 SoftBusMutexLock(&g_bleQueueLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR, CONN_BLE, "lock fail!");
147 do {
148 if (GetMsg(g_innerQueue, msg, &isFull, MIDDLE_PRIORITY) == SOFTBUS_OK) {
149 status = SOFTBUS_OK;
150 break;
151 }
152 LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_bleQueueList, ConnectionQueue, node) {
153 ListDelete(&(item->node));
154 if (GetMsg(item, msg, &isFull, LOW_PRIORITY) == SOFTBUS_OK) {
155 ListTailInsert(&g_bleQueueList, &(item->node));
156 status = SOFTBUS_OK;
157 break;
158 }
159 DestroyBleQueue(item);
160 }
161 if (status == SOFTBUS_OK) {
162 break;
163 }
164 if (GetMsg(g_innerQueue, msg, &isFull, LOW_PRIORITY) == SOFTBUS_OK) {
165 status = SOFTBUS_OK;
166 break;
167 }
168 int32_t ret = SoftBusCondWait(&g_sendCond, &g_bleQueueLock, &waitTime);
169 if (ret != SOFTBUS_OK) {
170 if (ret == SOFTBUS_TIMOUT) {
171 CONN_LOGD(CONN_BLE, "BleSendCondWait 600s time out");
172 status = SOFTBUS_TIMOUT;
173 break;
174 }
175 CONN_LOGD(CONN_BLE, "BleSendCondWait fail");
176 status = SOFTBUS_CONN_COND_WAIT_FAIL;
177 break;
178 }
179 CONN_LOGD(CONN_BLE, "ble queue wakeup.");
180 } while (true);
181
182 if (isFull) {
183 (void)SoftBusCondBroadcast(&g_sendWaitCond);
184 }
185 (void)SoftBusMutexUnlock(&g_bleQueueLock);
186 return status;
187 }
188
ConnBleInitSendQueue(void)189 int32_t ConnBleInitSendQueue(void)
190 {
191 if (SoftBusMutexInit(&g_bleQueueLock, NULL) != 0) {
192 CONN_LOGE(CONN_INIT, "Mutex Init failed");
193 return SOFTBUS_NO_INIT;
194 }
195 if (SoftBusCondInit(&g_sendWaitCond) != SOFTBUS_OK) {
196 CONN_LOGE(CONN_INIT, "cond Init failed");
197 (void)SoftBusMutexDestroy(&g_bleQueueLock);
198 return SOFTBUS_NO_INIT;
199 }
200 if (SoftBusCondInit(&g_sendCond) != SOFTBUS_OK) {
201 (void)SoftBusMutexDestroy(&g_bleQueueLock);
202 (void)SoftBusCondDestroy(&g_sendWaitCond);
203 return SOFTBUS_NO_INIT;
204 }
205 g_innerQueue = CreateBleQueue(0);
206 if (g_innerQueue == NULL) {
207 CONN_LOGE(CONN_INIT, "BleQueueInit CreateBleQueue(0) failed");
208 (void)SoftBusMutexDestroy(&g_bleQueueLock);
209 (void)SoftBusCondDestroy(&g_sendWaitCond);
210 (void)SoftBusCondDestroy(&g_sendCond);
211 return SOFTBUS_NO_INIT;
212 }
213 return SOFTBUS_OK;
214 }
215
ConnBleDeinitSendQueue(void)216 void ConnBleDeinitSendQueue(void)
217 {
218 (void)SoftBusMutexDestroy(&g_bleQueueLock);
219 (void)SoftBusCondDestroy(&g_sendWaitCond);
220 (void)SoftBusCondDestroy(&g_sendCond);
221 DestroyBleQueue(g_innerQueue);
222 g_innerQueue = NULL;
223 }