• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include <atomic>
20 #include "ffrt.h"
21 #include "c/ffrt_ipc.h"
22 
23 #include "common_list.h"
24 #include "comm_log.h"
25 #include "softbus_adapter_mem.h"
26 #include "softbus_def.h"
27 #include "softbus_error_code.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 #define TASK_HANDLE_TIMEOUT 5000LL
34 
35 static std::atomic<uint32_t> g_looperCnt(0);
36 
37 typedef struct {
38     int32_t what;
39     uint64_t arg1;
40     uint64_t arg2;
41     int64_t time;
42     char *handler;
43     char looper[LOOP_NAME_LEN];
44 } MsgEventInfo;
45 
46 struct FfrtMsgQueue {
47     ffrt::queue *msgQueue;
48 };
49 
50 typedef struct {
51     SoftBusMessage *msg;
52     ListNode node;
53     ffrt::task_handle *msgHandle;
54 } SoftBusMessageNode;
55 
56 struct SoftBusLooperContext {
57     ListNode msgHead;
58     char name[LOOP_NAME_LEN];
59     unsigned int msgSize;
60     ffrt::mutex *mtx;
61     volatile bool stop; // destroys looper, stop = true
62     MsgEventInfo handlingMsg;
63 };
64 
UptimeMicros(void)65 static int64_t UptimeMicros(void)
66 {
67     SoftBusSysTime t = {
68         .sec = 0,
69         .usec = 0,
70     };
71     SoftBusGetTime(&t);
72     int64_t when = t.sec * TIME_THOUSANDS_MULTIPLIER * TIME_THOUSANDS_MULTIPLIER + t.usec;
73     return when;
74 }
75 
FreeSoftBusMsg(SoftBusMessage * msg)76 NO_SANITIZE("cfi") static void FreeSoftBusMsg(SoftBusMessage *msg)
77 {
78     if (msg->FreeMessage == nullptr) {
79         SoftBusFree(msg);
80         msg = nullptr;
81     } else {
82         msg->FreeMessage(msg);
83     }
84 }
85 
MallocMessage(void)86 SoftBusMessage *MallocMessage(void)
87 {
88     SoftBusMessage *msg = static_cast<SoftBusMessage *>(SoftBusCalloc(sizeof(SoftBusMessage)));
89     if (msg == nullptr) {
90         COMM_LOGE(COMM_UTILS, "malloc SoftBusMessage failed");
91         return nullptr;
92     }
93     return msg;
94 }
95 
FreeMessage(SoftBusMessage * msg)96 void FreeMessage(SoftBusMessage *msg)
97 {
98     if (msg != nullptr) {
99         FreeSoftBusMsg(msg);
100         msg = nullptr;
101     }
102 }
103 
DumpLooperLocked(const SoftBusLooperContext * context)104 static void DumpLooperLocked(const SoftBusLooperContext *context)
105 {
106     int32_t i = 0;
107     ListNode *item = nullptr;
108     LIST_FOR_EACH(item, &context->msgHead) {
109         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
110         SoftBusMessage *msg = itemNode->msg;
111         if (i > MAX_LOOPER_PRINT_CNT) {
112             COMM_LOGW(COMM_UTILS, "many messages left unprocessed, msgSize=%{public}u",
113                 context->msgSize);
114             break;
115         }
116         COMM_LOGD(COMM_UTILS,
117             "DumpLooper. i=%{public}d, handler=%{public}s, what=%{public}" PRId32 ", arg1=%{public}" PRIu64 ", "
118             "arg2=%{public}" PRIu64 ", time=%{public}" PRId64 "",
119             i, msg->handler->name, msg->what, msg->arg1, msg->arg2, msg->time);
120         i++;
121     }
122 }
123 
DumpLooper(const SoftBusLooper * looper)124 void DumpLooper(const SoftBusLooper *looper)
125 {
126     if (looper == nullptr) {
127         return;
128     }
129     SoftBusLooperContext *context = looper->context;
130     context->mtx->lock();
131     if (looper->dumpable) {
132         DumpLooperLocked(context);
133     }
134     context->mtx->unlock();
135 }
136 
137 struct LoopConfigItem {
138     int type;
139     SoftBusLooper *looper;
140 };
141 
142 static struct LoopConfigItem g_loopConfig[] = {
143     {LOOP_TYPE_DEFAULT, nullptr},
144     {LOOP_TYPE_CONN, nullptr},
145     {LOOP_TYPE_LNN, nullptr},
146     {LOOP_TYPE_DISC, nullptr},
147 };
148 
ReleaseLooper(const SoftBusLooper * looper)149 static void ReleaseLooper(const SoftBusLooper *looper)
150 {
151     const uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
152     for (uint32_t i = 0; i < len; i++) {
153         if (g_loopConfig[i].looper == looper) {
154             g_loopConfig[i].looper = nullptr;
155             return;
156         }
157     }
158 }
159 
DumpMsgInfo(const SoftBusMessage * msg)160 static void DumpMsgInfo(const SoftBusMessage *msg)
161 {
162     if (msg->handler == nullptr || msg->handler->looper == nullptr ||
163         msg->handler->looper->context == nullptr) {
164         COMM_LOGE(COMM_UTILS, "invalid para when dump msg info");
165         return;
166     }
167     COMM_LOGI(COMM_UTILS, "handling msg, %{public}s, %{public}s, %{public}" PRId32 ", %{public}" PRIu64 ", "
168         "%{public}" PRIu64 ", %{public}" PRId64 "",
169         msg->handler->looper->context->name, msg->handler->name, msg->what, msg->arg1, msg->arg2, msg->time);
170 }
171 
UpdateHandlingMsg(const SoftBusMessage * currentMsg,const SoftBusLooper * looper)172 static void UpdateHandlingMsg(const SoftBusMessage *currentMsg, const SoftBusLooper *looper)
173 {
174     if (looper->queue == nullptr || currentMsg->handler == nullptr || currentMsg->handler->name == nullptr) {
175         COMM_LOGE(COMM_UTILS, "invalid para when update handling msg");
176         return;
177     }
178     MsgEventInfo *tmpMsg = &(looper->context->handlingMsg);
179     if (tmpMsg->handler != nullptr) {
180         SoftBusFree(tmpMsg->handler);
181         tmpMsg->handler = nullptr;
182     }
183     tmpMsg->handler = static_cast<char *>(SoftBusCalloc(strlen(currentMsg->handler->name) + 1));
184     if (tmpMsg->handler == nullptr) {
185         COMM_LOGE(COMM_UTILS, "calloc fail when update handling msg");
186         return;
187     }
188     if (memcpy_s(tmpMsg->looper, LOOP_NAME_LEN, looper->context->name, LOOP_NAME_LEN) != EOK) {
189         COMM_LOGE(COMM_UTILS, "copy looper fail when update handling msg");
190     }
191     if (strcpy_s(tmpMsg->handler, strlen(currentMsg->handler->name) + 1, currentMsg->handler->name) != EOK) {
192         COMM_LOGE(COMM_UTILS, "copy handler fail when update handling msg");
193         SoftBusFree(tmpMsg->handler);
194         tmpMsg->handler = nullptr;
195     }
196     tmpMsg->what = currentMsg->what;
197     tmpMsg->arg1 = currentMsg->arg1;
198     tmpMsg->arg2 = currentMsg->arg2;
199     tmpMsg->time = currentMsg->time;
200 }
201 
GetMsgNodeFromContext(SoftBusMessageNode ** msgNode,const SoftBusMessage * tmpMsg,const SoftBusLooper * looper)202 static int32_t GetMsgNodeFromContext(SoftBusMessageNode **msgNode,
203     const SoftBusMessage *tmpMsg, const SoftBusLooper *looper)
204 {
205     looper->context->mtx->lock();
206     if (looper->context->stop) {
207         COMM_LOGE(COMM_UTILS, "cancel handle with looper is stop, name=%{public}s", looper->context->name);
208         looper->context->mtx->unlock();
209         return SOFTBUS_LOOPER_ERR;
210     }
211     ListNode *item = nullptr;
212     ListNode *nextItem = nullptr;
213     LIST_FOR_EACH_SAFE(item, nextItem, &(looper->context->msgHead)) {
214         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
215         SoftBusMessage *msg = itemNode->msg;
216         if (tmpMsg->what == msg->what && tmpMsg->arg1 == msg->arg1 && tmpMsg->arg2 == msg->arg2 &&
217             tmpMsg->time == msg->time && tmpMsg->handler == msg->handler) {
218             ListDelete(&itemNode->node);
219             *msgNode = itemNode;
220             looper->context->msgSize--;
221             UpdateHandlingMsg(msg, looper);
222             looper->context->mtx->unlock();
223             return SOFTBUS_OK;
224         }
225     }
226     COMM_LOGE(COMM_UTILS, "no get correct msg from context, time=%{public}" PRId64"", tmpMsg->time);
227     looper->context->mtx->unlock();
228     return SOFTBUS_LOOPER_ERR;
229 }
230 
SubmitMsgToFfrt(SoftBusMessageNode * msgNode,const SoftBusLooper * looper,uint64_t delayMicros)231 static int32_t SubmitMsgToFfrt(SoftBusMessageNode *msgNode, const SoftBusLooper *looper, uint64_t delayMicros)
232 {
233     msgNode->msgHandle = new (std::nothrow)ffrt::task_handle();
234     if (msgNode->msgHandle == nullptr) {
235         COMM_LOGE(COMM_UTILS, "ffrt msgHandle SoftBusCalloc fail");
236         return SOFTBUS_MALLOC_ERR;
237     }
238     SoftBusMessage tmpMsg = {
239         .what = msgNode->msg->what,
240         .arg1 = msgNode->msg->arg1,
241         .arg2 = msgNode->msg->arg2,
242         .time = msgNode->msg->time,
243         .handler = msgNode->msg->handler,
244     };
245     *(msgNode->msgHandle) = looper->queue->msgQueue->submit_h([tmpMsg, looper] {
246         ffrt_this_task_set_legacy_mode(true);
247         if (looper == nullptr || looper->context == nullptr) {
248             COMM_LOGE(COMM_UTILS, "invalid looper para when handle");
249             return;
250         }
251         SoftBusMessageNode *currentMsgNode = nullptr;
252         if (GetMsgNodeFromContext(&currentMsgNode, &tmpMsg, looper) != SOFTBUS_OK) {
253             COMM_LOGE(COMM_UTILS, "get currentMsgNode from context fail");
254             return;
255         }
256         SoftBusMessage *currentMsg = currentMsgNode->msg;
257         if (currentMsg->handler != nullptr && currentMsg->handler->HandleMessage != nullptr) {
258             DumpMsgInfo(currentMsg);
259             currentMsg->handler->HandleMessage(currentMsg);
260         } else {
261             COMM_LOGE(COMM_UTILS, "handler is null when handle msg, name=%{public}s", looper->context->name);
262         }
263         FreeSoftBusMsg(currentMsg);
264         delete (currentMsgNode->msgHandle);
265         SoftBusFree(currentMsgNode);
266     }, ffrt::task_attr().delay(delayMicros));
267     return SOFTBUS_OK;
268 }
269 
InsertMsgWithTime(SoftBusLooperContext * context,SoftBusMessageNode * msgNode)270 static void InsertMsgWithTime(SoftBusLooperContext *context, SoftBusMessageNode *msgNode)
271 {
272     ListNode *item = nullptr;
273     ListNode *nextItem = nullptr;
274     bool insert = false;
275     LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
276         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
277         if (itemNode->msg->time > msgNode->msg->time) {
278             ListTailInsert(item, &(msgNode->node));
279             insert = true;
280             break;
281         }
282     }
283     if (!insert) {
284         ListTailInsert(&(context->msgHead), &(msgNode->node));
285     }
286 }
287 
PostMessageWithFfrt(const SoftBusLooper * looper,SoftBusMessage * msg,uint64_t delayMicros)288 static void PostMessageWithFfrt(const SoftBusLooper *looper, SoftBusMessage *msg, uint64_t delayMicros)
289 {
290     SoftBusMessageNode *msgNode = static_cast<SoftBusMessageNode *>(SoftBusCalloc(sizeof(SoftBusMessageNode)));
291     if (msgNode == nullptr) {
292         COMM_LOGE(COMM_UTILS, "message node malloc failed");
293         FreeSoftBusMsg(msg);
294         return;
295     }
296     ListInit(&msgNode->node);
297     msgNode->msg = msg;
298     SoftBusLooperContext *context = looper->context;
299     context->mtx->lock();
300     if (context->stop) {
301         FreeSoftBusMsg(msg);
302         SoftBusFree(msgNode);
303         COMM_LOGE(COMM_UTILS, "cancel post with looper is stop, name=%{public}s", context->name);
304         context->mtx->unlock();
305         return;
306     }
307     if (SubmitMsgToFfrt(msgNode, looper, delayMicros) != SOFTBUS_OK) {
308         FreeSoftBusMsg(msg);
309         SoftBusFree(msgNode);
310         COMM_LOGE(COMM_UTILS, "submit msg to ffrt fail, name=%{public}s", context->name);
311         context->mtx->unlock();
312         return;
313     }
314     InsertMsgWithTime(context, msgNode);
315     context->msgSize++;
316     if (looper->dumpable) {
317         DumpLooperLocked(context);
318     }
319     context->mtx->unlock();
320 }
321 
RemoveMessageWithFfrt(const SoftBusLooper * looper,const SoftBusHandler * handler,int (* customFunc)(const SoftBusMessage *,void *),void * args)322 static void RemoveMessageWithFfrt(const SoftBusLooper *looper, const SoftBusHandler *handler,
323     int (*customFunc)(const SoftBusMessage*, void*), void *args)
324 {
325     SoftBusLooperContext *context = looper->context;
326     context->mtx->lock();
327     if (context->stop) {
328         COMM_LOGE(COMM_UTILS, "cancel remove with looper is stop, name=%{public}s", context->name);
329         context->mtx->unlock();
330         return;
331     }
332     ListNode *item = nullptr;
333     ListNode *nextItem = nullptr;
334     LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
335         SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
336         SoftBusMessage *msg = itemNode->msg;
337         if (msg->handler == handler && customFunc(msg, args) == 0) {
338             looper->queue->msgQueue->cancel(*(itemNode->msgHandle)); // cancel fail when task is handling
339             COMM_LOGD(COMM_UTILS, "remove msg with ffrt succ, time=%{public}" PRId64"", msg->time);
340             FreeSoftBusMsg(msg);
341             ListDelete(&itemNode->node);
342             delete (itemNode->msgHandle);
343             SoftBusFree(itemNode);
344             context->msgSize--;
345         }
346     }
347     context->mtx->unlock();
348 }
349 
DestroyLooperWithFfrt(SoftBusLooper * looper)350 static void DestroyLooperWithFfrt(SoftBusLooper *looper)
351 {
352     SoftBusLooperContext *context = looper->context;
353     if (context != nullptr) {
354         context->mtx->lock();
355         context->stop = true;
356         COMM_LOGI(COMM_UTILS, "looper is stop, name=%{public}s", looper->context->name);
357         context->mtx->unlock();
358         delete (looper->queue->msgQueue); //if task is handling when delete, it will return after handle;
359         looper->queue->msgQueue = nullptr;
360         ListNode *item = nullptr;
361         ListNode *nextItem = nullptr;
362         LIST_FOR_EACH_SAFE(item, nextItem, &context->msgHead) {
363             SoftBusMessageNode *itemNode = LIST_ENTRY(item, SoftBusMessageNode, node);
364             SoftBusMessage *msg = itemNode->msg;
365             FreeSoftBusMsg(msg);
366             ListDelete(&itemNode->node);
367             delete (itemNode->msgHandle);
368             SoftBusFree(itemNode);
369             context->msgSize--;
370         }
371         if (context->handlingMsg.handler != nullptr) {
372             SoftBusFree(context->handlingMsg.handler);
373             context->handlingMsg.handler = nullptr;
374         }
375         delete (context->mtx);
376         context->mtx = nullptr;
377         SoftBusFree(context);
378         context = nullptr;
379     } else {
380         delete (looper->queue->msgQueue);
381         looper->queue->msgQueue = nullptr;
382     }
383     SoftBusFree(looper->queue);
384     looper->queue = nullptr;
385     ReleaseLooper(looper);
386     SoftBusFree(looper);
387     looper = nullptr;
388     if (g_looperCnt.load(std::memory_order_acquire) != 0) {
389         g_looperCnt--;
390     }
391 }
392 
LooperPostMessage(const SoftBusLooper * looper,SoftBusMessage * msg)393 static void LooperPostMessage(const SoftBusLooper *looper, SoftBusMessage *msg)
394 {
395     if (msg == nullptr || msg->handler == nullptr) {
396         COMM_LOGE(COMM_UTILS, "LooperPostMessage with nullmsg");
397         return;
398     }
399     if (looper == nullptr || looper->context == nullptr) {
400         COMM_LOGE(COMM_UTILS, "LooperPostMessage with nulllooper");
401         return;
402     }
403     if (looper->queue == nullptr || looper->queue->msgQueue == nullptr) {
404         COMM_LOGE(COMM_UTILS, "LooperPostMessage with nullqueue");
405         return;
406     }
407     msg->time = UptimeMicros();
408     PostMessageWithFfrt(looper, msg, 0);
409 }
410 
LooperPostMessageDelay(const SoftBusLooper * looper,SoftBusMessage * msg,uint64_t delayMillis)411 static void LooperPostMessageDelay(const SoftBusLooper *looper, SoftBusMessage *msg, uint64_t delayMillis)
412 {
413     if (msg == nullptr || msg->handler == nullptr) {
414         COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nullmsg");
415         return;
416     }
417     if (looper == nullptr || looper->context == nullptr) {
418         COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nulllooper");
419         return;
420     }
421     if (looper->queue == nullptr || looper->queue->msgQueue == nullptr) {
422         COMM_LOGE(COMM_UTILS, "LooperPostMessageDelay with nullqueue");
423         return;
424     }
425     msg->time = UptimeMicros() + (int64_t)delayMillis * TIME_THOUSANDS_MULTIPLIER;
426     PostMessageWithFfrt(looper, msg, delayMillis * TIME_THOUSANDS_MULTIPLIER);
427 }
428 
WhatRemoveFunc(const SoftBusMessage * msg,void * args)429 static int WhatRemoveFunc(const SoftBusMessage *msg, void *args)
430 {
431     int32_t what = static_cast<int32_t>(reinterpret_cast<intptr_t>(args));
432     if (msg->what == what) {
433         return 0;
434     }
435     return 1;
436 }
437 
LoopRemoveMessageCustom(const SoftBusLooper * looper,const SoftBusHandler * handler,int (* customFunc)(const SoftBusMessage *,void *),void * args)438 static void LoopRemoveMessageCustom(const SoftBusLooper *looper, const SoftBusHandler *handler,
439     int (*customFunc)(const SoftBusMessage*, void*), void *args)
440 {
441     if (looper == nullptr || looper->context == nullptr) {
442         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nulllopper");
443         return;
444     }
445     if (looper->queue == nullptr || looper->queue->msgQueue == nullptr) {
446         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nullqueue");
447         return;
448     }
449     if (handler == nullptr) {
450         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nullhandler");
451         return;
452     }
453     if (customFunc == nullptr) {
454         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nullcustomFunc");
455         return;
456     }
457     RemoveMessageWithFfrt(looper, handler, customFunc, args);
458 }
459 
LooperRemoveMessage(const SoftBusLooper * looper,const SoftBusHandler * handler,int32_t what)460 static void LooperRemoveMessage(const SoftBusLooper *looper, const SoftBusHandler *handler, int32_t what)
461 {
462     if (looper == nullptr || looper->context == nullptr) {
463         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nulllopper");
464         return;
465     }
466     if (looper->queue == nullptr || looper->queue->msgQueue == nullptr) {
467         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nullqueue");
468         return;
469     }
470     if (handler == nullptr) {
471         COMM_LOGE(COMM_UTILS, "LooperRemoveMessage with nullhandler");
472         return;
473     }
474     void *arg = reinterpret_cast<void *>(static_cast<intptr_t>(what));
475     LoopRemoveMessageCustom(looper, handler, WhatRemoveFunc, arg);
476 }
477 
SetLooperDumpable(SoftBusLooper * looper,bool dumpable)478 void SetLooperDumpable(SoftBusLooper *looper, bool dumpable)
479 {
480     if (looper == nullptr || looper->context == nullptr) {
481         COMM_LOGE(COMM_UTILS, "looper param is invalid");
482         return;
483     }
484     looper->context->mtx->lock();
485     looper->dumpable = dumpable;
486     looper->context->mtx->unlock();
487 }
488 /* create new ffrt queue depend on create new context success */
CreateNewFfrtQueue(FfrtMsgQueue ** ffrtQueue,const char * name,const SoftBusLooperContext * context)489 static int32_t CreateNewFfrtQueue(FfrtMsgQueue **ffrtQueue, const char *name, const SoftBusLooperContext *context)
490 {
491     FfrtMsgQueue *tmpQueue = static_cast<FfrtMsgQueue *>(SoftBusCalloc(sizeof(FfrtMsgQueue)));
492     if (tmpQueue == nullptr) {
493         COMM_LOGE(COMM_UTILS, "softbus msgQueue SoftBusCalloc fail");
494         return SOFTBUS_MALLOC_ERR;
495     }
496     std::function<void()> callbackFunc = [context]() {
497         if (context == nullptr || context->mtx == nullptr) {
498             COMM_LOGE(COMM_UTILS, "abnormal handle long time task with invalid task context");
499             return;
500         }
501         context->mtx->lock();
502         if (context->handlingMsg.handler != nullptr) {
503             COMM_LOGE(COMM_UTILS, "abnormal handle long time task, what=%{public}" PRId32 ", "
504                 "arg1=%{public}" PRIu64 ", arg2=%{public}" PRIu64 ", time=%{public}" PRId64 ", "
505                 "handler=%{public}s, looper=%{public}s", context->handlingMsg.what, context->handlingMsg.arg1,
506                 context->handlingMsg.arg2, context->handlingMsg.time, context->handlingMsg.handler,
507                 context->handlingMsg.looper);
508         } else {
509             COMM_LOGE(COMM_UTILS, "abnormal handle long time task with invalid msg info, looper=%{public}s",
510                 context->handlingMsg.looper);
511         }
512         context->mtx->unlock();
513     };
514     tmpQueue->msgQueue = new (std::nothrow)ffrt::queue(name,
515         ffrt::queue_attr().timeout(TASK_HANDLE_TIMEOUT * TIME_THOUSANDS_MULTIPLIER).callback(callbackFunc));
516     if (tmpQueue->msgQueue == nullptr) {
517         COMM_LOGE(COMM_UTILS, "ffrt msgQueue SoftBusCalloc fail");
518         SoftBusFree(tmpQueue);
519         return SOFTBUS_MALLOC_ERR;
520     }
521     *ffrtQueue = tmpQueue;
522     return SOFTBUS_OK;
523 }
524 
CreateNewContext(SoftBusLooperContext ** context,const char * name)525 static int32_t CreateNewContext(SoftBusLooperContext **context, const char *name)
526 {
527     SoftBusLooperContext *tmpContext = static_cast<SoftBusLooperContext *>(SoftBusCalloc(sizeof(SoftBusLooperContext)));
528     if (tmpContext == nullptr) {
529         COMM_LOGE(COMM_UTILS, "context SoftBusCalloc fail");
530         return SOFTBUS_MALLOC_ERR;
531     }
532     if (strncpy_s(tmpContext->name, LOOP_NAME_LEN, name, strlen(name)) != EOK) {
533         COMM_LOGE(COMM_UTILS, "memcpy context name fail");
534         SoftBusFree(tmpContext);
535         return SOFTBUS_STRCPY_ERR;
536     }
537     ListInit(&tmpContext->msgHead);
538     // init mtx
539     tmpContext->mtx = new (std::nothrow)ffrt::mutex();
540     if (tmpContext->mtx == nullptr) {
541         COMM_LOGE(COMM_UTILS, "context ffrt lock init fail");
542         SoftBusFree(tmpContext);
543         return SOFTBUS_MALLOC_ERR;
544     }
545     tmpContext->stop = false;
546     tmpContext->handlingMsg.what = 0;
547     tmpContext->handlingMsg.arg1 = 0;
548     tmpContext->handlingMsg.arg2 = 0;
549     tmpContext->handlingMsg.time = 0;
550     tmpContext->handlingMsg.handler = nullptr;
551     (void)memset_s(tmpContext->handlingMsg.looper, LOOP_NAME_LEN, 0, LOOP_NAME_LEN);
552     *context = tmpContext;
553     return SOFTBUS_OK;
554 }
555 
CreateNewLooper(const char * name)556 SoftBusLooper *CreateNewLooper(const char *name)
557 {
558     if (name == nullptr || strlen(name) >= LOOP_NAME_LEN) {
559         COMM_LOGE(COMM_UTILS, "invalid looper name=%{public}s", name);
560         return nullptr;
561     }
562     if (g_looperCnt.load(std::memory_order_acquire) >= MAX_LOOPER_CNT) {
563         COMM_LOGE(COMM_UTILS, "Looper exceeds the maximum, count=%{public}u,",
564             g_looperCnt.load(std::memory_order_acquire));
565         return nullptr;
566     }
567     SoftBusLooper *looper = static_cast<SoftBusLooper *>(SoftBusCalloc(sizeof(SoftBusLooper)));
568     if (looper == nullptr) {
569         COMM_LOGE(COMM_UTILS, "Looper SoftBusCalloc fail");
570         return nullptr;
571     }
572     SoftBusLooperContext *context = nullptr;
573     if (CreateNewContext(&context, name) != SOFTBUS_OK) {
574         COMM_LOGE(COMM_UTILS, "create new context fail");
575         SoftBusFree(looper);
576         return nullptr;
577     }
578     FfrtMsgQueue *ffrtQueue = nullptr;
579     if (CreateNewFfrtQueue(&ffrtQueue, name, context) != SOFTBUS_OK) {
580         COMM_LOGE(COMM_UTILS, "create new ffrtQueue fail");
581         delete (context->mtx);
582         SoftBusFree(context);
583         SoftBusFree(looper);
584         return nullptr;
585     }
586     // init looper
587     looper->context = context;
588     looper->dumpable = true;
589     looper->PostMessage = LooperPostMessage;
590     looper->PostMessageDelay = LooperPostMessageDelay;
591     looper->RemoveMessage = LooperRemoveMessage;
592     looper->RemoveMessageCustom = LoopRemoveMessageCustom;
593     looper->queue = ffrtQueue;
594     COMM_LOGI(COMM_UTILS, "start looper with ffrt ok, name=%{public}s", context->name);
595     g_looperCnt++;
596     return looper;
597 }
598 
GetLooper(int type)599 SoftBusLooper *GetLooper(int type)
600 {
601     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
602     for (uint32_t i = 0; i < len; i++) {
603         if (g_loopConfig[i].type == type) {
604             return g_loopConfig[i].looper;
605         }
606     }
607     return nullptr;
608 }
609 
SetLooper(int type,SoftBusLooper * looper)610 void SetLooper(int type, SoftBusLooper *looper)
611 {
612     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
613     for (uint32_t i = 0; i < len; i++) {
614         if (g_loopConfig[i].type == type) {
615             g_loopConfig[i].looper = looper;
616         }
617     }
618 }
619 
DestroyLooper(SoftBusLooper * looper)620 void DestroyLooper(SoftBusLooper *looper)
621 {
622     if (looper == nullptr) {
623         COMM_LOGE(COMM_UTILS, "DestroyLooper with nulllooper");
624         return;
625     }
626     if (looper->queue == nullptr || looper->queue->msgQueue == nullptr) {
627         COMM_LOGE(COMM_UTILS, "DestroyLooper with nullqueue");
628         return;
629     }
630     DestroyLooperWithFfrt(looper);
631 }
632 
LooperInit(void)633 int LooperInit(void)
634 {
635     SoftBusLooper *looper = CreateNewLooper("BusCenter_Lp");
636     if (!looper) {
637         COMM_LOGE(COMM_UTILS, "init BusCenter looper fail.");
638         return SOFTBUS_LOOPER_ERR;
639     }
640     SetLooper(LOOP_TYPE_DEFAULT, looper);
641 
642     SoftBusLooper *connLooper = CreateNewLooper("ReactorLink_Lp");
643     if (!connLooper) {
644         COMM_LOGE(COMM_UTILS, "init connection looper fail.");
645         return SOFTBUS_LOOPER_ERR;
646     }
647     SetLooper(LOOP_TYPE_CONN, connLooper);
648 
649     COMM_LOGD(COMM_UTILS, "init looper success.");
650     return SOFTBUS_OK;
651 }
652 
LooperDeinit(void)653 void LooperDeinit(void)
654 {
655     uint32_t len = sizeof(g_loopConfig) / sizeof(struct LoopConfigItem);
656     for (uint32_t i = 0; i < len; i++) {
657         if (g_loopConfig[i].looper == nullptr) {
658             continue;
659         }
660         DestroyLooper(g_loopConfig[i].looper);
661     }
662 }