• 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 #include "libuv_async_stack.h"
16 
17 #include <dlfcn.h>
18 #include <pthread.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 typedef void(*LibuvSetStackIdFunc)(uint64_t stackId);
23 typedef uint64_t(*LibuvCollectAsyncStackFunc)();
24 static LibuvCollectAsyncStackFunc g_collectAsyncStackFunc = NULL;
25 static LibuvSetStackIdFunc g_setStackIdFunc = NULL;
26 typedef enum {
27     ASYNC_DFX_NOT_INIT,
28     ASYNC_DFX_DISABLE,
29     ASYNC_DFX_ENABLE
30 } AsyncDfxInitStatus;
31 
32 static AsyncDfxInitStatus g_enabledLibuvAsyncStackStatus = ASYNC_DFX_NOT_INIT;
33 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
34 
LoadDfxAsyncStackLib()35 static void LoadDfxAsyncStackLib()
36 {
37     g_enabledLibuvAsyncStackStatus = ASYNC_DFX_DISABLE;
38     const char* debuggableEnv = getenv("HAP_DEBUGGABLE");
39     if ((debuggableEnv == NULL) || (strcmp(debuggableEnv, "true") != 0)) {
40         return;
41     }
42 
43     // if async stack is not enabled, the lib should not be unloaded
44     void* asyncStackLibHandle = dlopen("libasync_stack.z.so", RTLD_NOW);
45     if (asyncStackLibHandle == NULL) {
46         return;
47     }
48 
49     g_collectAsyncStackFunc = (LibuvCollectAsyncStackFunc)(dlsym(asyncStackLibHandle, "CollectAsyncStack"));
50     if (g_collectAsyncStackFunc == NULL) {
51         dlclose(asyncStackLibHandle);
52         asyncStackLibHandle = NULL;
53         return;
54     }
55 
56     g_setStackIdFunc = (LibuvSetStackIdFunc)(dlsym(asyncStackLibHandle, "SetStackId"));
57     if (g_setStackIdFunc == NULL) {
58         g_collectAsyncStackFunc = NULL;
59         dlclose(asyncStackLibHandle);
60         asyncStackLibHandle = NULL;
61         return;
62     }
63 
64     g_enabledLibuvAsyncStackStatus = ASYNC_DFX_ENABLE;
65 }
66 
LibuvAsyncStackInit()67 static AsyncDfxInitStatus LibuvAsyncStackInit()
68 {
69     if (g_enabledLibuvAsyncStackStatus == ASYNC_DFX_NOT_INIT) {
70         pthread_mutex_lock(&g_mutex);
71         if (g_enabledLibuvAsyncStackStatus == ASYNC_DFX_NOT_INIT) {
72             LoadDfxAsyncStackLib();
73         }
74         pthread_mutex_unlock(&g_mutex);
75     }
76     return g_enabledLibuvAsyncStackStatus;
77 }
78 
LibuvCollectAsyncStack(void)79 uint64_t LibuvCollectAsyncStack(void)
80 {
81     if (LibuvAsyncStackInit() == ASYNC_DFX_ENABLE) {
82         return g_collectAsyncStackFunc();
83     }
84 
85     return 0;
86 }
87 
LibuvSetStackId(uint64_t stackId)88 void LibuvSetStackId(uint64_t stackId)
89 {
90     if (LibuvAsyncStackInit() == ASYNC_DFX_ENABLE) {
91         return g_setStackIdFunc(stackId);
92     }
93 }
94