1e66f31c5Sopenharmony_ci/* 2e66f31c5Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3e66f31c5Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e66f31c5Sopenharmony_ci * you may not use this file except in compliance with the License. 5e66f31c5Sopenharmony_ci * You may obtain a copy of the License at 6e66f31c5Sopenharmony_ci * 7e66f31c5Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e66f31c5Sopenharmony_ci * 9e66f31c5Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e66f31c5Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e66f31c5Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e66f31c5Sopenharmony_ci * See the License for the specific language governing permissions and 13e66f31c5Sopenharmony_ci * limitations under the License. 14e66f31c5Sopenharmony_ci */ 15e66f31c5Sopenharmony_ci#include "libuv_async_stack.h" 16e66f31c5Sopenharmony_ci 17e66f31c5Sopenharmony_ci#include <dlfcn.h> 18e66f31c5Sopenharmony_ci#include <pthread.h> 19e66f31c5Sopenharmony_ci#include <stdlib.h> 20e66f31c5Sopenharmony_ci#include <string.h> 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_citypedef void(*LibuvSetStackIdFunc)(uint64_t stackId); 23e66f31c5Sopenharmony_citypedef uint64_t(*LibuvCollectAsyncStackFunc)(); 24e66f31c5Sopenharmony_cistatic LibuvCollectAsyncStackFunc g_collectAsyncStackFunc = NULL; 25e66f31c5Sopenharmony_cistatic LibuvSetStackIdFunc g_setStackIdFunc = NULL; 26e66f31c5Sopenharmony_citypedef enum { 27e66f31c5Sopenharmony_ci ASYNC_DFX_NOT_INIT, 28e66f31c5Sopenharmony_ci ASYNC_DFX_DISABLE, 29e66f31c5Sopenharmony_ci ASYNC_DFX_ENABLE 30e66f31c5Sopenharmony_ci} AsyncDfxInitStatus; 31e66f31c5Sopenharmony_ci 32e66f31c5Sopenharmony_cistatic AsyncDfxInitStatus g_enabledLibuvAsyncStackStatus = ASYNC_DFX_NOT_INIT; 33e66f31c5Sopenharmony_cistatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 34e66f31c5Sopenharmony_ci 35e66f31c5Sopenharmony_cistatic void LoadDfxAsyncStackLib() 36e66f31c5Sopenharmony_ci{ 37e66f31c5Sopenharmony_ci g_enabledLibuvAsyncStackStatus = ASYNC_DFX_DISABLE; 38e66f31c5Sopenharmony_ci const char* debuggableEnv = getenv("HAP_DEBUGGABLE"); 39e66f31c5Sopenharmony_ci if ((debuggableEnv == NULL) || (strcmp(debuggableEnv, "true") != 0)) { 40e66f31c5Sopenharmony_ci return; 41e66f31c5Sopenharmony_ci } 42e66f31c5Sopenharmony_ci 43e66f31c5Sopenharmony_ci // if async stack is not enabled, the lib should not be unloaded 44e66f31c5Sopenharmony_ci void* asyncStackLibHandle = dlopen("libasync_stack.z.so", RTLD_NOW); 45e66f31c5Sopenharmony_ci if (asyncStackLibHandle == NULL) { 46e66f31c5Sopenharmony_ci return; 47e66f31c5Sopenharmony_ci } 48e66f31c5Sopenharmony_ci 49e66f31c5Sopenharmony_ci g_collectAsyncStackFunc = (LibuvCollectAsyncStackFunc)(dlsym(asyncStackLibHandle, "CollectAsyncStack")); 50e66f31c5Sopenharmony_ci if (g_collectAsyncStackFunc == NULL) { 51e66f31c5Sopenharmony_ci dlclose(asyncStackLibHandle); 52e66f31c5Sopenharmony_ci asyncStackLibHandle = NULL; 53e66f31c5Sopenharmony_ci return; 54e66f31c5Sopenharmony_ci } 55e66f31c5Sopenharmony_ci 56e66f31c5Sopenharmony_ci g_setStackIdFunc = (LibuvSetStackIdFunc)(dlsym(asyncStackLibHandle, "SetStackId")); 57e66f31c5Sopenharmony_ci if (g_setStackIdFunc == NULL) { 58e66f31c5Sopenharmony_ci g_collectAsyncStackFunc = NULL; 59e66f31c5Sopenharmony_ci dlclose(asyncStackLibHandle); 60e66f31c5Sopenharmony_ci asyncStackLibHandle = NULL; 61e66f31c5Sopenharmony_ci return; 62e66f31c5Sopenharmony_ci } 63e66f31c5Sopenharmony_ci 64e66f31c5Sopenharmony_ci g_enabledLibuvAsyncStackStatus = ASYNC_DFX_ENABLE; 65e66f31c5Sopenharmony_ci} 66e66f31c5Sopenharmony_ci 67e66f31c5Sopenharmony_cistatic AsyncDfxInitStatus LibuvAsyncStackInit() 68e66f31c5Sopenharmony_ci{ 69e66f31c5Sopenharmony_ci if (g_enabledLibuvAsyncStackStatus == ASYNC_DFX_NOT_INIT) { 70e66f31c5Sopenharmony_ci pthread_mutex_lock(&g_mutex); 71e66f31c5Sopenharmony_ci if (g_enabledLibuvAsyncStackStatus == ASYNC_DFX_NOT_INIT) { 72e66f31c5Sopenharmony_ci LoadDfxAsyncStackLib(); 73e66f31c5Sopenharmony_ci } 74e66f31c5Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 75e66f31c5Sopenharmony_ci } 76e66f31c5Sopenharmony_ci return g_enabledLibuvAsyncStackStatus; 77e66f31c5Sopenharmony_ci} 78e66f31c5Sopenharmony_ci 79e66f31c5Sopenharmony_ciuint64_t LibuvCollectAsyncStack(void) 80e66f31c5Sopenharmony_ci{ 81e66f31c5Sopenharmony_ci if (LibuvAsyncStackInit() == ASYNC_DFX_ENABLE) { 82e66f31c5Sopenharmony_ci return g_collectAsyncStackFunc(); 83e66f31c5Sopenharmony_ci } 84e66f31c5Sopenharmony_ci 85e66f31c5Sopenharmony_ci return 0; 86e66f31c5Sopenharmony_ci} 87e66f31c5Sopenharmony_ci 88e66f31c5Sopenharmony_civoid LibuvSetStackId(uint64_t stackId) 89e66f31c5Sopenharmony_ci{ 90e66f31c5Sopenharmony_ci if (LibuvAsyncStackInit() == ASYNC_DFX_ENABLE) { 91e66f31c5Sopenharmony_ci return g_setStackIdFunc(stackId); 92e66f31c5Sopenharmony_ci } 93e66f31c5Sopenharmony_ci} 94