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