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