• 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 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         (void)SoftBusMutexUnlock(&context->lock);
162         if (looper->dumpable) {
163             COMM_LOGD(COMM_UTILS,
164                 "LoopTask HandleMessage message. name=%{public}s, handle=%{public}s, what=%{public}" PRId32,
165                 context->name, msg->handler ? msg->handler->name : "null", msg->what);
166         }
167 
168         if (msg->handler != NULL && msg->handler->HandleMessage != NULL) {
169             msg->handler->HandleMessage(msg);
170         }
171         if (looper->dumpable) {
172             // Don`t print msg->handler, msg->handler->HandleMessage() may remove handler,
173             // so msg->handler maybe invalid pointer
174             COMM_LOGD(COMM_UTILS,
175                 "LoopTask after HandleMessage message. "
176                 "name=%{public}s, what=%{public}" PRId32 ", arg1=%{public}" PRIu64,
177                 context->name, msg->what, msg->arg1);
178         }
179         (void)SoftBusMutexLock(&context->lock);
180         FreeSoftBusMsg(msg);
181         context->currentMsg = NULL;
182         (void)SoftBusMutexUnlock(&context->lock);
183     }
184     (void)SoftBusMutexLock(&context->lock);
185     context->running = 0;
186     COMM_LOGI(COMM_UTILS, "LoopTask running is 0. name=%{public}s", context->name);
187     SoftBusCondBroadcast(&context->cond);
188     SoftBusCondBroadcast(&context->condRunning);
189     (void)SoftBusMutexUnlock(&context->lock);
190     if (g_isNeedDestroy == 1) {
191         LooperDeinit();
192     }
193     return NULL;
194 }
195 
StartNewLooperThread(SoftBusLooper * looper)196 static int StartNewLooperThread(SoftBusLooper *looper)
197 {
198 #if (defined(__aarch64__) || defined(__x86_64__))
199 #define MAINLOOP_STACK_SIZE (2 * 1024 * 1024)
200 #else
201 #ifdef ASAN_BUILD
202 #define MAINLOOP_STACK_SIZE 10240
203 #else
204 #define MAINLOOP_STACK_SIZE (32 * 1024)
205 #endif
206 #endif
207     SoftBusThreadAttr threadAttr;
208     SoftBusThread tid;
209     SoftBusThreadAttrInit(&threadAttr);
210 
211     threadAttr.stackSize = MAINLOOP_STACK_SIZE;
212     int32_t ret = SoftBusThreadCreate(&tid, &threadAttr, LoopTask, looper);
213     if (ret != SOFTBUS_OK) {
214         COMM_LOGE(COMM_UTILS, "Init DeathProcTask ThreadAttr failed");
215         return -1;
216     }
217 
218     COMM_LOGI(COMM_UTILS, "loop thread creating. name=%{public}s, tid=%{public}d", looper->context->name,
219         (int)(uintptr_t)tid);
220     return 0;
221 }
222 
DumpLooperLocked(const SoftBusLooperContext * context,const SoftBusHandler * handler)223 static void DumpLooperLocked(const SoftBusLooperContext *context, const SoftBusHandler *handler)
224 {
225     int32_t i = 0;
226     ListNode *item = NULL;
227     LIST_FOR_EACH(item, &context->msgHead) {
228         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
229         SoftBusMessage *msg = itemNode->msg;
230         if (i > MAX_LOOPER_PRINT_CNT) {
231             COMM_LOGW(COMM_UTILS, "many messages left unprocessed, msgSize=%{public}u",
232                 context->msgSize);
233             break;
234         }
235         if (handler != NULL && handler != msg->handler) {
236             continue;
237         }
238         COMM_LOGD(COMM_UTILS,
239             "DumpLooper. i=%{public}d, handler=%{public}s, what=%{public}" PRId32 ", arg1=%{public}" PRIu64 ", "
240             "arg2=%{public}" PRIu64 ", time=%{public}" PRId64,
241             i, msg->handler->name, msg->what, msg->arg1, msg->arg2, msg->time);
242 
243         i++;
244     }
245 }
246 
DumpLooper(const SoftBusLooper * looper)247 void DumpLooper(const SoftBusLooper *looper)
248 {
249     if (looper == NULL) {
250         return;
251     }
252     SoftBusLooperContext *context = looper->context;
253     if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
254         return;
255     }
256     if (looper->dumpable) {
257         DumpLooperLocked(context, NULL);
258     }
259     (void)SoftBusMutexUnlock(&context->lock);
260 }
261 
PostMessageAtTimeParamVerify(const SoftBusLooper * looper,SoftBusMessage * msgPost)262 static int32_t PostMessageAtTimeParamVerify(const SoftBusLooper *looper, SoftBusMessage *msgPost)
263 {
264     if (msgPost == NULL) {
265         COMM_LOGE(COMM_UTILS, "the msgPost param is null.");
266         return SOFTBUS_INVALID_PARAM;
267     }
268 
269     if (looper == NULL) {
270         COMM_LOGE(COMM_UTILS, "the looper param is null.");
271         return SOFTBUS_INVALID_PARAM;
272     }
273 
274     if (looper->dumpable) {
275         COMM_LOGD(COMM_UTILS, "PostMessageAtTime name=%{public}s, what=%{public}d, time=%{public}" PRId64 "us",
276             looper->context->name, msgPost->what, msgPost->time);
277     }
278 
279     if (msgPost->handler == NULL) {
280         COMM_LOGE(COMM_UTILS, "[%s] msg handler is null", looper->context->name);
281         return SOFTBUS_ERR;
282     }
283 
284     return SOFTBUS_OK;
285 }
286 
PostMessageAtTime(const SoftBusLooper * looper,SoftBusMessage * msgPost)287 static void PostMessageAtTime(const SoftBusLooper *looper, SoftBusMessage *msgPost)
288 {
289     if (PostMessageAtTimeParamVerify(looper, msgPost) != SOFTBUS_OK) {
290         FreeSoftBusMsg(msgPost);
291         return;
292     }
293 
294     SoftBusMessageNode *newNode = (SoftBusMessageNode *)SoftBusCalloc(sizeof(SoftBusMessageNode));
295     if (newNode == NULL) {
296         COMM_LOGE(COMM_UTILS, "message node malloc failed.");
297         FreeSoftBusMsg(msgPost);
298         return;
299     }
300     ListInit(&newNode->node);
301     newNode->msg = msgPost;
302     SoftBusLooperContext *context = looper->context;
303     if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
304         SoftBusFree(newNode);
305         FreeSoftBusMsg(msgPost);
306         return;
307     }
308     if (context->stop == 1) {
309         SoftBusFree(newNode);
310         FreeSoftBusMsg(msgPost);
311         (void)SoftBusMutexUnlock(&context->lock);
312         COMM_LOGE(COMM_UTILS, "PostMessageAtTime stop is 1. name=%{public}s, running=%{public}d",
313             context->name, context->running);
314         return;
315     }
316     ListNode *item = NULL;
317     ListNode *nextItem = NULL;
318     bool insert = false;
319     LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
320         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
321         SoftBusMessage *msg = itemNode->msg;
322         if (msg->time > msgPost->time) {
323             ListTailInsert(item, &(newNode->node));
324             insert = true;
325             break;
326         }
327     }
328     if (!insert) {
329         ListTailInsert(&(context->msgHead), &(newNode->node));
330     }
331     context->msgSize++;
332     if (looper->dumpable) {
333         COMM_LOGD(COMM_UTILS, "PostMessageAtTime insert. name=%{public}s", context->name);
334         DumpLooperLocked(context, msgPost->handler);
335     }
336     SoftBusCondBroadcast(&context->cond);
337     (void)SoftBusMutexUnlock(&context->lock);
338 }
339 
LooperPostMessage(const SoftBusLooper * looper,SoftBusMessage * msg)340 static void LooperPostMessage(const SoftBusLooper *looper, SoftBusMessage *msg)
341 {
342     if (msg == NULL) {
343         COMM_LOGE(COMM_UTILS, "LooperPostMessage with nullmsg");
344         return;
345     }
346     if (looper == NULL) {
347         COMM_LOGE(COMM_UTILS, "LooperPostMessage with nulllooper");
348         return;
349     }
350     msg->time = UptimeMicros();
351     PostMessageAtTime(looper, msg);
352 }
353 
LooperPostMessageDelay(const SoftBusLooper * looper,SoftBusMessage * msg,uint64_t delayMillis)354 static void LooperPostMessageDelay(const SoftBusLooper *looper, SoftBusMessage *msg, uint64_t delayMillis)
355 {
356     if (msg == NULL) {
357         COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nullmsg");
358         return;
359     }
360     if (looper == NULL) {
361         COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nulllooper");
362         return;
363     }
364     msg->time = UptimeMicros() + (int64_t)delayMillis * TIME_THOUSANDS_MULTIPLIER;
365     PostMessageAtTime(looper, msg);
366 }
367 
WhatRemoveFunc(const SoftBusMessage * msg,void * args)368 static int WhatRemoveFunc(const SoftBusMessage *msg, void *args)
369 {
370     int32_t what = (int32_t)(intptr_t)args;
371     if (msg->what == what) {
372         return 0;
373     }
374     return 1;
375 }
376 
LoopRemoveMessageCustom(const SoftBusLooper * looper,const SoftBusHandler * handler,int (* customFunc)(const SoftBusMessage *,void *),void * args)377 static void LoopRemoveMessageCustom(const SoftBusLooper *looper, const SoftBusHandler *handler,
378     int (*customFunc)(const SoftBusMessage*, void*), void *args)
379 {
380     SoftBusLooperContext *context = looper->context;
381     if (SoftBusMutexLock(&context->lock) != SOFTBUS_OK) {
382         return;
383     }
384     if (context->running == 0 || context->stop == 1) {
385         (void)SoftBusMutexUnlock(&context->lock);
386         return;
387     }
388     ListNode *item = NULL;
389     ListNode *nextItem = NULL;
390     LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
391         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
392         SoftBusMessage *msg = itemNode->msg;
393         if (msg->handler == handler && customFunc(msg, args) == 0) {
394             COMM_LOGD(COMM_UTILS,
395                 "LooperRemoveMessage. name=%{public}s, handler=%{public}s, what=%{public}d, arg1=%{public}" PRIu64 ", "
396                 "time=%{public}" PRId64,
397                 context->name, handler->name, msg->what, msg->arg1, msg->time);
398             FreeSoftBusMsg(msg);
399             ListDelete(&itemNode->node);
400             SoftBusFree(itemNode);
401             context->msgSize--;
402         }
403     }
404     (void)SoftBusMutexUnlock(&context->lock);
405 }
406 
LooperRemoveMessage(const SoftBusLooper * looper,const SoftBusHandler * handler,int32_t what)407 static void LooperRemoveMessage(const SoftBusLooper *looper, const SoftBusHandler *handler, int32_t what)
408 {
409     LoopRemoveMessageCustom(looper, handler, WhatRemoveFunc, (void*)(intptr_t)what);
410 }
411 
SetLooperDumpable(SoftBusLooper * loop,bool dumpable)412 void SetLooperDumpable(SoftBusLooper *loop, bool dumpable)
413 {
414     if (loop == NULL) {
415         COMM_LOGE(COMM_UTILS, "loop is null");
416         return;
417     }
418     loop->dumpable = dumpable;
419 }
420 
CreateNewLooper(const char * name)421 SoftBusLooper *CreateNewLooper(const char *name)
422 {
423     if (g_looperCnt >= MAX_LOOPER_CNT) {
424         COMM_LOGE(COMM_UTILS, "Looper exceeds the maximum, count=%{public}u,", g_looperCnt);
425         return NULL;
426     }
427     SoftBusLooper *looper = (SoftBusLooper *)SoftBusCalloc(sizeof(SoftBusLooper));
428     if (looper == NULL) {
429         COMM_LOGE(COMM_UTILS, "Looper SoftBusCalloc fail");
430         return NULL;
431     }
432 
433     SoftBusLooperContext *context = (SoftBusLooperContext *)SoftBusCalloc(sizeof(SoftBusLooperContext));
434     if (context == NULL) {
435         COMM_LOGE(COMM_UTILS, "Looper SoftBusCalloc fail");
436         SoftBusFree(looper);
437         return NULL;
438     }
439 
440     if (memcpy_s(context->name, sizeof(context->name), name, strlen(name)) != EOK) {
441         COMM_LOGE(COMM_UTILS, "memcpy_s fail");
442         SoftBusFree(looper);
443         SoftBusFree(context);
444         return NULL;
445     }
446     ListInit(&context->msgHead);
447     // init context
448     SoftBusMutexInit(&context->lock, NULL);
449     SoftBusCondInit(&context->cond);
450     SoftBusCondInit(&context->condRunning);
451     // init looper
452     looper->context = context;
453     looper->dumpable = true;
454     looper->PostMessage = LooperPostMessage;
455     looper->PostMessageDelay = LooperPostMessageDelay;
456     looper->RemoveMessage = LooperRemoveMessage;
457     looper->RemoveMessageCustom = LoopRemoveMessageCustom;
458     int ret = StartNewLooperThread(looper);
459     if (ret != 0) {
460         COMM_LOGE(COMM_UTILS, "start fail");
461         SoftBusFree(looper);
462         SoftBusFree(context);
463         return NULL;
464     }
465     g_looperCnt++;
466     COMM_LOGD(COMM_UTILS, "wait looper start ok. name=%{public}s", context->name);
467     return looper;
468 }
469 
470 struct LoopConfigItem {
471     int type;
472     SoftBusLooper *looper;
473 };
474 
475 static struct LoopConfigItem g_loopConfig[] = {
476     {LOOP_TYPE_DEFAULT, NULL},
477     {LOOP_TYPE_BR_SEND, NULL},
478     {LOOP_TYPE_BR_RECV, NULL},
479     {LOOP_TYPE_P2P, NULL},
480     {LOOP_TYPE_LANE, NULL},
481     {LOOP_TYPE_HANDLE_FILE, NULL}
482 };
483 
GetLooper(int type)484 SoftBusLooper *GetLooper(int type)
485 {
486     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
487     for (uint32_t i = 0; i < len; i++) {
488         if (g_loopConfig[i].type == type) {
489             return g_loopConfig[i].looper;
490         }
491     }
492     return NULL;
493 }
494 
SetLooper(int type,SoftBusLooper * looper)495 void SetLooper(int type, SoftBusLooper *looper)
496 {
497     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
498     for (uint32_t i = 0; i < len; i++) {
499         if (g_loopConfig[i].type == type) {
500             g_loopConfig[i].looper = looper;
501         }
502     }
503 }
504 
ReleaseLooper(const SoftBusLooper * looper)505 static void ReleaseLooper(const 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].looper == looper) {
510             g_loopConfig[i].looper = NULL;
511             return;
512         }
513     }
514 }
515 
DestroyLooper(SoftBusLooper * looper)516 void DestroyLooper(SoftBusLooper *looper)
517 {
518     if (looper == NULL) {
519         COMM_LOGE(COMM_UTILS, "looper is null");
520         return;
521     }
522 
523     SoftBusLooperContext *context = looper->context;
524     if (context != NULL) {
525         (void)SoftBusMutexLock(&context->lock);
526 
527         COMM_LOGI(COMM_UTILS, "set stop 1. name=%{public}s", context->name);
528         context->stop = 1;
529 
530         SoftBusCondBroadcast(&context->cond);
531         (void)SoftBusMutexUnlock(&context->lock);
532         while (1) {
533             (void)SoftBusMutexLock(&context->lock);
534             COMM_LOGI(COMM_UTILS, "get. name=%{public}s, running=%{public}d", context->name, context->running);
535             if (context->running == 0) {
536                 (void)SoftBusMutexUnlock(&context->lock);
537                 break;
538             }
539             SoftBusCondWait(&context->condRunning, &context->lock, NULL);
540             (void)SoftBusMutexUnlock(&context->lock);
541         }
542         // release msg
543         ListNode *item = NULL;
544         ListNode *nextItem = NULL;
545         LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
546             SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
547             SoftBusMessage *msg = itemNode->msg;
548             FreeSoftBusMsg(msg);
549             ListDelete(&itemNode->node);
550             SoftBusFree(itemNode);
551         }
552         COMM_LOGI(COMM_UTILS, "destroy. name=%{public}s", context->name);
553         // destroy looper
554         SoftBusCondDestroy(&context->cond);
555         SoftBusCondDestroy(&context->condRunning);
556         SoftBusMutexDestroy(&context->lock);
557         SoftBusFree(context);
558         looper->context = NULL;
559     }
560     ReleaseLooper(looper);
561     SoftBusFree(looper);
562     if (g_looperCnt != 0) {
563         g_looperCnt--;
564     }
565 }
566 
LooperInit(void)567 int LooperInit(void)
568 {
569     SoftBusLooper *looper = CreateNewLooper("BusCenter");
570     if (!looper) {
571         COMM_LOGE(COMM_UTILS, "init BusCenter looper fail.");
572         return SOFTBUS_ERR;
573     }
574     SetLooper(LOOP_TYPE_DEFAULT, looper);
575 
576     SoftBusLooper *handleFileLooper = CreateNewLooper("HandleFile");
577     if (!handleFileLooper) {
578         COMM_LOGE(COMM_UTILS, "init HandleFile looper fail.");
579         return SOFTBUS_ERR;
580     }
581     SetLooper(LOOP_TYPE_HANDLE_FILE, handleFileLooper);
582     COMM_LOGD(COMM_UTILS, "init looper success.");
583     return SOFTBUS_OK;
584 }
585 
LooperDeinit(void)586 void LooperDeinit(void)
587 {
588     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
589     for (uint32_t i = 0; i < len; i++) {
590         if (g_loopConfig[i].looper == NULL) {
591             continue;
592         }
593         (void)SoftBusMutexLock(&(g_loopConfig[i].looper->context->lock));
594         if (g_isThreadStarted == 0) {
595             g_isNeedDestroy = 1;
596             (void)SoftBusMutexUnlock(&(g_loopConfig[i].looper->context->lock));
597             return;
598         }
599         (void)SoftBusMutexUnlock(&(g_loopConfig[i].looper->context->lock));
600         DestroyLooper(g_loopConfig[i].looper);
601     }
602 }
603