1 /*
2 * Copyright (c) 2021-2024 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 "message_handler.h"
17
18 #include <securec.h>
19
20 #include "common_list.h"
21 #include "comm_log.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_adapter_thread.h"
24 #include "softbus_def.h"
25 #include "softbus_error_code.h"
26
27 #define LOOP_NAME_LEN 16
28 #define TIME_THOUSANDS_MULTIPLIER 1000LL
29 #define MAX_LOOPER_CNT 30U
30 #define MAX_LOOPER_PRINT_CNT 64
31
32 static int8_t g_isNeedDestroy = 0;
33 static int8_t g_isThreadStarted = 0;
34 static uint32_t g_looperCnt = 0;
35
36 typedef struct {
37 SoftBusMessage *msg;
38 ListNode node;
39 } SoftBusMessageNode;
40
41 struct SoftBusLooperContext {
42 ListNode msgHead;
43 char name[LOOP_NAME_LEN];
44 volatile unsigned char stop; // destroys looper, stop =1, and running =0
45 volatile unsigned char running;
46 SoftBusMessage *currentMsg;
47 unsigned int msgSize;
48 SoftBusMutex lock;
49 SoftBusMutexAttr attr;
50 SoftBusCond cond;
51 SoftBusCond condRunning;
52 };
53
UptimeMicros(void)54 static int64_t UptimeMicros(void)
55 {
56 SoftBusSysTime t;
57 t.sec = 0;
58 t.usec = 0;
59 SoftBusGetTime(&t);
60 int64_t when = t.sec * TIME_THOUSANDS_MULTIPLIER * TIME_THOUSANDS_MULTIPLIER + t.usec;
61 return when;
62 }
63
FreeSoftBusMsg(SoftBusMessage * msg)64 NO_SANITIZE("cfi") static void FreeSoftBusMsg(SoftBusMessage *msg)
65 {
66 if (msg->FreeMessage == NULL) {
67 SoftBusFree(msg);
68 } else {
69 msg->FreeMessage(msg);
70 }
71 }
72
MallocMessage(void)73 SoftBusMessage *MallocMessage(void)
74 {
75 SoftBusMessage *msg = (SoftBusMessage *)SoftBusCalloc(sizeof(SoftBusMessage));
76 if (msg == NULL) {
77 COMM_LOGE(COMM_UTILS, "malloc SoftBusMessage failed");
78 return NULL;
79 }
80 return msg;
81 }
82
FreeMessage(SoftBusMessage * msg)83 void FreeMessage(SoftBusMessage *msg)
84 {
85 if (msg != NULL) {
86 FreeSoftBusMsg(msg);
87 }
88 }
89
LoopTask(void * arg)90 static void *LoopTask(void *arg)
91 {
92 SoftBusLooper *looper = arg;
93 SoftBusLooperContext *context = looper->context;
94 if (context == NULL) {
95 COMM_LOGE(COMM_UTILS, "loop context is NULL");
96 return NULL;
97 }
98
99 COMM_LOGD(COMM_UTILS, "LoopTask running. name=%{public}s", context->name);
100
101 if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
102 COMM_LOGE(COMM_UTILS, "lock failed");
103 return NULL;
104 }
105 context->running = 1;
106 g_isThreadStarted = 1;
107 (void)SoftBusMutexUnlock(&context->lock);
108
109 for (;;) {
110 if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
111 return NULL;
112 }
113 // wait
114 if (context->stop == 1) {
115 COMM_LOGI(COMM_UTILS, "LoopTask stop is 1. name=%{public}s", context->name);
116 (void)SoftBusMutexUnlock(&context->lock);
117 break;
118 }
119
120 if (g_isNeedDestroy == 1) {
121 (void)SoftBusMutexUnlock(&context->lock);
122 break;
123 }
124
125 if (IsListEmpty(&context->msgHead)) {
126 COMM_LOGD(COMM_UTILS, "LoopTask wait msg list empty. name=%{public}s", context->name);
127 SoftBusCondWait(&context->cond, &context->lock, NULL);
128 (void)SoftBusMutexUnlock(&context->lock);
129 continue;
130 }
131
132 int64_t now = UptimeMicros();
133 ListNode *item = context->msgHead.next;
134 SoftBusMessage *msg = NULL;
135 SoftBusMessageNode *itemNode = CONTAINER_OF(item, SoftBusMessageNode, node);
136 int64_t time = itemNode->msg->time;
137 if (now >= time) {
138 msg = itemNode->msg;
139 ListDelete(item);
140 SoftBusFree(itemNode);
141 context->msgSize--;
142 if (looper->dumpable) {
143 COMM_LOGD(COMM_UTILS,
144 "LoopTask get message. name=%{public}s, handle=%{public}s, what=%{public}" PRId32 ", arg1=%{public}"
145 PRIu64 ", msgSize=%{public}u, time=%{public}" PRId64,
146 context->name, msg->handler ? msg->handler->name : "null", msg->what, msg->arg1, context->msgSize,
147 msg->time);
148 }
149 } else {
150 SoftBusSysTime tv;
151 tv.sec = time / TIME_THOUSANDS_MULTIPLIER / TIME_THOUSANDS_MULTIPLIER;
152 tv.usec = time % (TIME_THOUSANDS_MULTIPLIER * TIME_THOUSANDS_MULTIPLIER);
153 SoftBusCondWait(&context->cond, &context->lock, &tv);
154 }
155
156 if (msg == NULL) {
157 (void)SoftBusMutexUnlock(&context->lock);
158 continue;
159 }
160 context->currentMsg = msg;
161 if (looper->dumpable) {
162 COMM_LOGD(COMM_UTILS,
163 "LoopTask HandleMessage message. name=%{public}s, handle=%{public}s, what=%{public}" PRId32,
164 context->name, msg->handler ? msg->handler->name : "null", msg->what);
165 }
166 (void)SoftBusMutexUnlock(&context->lock);
167
168 if (msg->handler != NULL && msg->handler->HandleMessage != NULL) {
169 msg->handler->HandleMessage(msg);
170 }
171
172 (void)SoftBusMutexLock(&context->lock);
173 if (looper->dumpable) {
174 // Don`t print msg->handler, msg->handler->HandleMessage() may remove handler,
175 // so msg->handler maybe invalid pointer
176 COMM_LOGD(COMM_UTILS,
177 "LoopTask after HandleMessage message. "
178 "name=%{public}s, what=%{public}" PRId32 ", arg1=%{public}" PRIu64,
179 context->name, msg->what, msg->arg1);
180 }
181 FreeSoftBusMsg(msg);
182 context->currentMsg = NULL;
183 (void)SoftBusMutexUnlock(&context->lock);
184 }
185 (void)SoftBusMutexLock(&context->lock);
186 context->running = 0;
187 COMM_LOGI(COMM_UTILS, "LoopTask running is 0. name=%{public}s", context->name);
188 SoftBusCondBroadcast(&context->cond);
189 SoftBusCondBroadcast(&context->condRunning);
190 (void)SoftBusMutexUnlock(&context->lock);
191 if (g_isNeedDestroy == 1) {
192 LooperDeinit();
193 }
194 return NULL;
195 }
196
StartNewLooperThread(SoftBusLooper * looper)197 static int StartNewLooperThread(SoftBusLooper *looper)
198 {
199 #if defined(__aarch64__) || defined(__x86_64__) || (defined(__riscv) && (__riscv_xlen == 64))
200 #define MAINLOOP_STACK_SIZE (2 * 1024 * 1024)
201 #else
202 #ifdef ASAN_BUILD
203 #define MAINLOOP_STACK_SIZE 10240
204 #else
205 #define MAINLOOP_STACK_SIZE (32 * 1024)
206 #endif
207 #endif
208 SoftBusThreadAttr threadAttr;
209 SoftBusThread tid;
210 SoftBusThreadAttrInit(&threadAttr);
211 threadAttr.taskName = looper->context->name;
212 threadAttr.stackSize = MAINLOOP_STACK_SIZE;
213 int32_t ret = SoftBusThreadCreate(&tid, &threadAttr, LoopTask, looper);
214 if (ret != SOFTBUS_OK) {
215 COMM_LOGE(COMM_UTILS, "Init DeathProcTask ThreadAttr failed");
216 return SOFTBUS_ERR;
217 }
218
219 COMM_LOGI(COMM_UTILS, "loop thread creating. name=%{public}s, tid=%{public}d", looper->context->name,
220 (int)(uintptr_t)tid);
221 return SOFTBUS_OK;
222 }
223
DumpLooperLocked(const SoftBusLooperContext * context,const SoftBusHandler * handler)224 static void DumpLooperLocked(const SoftBusLooperContext *context, const SoftBusHandler *handler)
225 {
226 int32_t i = 0;
227 ListNode *item = NULL;
228 LIST_FOR_EACH(item, &context->msgHead) {
229 SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
230 SoftBusMessage *msg = itemNode->msg;
231 if (i > MAX_LOOPER_PRINT_CNT) {
232 COMM_LOGW(COMM_UTILS, "many messages left unprocessed, msgSize=%{public}u",
233 context->msgSize);
234 break;
235 }
236 if (handler != NULL && handler != msg->handler) {
237 continue;
238 }
239 COMM_LOGD(COMM_UTILS,
240 "DumpLooper. i=%{public}d, handler=%{public}s, what=%{public}" PRId32 ", arg1=%{public}" PRIu64 ", "
241 "arg2=%{public}" PRIu64 ", time=%{public}" PRId64,
242 i, msg->handler->name, msg->what, msg->arg1, msg->arg2, msg->time);
243
244 i++;
245 }
246 }
247
DumpLooper(const SoftBusLooper * looper)248 void DumpLooper(const SoftBusLooper *looper)
249 {
250 if (looper == NULL) {
251 return;
252 }
253 SoftBusLooperContext *context = looper->context;
254 if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
255 return;
256 }
257 if (looper->dumpable) {
258 DumpLooperLocked(context, NULL);
259 }
260 (void)SoftBusMutexUnlock(&context->lock);
261 }
262
PostMessageAtTimeParamVerify(const SoftBusLooper * looper,SoftBusMessage * msgPost)263 static int32_t PostMessageAtTimeParamVerify(const SoftBusLooper *looper, SoftBusMessage *msgPost)
264 {
265 if (msgPost == NULL || msgPost->handler == NULL) {
266 COMM_LOGE(COMM_UTILS, "the msgPost param is null.");
267 return SOFTBUS_INVALID_PARAM;
268 }
269
270 if (looper == NULL || looper->context == NULL) {
271 COMM_LOGE(COMM_UTILS, "the looper param is null.");
272 return SOFTBUS_INVALID_PARAM;
273 }
274
275 if (SoftBusMutexLock(&looper->context->lock) != SOFTBUS_OK) {
276 COMM_LOGE(COMM_UTILS, "lock looper context failed.");
277 return SOFTBUS_LOCK_ERR;
278 }
279
280 if (looper->dumpable) {
281 COMM_LOGD(COMM_UTILS, "PostMessageAtTime name=%{public}s, what=%{public}d, time=%{public}" PRId64 "us",
282 looper->context->name, msgPost->what, msgPost->time);
283 }
284
285 (void)SoftBusMutexUnlock(&looper->context->lock);
286 return SOFTBUS_OK;
287 }
288
PostMessageAtTime(const SoftBusLooper * looper,SoftBusMessage * msgPost)289 static void PostMessageAtTime(const SoftBusLooper *looper, SoftBusMessage *msgPost)
290 {
291 if (PostMessageAtTimeParamVerify(looper, msgPost) != SOFTBUS_OK) {
292 FreeSoftBusMsg(msgPost);
293 return;
294 }
295
296 SoftBusMessageNode *newNode = (SoftBusMessageNode *)SoftBusCalloc(sizeof(SoftBusMessageNode));
297 if (newNode == NULL) {
298 COMM_LOGE(COMM_UTILS, "message node malloc failed.");
299 FreeSoftBusMsg(msgPost);
300 return;
301 }
302 ListInit(&newNode->node);
303 newNode->msg = msgPost;
304 SoftBusLooperContext *context = looper->context;
305 if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
306 SoftBusFree(newNode);
307 FreeSoftBusMsg(msgPost);
308 return;
309 }
310 if (context->stop == 1) {
311 SoftBusFree(newNode);
312 FreeSoftBusMsg(msgPost);
313 (void)SoftBusMutexUnlock(&context->lock);
314 COMM_LOGE(COMM_UTILS, "PostMessageAtTime stop is 1. name=%{public}s, running=%{public}d",
315 context->name, context->running);
316 return;
317 }
318 ListNode *item = NULL;
319 ListNode *nextItem = NULL;
320 bool insert = false;
321 LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
322 SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
323 SoftBusMessage *msg = itemNode->msg;
324 if (msg->time > msgPost->time) {
325 ListTailInsert(item, &(newNode->node));
326 insert = true;
327 break;
328 }
329 }
330 if (!insert) {
331 ListTailInsert(&(context->msgHead), &(newNode->node));
332 }
333 context->msgSize++;
334 if (looper->dumpable) {
335 COMM_LOGD(COMM_UTILS, "PostMessageAtTime insert. name=%{public}s", context->name);
336 DumpLooperLocked(context, msgPost->handler);
337 }
338 SoftBusCondBroadcast(&context->cond);
339 (void)SoftBusMutexUnlock(&context->lock);
340 }
341
LooperPostMessage(const SoftBusLooper * looper,SoftBusMessage * msg)342 static void LooperPostMessage(const SoftBusLooper *looper, SoftBusMessage *msg)
343 {
344 if (msg == NULL) {
345 COMM_LOGE(COMM_UTILS, "LooperPostMessage with nullmsg");
346 return;
347 }
348 if (looper == NULL) {
349 COMM_LOGE(COMM_UTILS, "LooperPostMessage with nulllooper");
350 return;
351 }
352 msg->time = UptimeMicros();
353 PostMessageAtTime(looper, msg);
354 }
355
LooperPostMessageDelay(const SoftBusLooper * looper,SoftBusMessage * msg,uint64_t delayMillis)356 static void LooperPostMessageDelay(const SoftBusLooper *looper, SoftBusMessage *msg, uint64_t delayMillis)
357 {
358 if (msg == NULL) {
359 COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nullmsg");
360 return;
361 }
362 if (looper == NULL) {
363 COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nulllooper");
364 return;
365 }
366 msg->time = UptimeMicros() + (int64_t)delayMillis * TIME_THOUSANDS_MULTIPLIER;
367 PostMessageAtTime(looper, msg);
368 }
369
WhatRemoveFunc(const SoftBusMessage * msg,void * args)370 static int WhatRemoveFunc(const SoftBusMessage *msg, void *args)
371 {
372 int32_t what = (int32_t)(intptr_t)args;
373 if (msg->what == what) {
374 return 0;
375 }
376 return 1;
377 }
378
LoopRemoveMessageCustom(const SoftBusLooper * looper,const SoftBusHandler * handler,int (* customFunc)(const SoftBusMessage *,void *),void * args)379 static void LoopRemoveMessageCustom(const SoftBusLooper *looper, const SoftBusHandler *handler,
380 int (*customFunc)(const SoftBusMessage*, void*), void *args)
381 {
382 SoftBusLooperContext *context = looper->context;
383 if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
384 return;
385 }
386 if (context->running == 0 || context->stop == 1) {
387 (void)SoftBusMutexUnlock(&context->lock);
388 return;
389 }
390 ListNode *item = NULL;
391 ListNode *nextItem = NULL;
392 LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
393 SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
394 SoftBusMessage *msg = itemNode->msg;
395 if (msg->handler == handler && customFunc(msg, args) == 0) {
396 COMM_LOGD(COMM_UTILS,
397 "LooperRemoveMessage. name=%{public}s, handler=%{public}s, what=%{public}d, arg1=%{public}" PRIu64 ", "
398 "time=%{public}" PRId64,
399 context->name, handler->name, msg->what, msg->arg1, msg->time);
400 FreeSoftBusMsg(msg);
401 ListDelete(&itemNode->node);
402 SoftBusFree(itemNode);
403 context->msgSize--;
404 }
405 }
406 (void)SoftBusMutexUnlock(&context->lock);
407 }
408
LooperRemoveMessage(const SoftBusLooper * looper,const SoftBusHandler * handler,int32_t what)409 static void LooperRemoveMessage(const SoftBusLooper *looper, const SoftBusHandler *handler, int32_t what)
410 {
411 LoopRemoveMessageCustom(looper, handler, WhatRemoveFunc, (void*)(intptr_t)what);
412 }
413
SetLooperDumpable(SoftBusLooper * looper,bool dumpable)414 void SetLooperDumpable(SoftBusLooper *looper, bool dumpable)
415 {
416 if (looper == NULL || looper->context == NULL) {
417 COMM_LOGE(COMM_UTILS, "looper param is invalid");
418 return;
419 }
420
421 if (SoftBusMutexLock(&looper->context->lock) != SOFTBUS_OK) {
422 COMM_LOGE(COMM_UTILS, "lock looper context failed.");
423 return;
424 }
425
426 looper->dumpable = dumpable;
427 (void)SoftBusMutexUnlock(&looper->context->lock);
428 }
429
CreateNewLooper(const char * name)430 SoftBusLooper *CreateNewLooper(const char *name)
431 {
432 if (g_looperCnt >= MAX_LOOPER_CNT) {
433 COMM_LOGE(COMM_UTILS, "Looper exceeds the maximum, count=%{public}u,", g_looperCnt);
434 return NULL;
435 }
436 SoftBusLooper *looper = (SoftBusLooper *)SoftBusCalloc(sizeof(SoftBusLooper));
437 if (looper == NULL) {
438 COMM_LOGE(COMM_UTILS, "Looper SoftBusCalloc fail");
439 return NULL;
440 }
441
442 SoftBusLooperContext *context = (SoftBusLooperContext *)SoftBusCalloc(sizeof(SoftBusLooperContext));
443 if (context == NULL) {
444 COMM_LOGE(COMM_UTILS, "Looper SoftBusCalloc fail");
445 SoftBusFree(looper);
446 return NULL;
447 }
448 if (memcpy_s(context->name, sizeof(context->name), name, strlen(name)) != EOK) {
449 COMM_LOGE(COMM_UTILS, "memcpy_s fail");
450 SoftBusFree(looper);
451 SoftBusFree(context);
452 return NULL;
453 }
454 ListInit(&context->msgHead);
455 // init context
456 SoftBusMutexInit(&context->lock, NULL);
457 SoftBusCondInit(&context->cond);
458 SoftBusCondInit(&context->condRunning);
459 // init looper
460 looper->context = context;
461 looper->dumpable = true;
462 looper->PostMessage = LooperPostMessage;
463 looper->PostMessageDelay = LooperPostMessageDelay;
464 looper->RemoveMessage = LooperRemoveMessage;
465 looper->RemoveMessageCustom = LoopRemoveMessageCustom;
466 int ret = StartNewLooperThread(looper);
467 if (ret != 0) {
468 COMM_LOGE(COMM_UTILS, "start fail");
469 SoftBusFree(looper);
470 SoftBusFree(context);
471 return NULL;
472 }
473 g_looperCnt++;
474 COMM_LOGD(COMM_UTILS, "wait looper start ok. name=%{public}s", context->name);
475 return looper;
476 }
477
478 struct LoopConfigItem {
479 int type;
480 SoftBusLooper *looper;
481 };
482
483 static struct LoopConfigItem g_loopConfig[] = {
484 {LOOP_TYPE_DEFAULT, NULL},
485 {LOOP_TYPE_CONN, NULL},
486 {LOOP_TYPE_LNN, NULL}
487 };
488
GetLooper(int type)489 SoftBusLooper *GetLooper(int type)
490 {
491 uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
492 for (uint32_t i = 0; i < len; i++) {
493 if (g_loopConfig[i].type == type) {
494 return g_loopConfig[i].looper;
495 }
496 }
497 return NULL;
498 }
499
SetLooper(int type,SoftBusLooper * looper)500 void SetLooper(int type, SoftBusLooper *looper)
501 {
502 uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
503 for (uint32_t i = 0; i < len; i++) {
504 if (g_loopConfig[i].type == type) {
505 g_loopConfig[i].looper = looper;
506 }
507 }
508 }
509
ReleaseLooper(const SoftBusLooper * looper)510 static void ReleaseLooper(const SoftBusLooper *looper)
511 {
512 uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
513 for (uint32_t i = 0; i < len; i++) {
514 if (g_loopConfig[i].looper == looper) {
515 g_loopConfig[i].looper = NULL;
516 return;
517 }
518 }
519 }
520
DestroyLooper(SoftBusLooper * looper)521 void DestroyLooper(SoftBusLooper *looper)
522 {
523 if (looper == NULL) {
524 COMM_LOGE(COMM_UTILS, "looper is null");
525 return;
526 }
527
528 SoftBusLooperContext *context = looper->context;
529 if (context != NULL) {
530 (void)SoftBusMutexLock(&context->lock);
531
532 COMM_LOGI(COMM_UTILS, "set stop 1. name=%{public}s", context->name);
533 context->stop = 1;
534
535 SoftBusCondBroadcast(&context->cond);
536 (void)SoftBusMutexUnlock(&context->lock);
537 while (1) {
538 (void)SoftBusMutexLock(&context->lock);
539 COMM_LOGI(COMM_UTILS, "get. name=%{public}s, running=%{public}d", context->name, context->running);
540 if (context->running == 0) {
541 (void)SoftBusMutexUnlock(&context->lock);
542 break;
543 }
544 SoftBusCondWait(&context->condRunning, &context->lock, NULL);
545 (void)SoftBusMutexUnlock(&context->lock);
546 }
547 // release msg
548 ListNode *item = NULL;
549 ListNode *nextItem = NULL;
550 LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
551 SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
552 SoftBusMessage *msg = itemNode->msg;
553 FreeSoftBusMsg(msg);
554 ListDelete(&itemNode->node);
555 SoftBusFree(itemNode);
556 }
557 COMM_LOGI(COMM_UTILS, "destroy. name=%{public}s", context->name);
558 // destroy looper
559 SoftBusCondDestroy(&context->cond);
560 SoftBusCondDestroy(&context->condRunning);
561 SoftBusMutexDestroy(&context->lock);
562 SoftBusFree(context);
563 looper->context = NULL;
564 }
565 ReleaseLooper(looper);
566 SoftBusFree(looper);
567 if (g_looperCnt != 0) {
568 g_looperCnt--;
569 }
570 }
571
LooperInit(void)572 int LooperInit(void)
573 {
574 SoftBusLooper *looper = CreateNewLooper("BusCenter_Lp");
575 if (!looper) {
576 COMM_LOGE(COMM_UTILS, "init BusCenter looper fail.");
577 return SOFTBUS_ERR;
578 }
579 SetLooper(LOOP_TYPE_DEFAULT, looper);
580
581 SoftBusLooper *connLooper = CreateNewLooper("ReactorLink_Lp");
582 if (!connLooper) {
583 COMM_LOGE(COMM_UTILS, "init connection looper fail.");
584 return SOFTBUS_ERR;
585 }
586 SetLooper(LOOP_TYPE_CONN, connLooper);
587
588 COMM_LOGD(COMM_UTILS, "init looper success.");
589 return SOFTBUS_OK;
590 }
591
LooperDeinit(void)592 void LooperDeinit(void)
593 {
594 uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
595 for (uint32_t i = 0; i < len; i++) {
596 if (g_loopConfig[i].looper == NULL) {
597 continue;
598 }
599 (void)SoftBusMutexLock(&(g_loopConfig[i].looper->context->lock));
600 if (g_isThreadStarted == 0) {
601 g_isNeedDestroy = 1;
602 (void)SoftBusMutexUnlock(&(g_loopConfig[i].looper->context->lock));
603 return;
604 }
605 (void)SoftBusMutexUnlock(&(g_loopConfig[i].looper->context->lock));
606 DestroyLooper(g_loopConfig[i].looper);
607 }
608 }
609