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