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