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