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(¤tMsgNode, &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 }