• 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 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     {LOOP_TYPE_LANE, NULL},
492 };
493 
GetLooper(int type)494 SoftBusLooper *GetLooper(int type)
495 {
496     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
497     for (uint32_t i = 0; i < len; i++) {
498         if (g_loopConfig[i].type == type) {
499             return g_loopConfig[i].looper;
500         }
501     }
502     return NULL;
503 }
504 
SetLooper(int type,SoftBusLooper * looper)505 void SetLooper(int type, SoftBusLooper *looper)
506 {
507     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
508     for (uint32_t i = 0; i < len; i++) {
509         if (g_loopConfig[i].type == type) {
510             g_loopConfig[i].looper = looper;
511         }
512     }
513 }
514 
ReleaseLooper(const SoftBusLooper * looper)515 static void ReleaseLooper(const SoftBusLooper *looper)
516 {
517     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
518     for (uint32_t i = 0; i < len; i++) {
519         if (g_loopConfig[i].looper == looper) {
520             g_loopConfig[i].looper = NULL;
521             return;
522         }
523     }
524 }
525 
DestroyLooper(SoftBusLooper * looper)526 void DestroyLooper(SoftBusLooper *looper)
527 {
528     if (looper == NULL) {
529         COMM_LOGE(COMM_UTILS, "looper is null");
530         return;
531     }
532 
533     SoftBusLooperContext *context = looper->context;
534     if (context != NULL) {
535         (void)SoftBusMutexLock(&context->lock);
536 
537         COMM_LOGI(COMM_UTILS, "set stop 1. name=%{public}s", context->name);
538         context->stop = 1;
539 
540         SoftBusCondBroadcast(&context->cond);
541         (void)SoftBusMutexUnlock(&context->lock);
542         while (1) {
543             (void)SoftBusMutexLock(&context->lock);
544             COMM_LOGI(COMM_UTILS, "get. name=%{public}s, running=%{public}d", context->name, context->running);
545             if (context->running == 0) {
546                 (void)SoftBusMutexUnlock(&context->lock);
547                 break;
548             }
549             SoftBusCondWait(&context->condRunning, &context->lock, NULL);
550             (void)SoftBusMutexUnlock(&context->lock);
551         }
552         // release msg
553         ListNode *item = NULL;
554         ListNode *nextItem = NULL;
555         LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
556             SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
557             SoftBusMessage *msg = itemNode->msg;
558             FreeSoftBusMsg(msg);
559             ListDelete(&itemNode->node);
560             SoftBusFree(itemNode);
561         }
562         COMM_LOGI(COMM_UTILS, "destroy. name=%{public}s", context->name);
563         // destroy looper
564         SoftBusCondDestroy(&context->cond);
565         SoftBusCondDestroy(&context->condRunning);
566         SoftBusMutexDestroy(&context->lock);
567         SoftBusFree(context);
568         looper->context = NULL;
569     }
570     ReleaseLooper(looper);
571     SoftBusFree(looper);
572     if (g_looperCnt != 0) {
573         g_looperCnt--;
574     }
575 }
576 
LooperInit(void)577 int LooperInit(void)
578 {
579     SoftBusLooper *looper = CreateNewLooper("BusCenter_Lp");
580     if (!looper) {
581         COMM_LOGE(COMM_UTILS, "init BusCenter looper fail.");
582         return SOFTBUS_ERR;
583     }
584     SetLooper(LOOP_TYPE_DEFAULT, looper);
585 
586     SoftBusLooper *connLooper = CreateNewLooper("ReactorLink_Lp");
587     if (!connLooper) {
588         COMM_LOGE(COMM_UTILS, "init connection looper fail.");
589         return SOFTBUS_ERR;
590     }
591     SetLooper(LOOP_TYPE_CONN, connLooper);
592 
593     COMM_LOGD(COMM_UTILS, "init looper success.");
594     return SOFTBUS_OK;
595 }
596 
LooperDeinit(void)597 void LooperDeinit(void)
598 {
599     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
600     for (uint32_t i = 0; i < len; i++) {
601         if (g_loopConfig[i].looper == NULL) {
602             continue;
603         }
604         (void)SoftBusMutexLock(&(g_loopConfig[i].looper->context->lock));
605         if (g_isThreadStarted == 0) {
606             g_isNeedDestroy = 1;
607             (void)SoftBusMutexUnlock(&(g_loopConfig[i].looper->context->lock));
608             return;
609         }
610         (void)SoftBusMutexUnlock(&(g_loopConfig[i].looper->context->lock));
611         DestroyLooper(g_loopConfig[i].looper);
612     }
613 }
614