From e9a2ea735eb2919d7d483aeccdfc391a1348cd76 Mon Sep 17 00:00:00 2001 From: lijincheng Date: Tue, 1 Apr 2025 21:34:44 +0800 Subject: [PATCH] Add register_ldso_func_for_add_dso 1.add register_ldso_func_for_add_dso and only symbol exposure Issue: https://gitee.com/openharmony/third_party_musl/issues/IBY3F4 Signed-off-by: lijincheng --- ldso/linux/dynlink.c | 155 ++++++++++- libc-test/src/functional/BUILD.gn | 12 + libc-test/src/functional/dlopen_register_a.c | 25 ++ libc-test/src/functional/dlopen_register_b.c | 25 ++ libc-test/src/functional/dlopen_register_c.c | 20 ++ libc-test/src/functional/ldso_register.c | 264 +++++++++++++++++++ libc.map.txt | 1 + src/internal/dynlink.h | 9 +- src/internal/pthread_impl.h | 3 + src/sigchain/linux/sigchain.c | 6 +- src/thread/linux/pthread_create.c | 11 + src/thread/pthread_rwlock_unlock.c | 9 + 12 files changed, 536 insertions(+), 4 deletions(-) create mode 100644 libc-test/src/functional/dlopen_register_a.c create mode 100644 libc-test/src/functional/dlopen_register_b.c create mode 100644 libc-test/src/functional/dlopen_register_c.c create mode 100644 libc-test/src/functional/ldso_register.c diff --git a/ldso/linux/dynlink.c b/ldso/linux/dynlink.c index 8eba7387c..ec2a6be3a 100644 --- a/ldso/linux/dynlink.c +++ b/ldso/linux/dynlink.c @@ -102,6 +102,9 @@ static void (*error)(const char *, ...) = error_noop; #define PARENTS_BASE_CAPACITY 8 #define RELOC_CAN_SEARCH_DSO_BASE_CAPACITY 32 #define ANON_NAME_MAX_LEN 70 +#define NOTIFY_BASE_CAPACITY 8 +#define SEC_CHECK_HAS_ENCAPS 0x1 +#define HM_PR_CHECK_ENCAPS 0x6a6975 #define KPMD_SIZE (1UL << 21) #define HUGEPAGES_SUPPORTED_STR_SIZE (32) @@ -164,6 +167,10 @@ static int noload; static int shutting_down; static jmp_buf *rtld_fail; static pthread_rwlock_t lock; +static pthread_rwlock_t notifier_lock = PTHREAD_RWLOCK_INITIALIZER; +static notify_call *notify_list = NULL; +static size_t notify_cnt = 0; +static size_t notify_capacity = 0; static pthread_mutex_t dlclose_lock = {{{ PTHREAD_MUTEX_RECURSIVE }}}; // set mutex type to PTHREAD_MUTEX_RECURSIVE static struct debug debug; static struct tls_module *tls_tail; @@ -520,6 +527,124 @@ static void (*fdbarrier(void *p))() #define fpaddr(p, v) ((void (*)())laddr(p, v)) #endif +struct notify_dso *create_notify_dso_list(void) +{ + struct notify_dso *list = malloc(sizeof(struct notify_dso)); + if (list) { + list->dso_list = NULL; + list->capacity = 0; + list->length = 0; + return list; + } + return NULL; +} + +void free_notify_dso_list(struct notify_dso *list) +{ + if (list) { + if (list->dso_list) { + free(list->dso_list); + list->dso_list = NULL; + } + list->capacity = 0; + list->length = 0; + free(list); + } +} + +void append_notify_dso(struct notify_dso *list, struct dso *p) +{ + if (list->length >= list->capacity) { + struct dso **realloced = + (struct dso **)realloc(list->dso_list, sizeof(struct dso *) * (list->capacity + NOTIFY_BASE_CAPACITY)); + if (!realloced) { + LD_LOGE("realloc failed for append notify for so %{public}s, errno %{public}d", p->name, errno); + return; + } + list->dso_list = realloced; + list->capacity += NOTIFY_BASE_CAPACITY; + } + list->dso_list[list->length++] = p; +} + +void iterate_notify_dso(struct notify_dso *list, notify_call callback) +{ + struct dso *p = NULL; + for (size_t index = 0; index < list->length; index++) { + p = list->dso_list[index]; + callback(p->map, p->map_len, p->name); + } +} + +static void add_notify_callback(notify_call callback) +{ + if (notify_cnt >= notify_capacity) { + notify_call *realloced = + (notify_call *)realloc(notify_list, sizeof(notify_call) * (notify_capacity + NOTIFY_BASE_CAPACITY)); + if (!realloced) { + LD_LOGE("realloc failed for append notify callback, errno %{public}d", errno); + return; + } + notify_list = realloced; + notify_capacity += NOTIFY_BASE_CAPACITY; + } + notify_list[notify_cnt++] = callback; +} + +struct encaps_for_prctl { + unsigned int option; + char *key; + unsigned int key_len; + unsigned int value_type; + unsigned int value; +}; + +int check_encaps_for_got() +{ + struct encaps_for_prctl encaps_args = {0}; + char got_key[] = "ohos.permission.kernel.DISABLE_GOTPLT_RO_PROTECTION"; + encaps_args.option = SEC_CHECK_HAS_ENCAPS; + encaps_args.key = got_key; + encaps_args.key_len = strlen(got_key); + return prctl(HM_PR_CHECK_ENCAPS, &encaps_args); +} + +/** + * @brief This function can register callback functions to linker. + * During the registration phase, this callback will be executed for all SOs already loaded. + * In the subsequent dynamic loading phase(dlopen), this callback will be executed for the newly loaded Sos. + * Only async-signal-safe functions can be called safely in callback. OtherWise, the behavior of + * the program may be undefined. For example, using memory allocation operations within callbacks + * may result in a deadlock with fork behavior. + * @param callback A pointer of the callback function which has three input parameters. + * @retval 0 is returned on success. + * @retval -1 is returned on failure, and errno is set: + * EACCES: The calling process don't have registration permission and cannot register callback successfully + */ +int register_ldso_func_for_add_dso(notify_call callback) +{ + LD_LOGE("process call register_ldso_func_for_add_dso"); + if (check_encaps_for_got() < 0) { + errno = EACCES; + return -1; + } + struct dso *p; + pthread_rwlock_rdlock(&lock); + update_register_count(); + for (p = head; p; p = p->next) { + // Skip vdso map. + if(!p->map) { + continue; + } + callback(p->map, p->map_len, p->name); + } + pthread_rwlock_wrlock(¬ifier_lock); + pthread_rwlock_unlock(&lock); + add_notify_callback(callback); + pthread_rwlock_unlock(¬ifier_lock); + return 0; +} + static void decode_vec(size_t *v, size_t *a, size_t cnt) { size_t i; @@ -2769,6 +2894,10 @@ void __pthread_mutex_unlock_atfork(int who) // dlclose_lock will never unlock before child process call execve. // so reset dlclose_lock to make sure child process can call dlclose after fork __pthread_mutex_unlock_recursive_inner(&dlclose_lock); + // If a multithread process lock notifier_lock and call fork, + // notifier_lock will has wrong r/w status before child process call execve. + // so reset notifier_lock to make sure child process can use this lock rightly + __pthread__rwlock_unlock_inner(¬ifier_lock); } } @@ -3548,7 +3677,7 @@ static const char *redir_paths[] = { void *dlopen_impl( const char *file, int mode, const char *namespace, const void *caller_addr, const dl_extinfo *extinfo) { - struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next; + struct dso *volatile p, *orig_tail, *notifier_tail, *orig_syms_tail, *orig_lazy_head, *next; struct tls_module *orig_tls_tail; size_t orig_tls_cnt, orig_tls_offset, orig_tls_align; size_t i; @@ -3563,6 +3692,8 @@ void *dlopen_impl( struct dlopen_time_info dlopen_cost = {0}; struct timespec time_start, time_end, total_start, total_end; struct dso *current_so = NULL; + struct notify_dso *list = NULL; + int volatile has_notifier = 0; clock_gettime(CLOCK_MONOTONIC, &total_start); #ifdef LOAD_ORDER_RANDOMIZATION struct loadtasks *tasks = NULL; @@ -3832,9 +3963,22 @@ void *dlopen_impl( notify_addition_to_debugger(orig_tail->next); } + notifier_tail = orig_tail; orig_tail = tail; current_so = p; p = dlopen_post(p, mode); + pthread_rwlock_rdlock(¬ifier_lock); + if (notify_list) { + list = create_notify_dso_list(); + if (list != NULL) { + for (struct dso *new = notifier_tail->next; new; new = new->next) { + if (!new->lazy_cnt) { + append_notify_dso(list, new); + } + } + } + } + has_notifier = 1; end: #ifdef LOAD_ORDER_RANDOMIZATION if (!is_task_appended) { @@ -3845,6 +3989,15 @@ end: __release_ptc(); clock_gettime(CLOCK_MONOTONIC, &time_start); pthread_rwlock_unlock(&lock); + if (has_notifier) { + if (notify_list && list) { + for (size_t notify_index = 0; notify_index < notify_cnt; notify_index++) { + iterate_notify_dso(list, notify_list[notify_index]); + } + free_notify_dso_list(list); + } + pthread_rwlock_unlock(¬ifier_lock); + } if (ctor_queue) { do_init_fini(ctor_queue); free(ctor_queue); diff --git a/libc-test/src/functional/BUILD.gn b/libc-test/src/functional/BUILD.gn index 29dc13653..2d8d1dc05 100644 --- a/libc-test/src/functional/BUILD.gn +++ b/libc-test/src/functional/BUILD.gn @@ -64,6 +64,15 @@ test_sharedlib("dlopen_local") { test_sharedlib("dlopen_init") { } +test_sharedlib("dlopen_register_a") { +} + +test_sharedlib("dlopen_register_b") { +} + +test_sharedlib("dlopen_register_c") { +} + group("dso_shared") { testonly = true @@ -81,6 +90,9 @@ group("dso_shared") { ":dlopen_init", ":dlopen_local", ":dlopen_ns_dso", + ":dlopen_register_a", + ":dlopen_register_b", + ":dlopen_register_c", ":dlopen_so_dep_dlopen_ns_dso", ":dlopen_weak", ":dlopen_weak_deps", diff --git a/libc-test/src/functional/dlopen_register_a.c b/libc-test/src/functional/dlopen_register_a.c new file mode 100644 index 000000000..f85d8ea5d --- /dev/null +++ b/libc-test/src/functional/dlopen_register_a.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + static int test_val; + + int getVal(void) + { + return test_val; + } + + void setVal(int val) + { + test_val = val; + } \ No newline at end of file diff --git a/libc-test/src/functional/dlopen_register_b.c b/libc-test/src/functional/dlopen_register_b.c new file mode 100644 index 000000000..eb42dcd7f --- /dev/null +++ b/libc-test/src/functional/dlopen_register_b.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +void sayhello(void) +{ + printf("hello world!\n"); +} + +void call(void) +{ + sayhello(); +} \ No newline at end of file diff --git a/libc-test/src/functional/dlopen_register_c.c b/libc-test/src/functional/dlopen_register_c.c new file mode 100644 index 000000000..a8c3e2c3d --- /dev/null +++ b/libc-test/src/functional/dlopen_register_c.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include + + void sayhello(void) + { + printf("hello world!\n"); + } \ No newline at end of file diff --git a/libc-test/src/functional/ldso_register.c b/libc-test/src/functional/ldso_register.c new file mode 100644 index 000000000..7dc292154 --- /dev/null +++ b/libc-test/src/functional/ldso_register.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test.h" +typedef void(*notify_call)(uintptr_t dso_base, size_t dso_len, const char *dso_path); +#define MAX_BUF 256 +#define THREAD_NUMBER 3 +#define SET_PROC_TYPE_CMD _IOW('E', 0x18, uint32_t) +#define ASSIGN_ENCAPS_CMD _IOW('E', 0x1A, char *) + +const char* g_libPath1 = "/data/local/tmp/libc-test-lib/libdlopen_register_a.so"; +const char* g_libPath2 = "/data/local/tmp/libc-test-lib/libdlopen_register_b.so"; +static int test_value1 = 0; +static int test_value2 = 0; +static int test_value3 = 0; +static int test_value4 = 0; +static void *register_ptr = NULL; +static int so_nums = 0; + +int check_loaded(const char *so, uintptr_t dso_base, size_t dso_len) +{ + int pid = getpid(); + char path[MAX_BUF] = { 0 }; + if (sprintf(path, "/proc/%d/maps", pid) < 0) { + t_error("Failed in sprintf: %s\n", strerror(errno)); + } + FILE* fp = fopen(path, "r"); + if (fp == NULL) { + return 0; + } + if (strchr(so, '/')) { + so = strrchr(so, '/') + 1; + } + + char buffer[MAX_BUF] = { 0 }; + unsigned long start = 0; + unsigned long end = 0; + unsigned long base = 0; + unsigned long size = 0; + int has_check = 0; + while (fgets(buffer, MAX_BUF, fp) != NULL) { + if (strstr(buffer, so) != NULL) { + char *end_ptr; + start = strtoul(buffer, &end_ptr, 16); + end = strtoul(end_ptr + 1, &end_ptr, 16); + size += end - start; + if (base == 0) { + base = start; + has_check = 1; + } + } else if (has_check) { + break; + } + } + fclose(fp); + if (dso_base == base && size == dso_len) { + return 1; + } + return 0; +} + +void callback1(uintptr_t dso_base, size_t dso_len, const char *dso_path) +{ + test_value1++; + int ret = check_loaded(dso_path, dso_base, dso_len); + if (!ret) { + t_error("Failed check in callback1 for so: %s\n", dso_path); + } +} + +void callback2(uintptr_t dso_base, size_t dso_len, const char *dso_path) +{ + test_value2++; + int ret = check_loaded(dso_path, dso_base, dso_len); + if (!ret) { + t_error("Failed check in callback2 for so: %s\n", dso_path); + } +} + +void callback3(uintptr_t dso_base, size_t dso_len, const char *dso_path) +{ + test_value3++; + int ret = check_loaded(dso_path, dso_base, dso_len); + if (!ret) { + t_error("Failed check in callback3 for so: %s\n", dso_path); + } +} + +void callback4(uintptr_t dso_base, size_t dso_len, const char *dso_path) +{ + test_value4++; + int ret = check_loaded(dso_path, dso_base, dso_len); + if (!ret) { + t_error("Failed check in callback4 for so: %s\n", dso_path); + } +} + +static int header_handler(struct dl_phdr_info *info, size_t size, void *data) +{ + if (strlen(info->dlpi_name) == 0) { + return 0; + } + so_nums++; + return 0; +} + +static notify_call func_list[THREAD_NUMBER] = {callback1, callback2, callback3}; + +struct callback_param { + int (*register_func)(notify_call); + notify_call callback; +}; + +void *add_callback(void *arg) +{ + struct callback_param *info = (struct callback_param *)arg; + info->register_func(info->callback); + return arg; +} + +void add_callback_concurrently() +{ + pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t) * THREAD_NUMBER); + if (threads == NULL) { + t_error("Failed to allocate memory: %s\n", strerror(errno)); + return; + } + register_ptr = dlsym(RTLD_DEFAULT, "register_ldso_func_for_add_dso"); + if (register_ptr == NULL) { + t_error("Failed to find register function in libc.so\n"); + return; + } + size_t index = 0; + struct callback_param arg[THREAD_NUMBER] = {0}; + while (index < THREAD_NUMBER) { + arg[index].register_func = register_ptr; + arg[index].callback = func_list[index]; + if (pthread_create(&(threads[index]), NULL, add_callback, (void*)(&arg[index]))) { + t_error("Failed to create thread: %s\n", strerror(errno)); + break; + } + index++; + } + for (size_t i = 0; i < index; i++) { + if (pthread_join(threads[i], NULL)) { + t_error("Failed to join thread: %s\n", strerror(errno)); + } + } + + free(threads); +} + +int do_iterate_check() +{ + so_nums = 0; + if (dl_iterate_phdr(header_handler, NULL)) { + t_error("Failed to run dl_iterate_phdr\n"); + return -1; + } + + if (so_nums != test_value1 || so_nums != test_value2 || so_nums != test_value3) { + t_error("callback check failed, so_nums: %d, test_value1: %d, test_value2: %d, test_value3: %d\n", + so_nums, test_value1, test_value2, test_value3); + return -1; + } + + if (test_value4 != 0 && so_nums != test_value4) { + t_error("callback second check failed, so_nums: %d, test_value4: %d\n", + so_nums, test_value4); + return -1; + } + return 0; +} + +void *dlopen_thread1(void *arg) +{ + void* handle = dlopen(g_libPath1, RTLD_NOW); + if (!handle) { + t_error("dlopen(name=%s, mode=%d) failed: %s\n", g_libPath1, RTLD_NOW, dlerror()); + } + return arg; +} + +void *dlopen_thread2(void *arg) +{ + void* handle = dlopen(g_libPath2, RTLD_LAZY); + if (!handle) { + t_error("dlopen(name=%s, mode=%d) failed: %s\n", g_libPath2, RTLD_LAZY, dlerror()); + } + return arg; +} + +void dlopen_concurrently() +{ + pthread_t td1, td2, td3; + struct callback_param arg = {register_ptr, callback4}; + pthread_create(&td1, NULL, dlopen_thread1, NULL); + pthread_create(&td2, NULL, dlopen_thread2, NULL); + pthread_create(&td3, NULL, add_callback, (void *)(&arg)); + pthread_join(td1, NULL); + pthread_join(td2, NULL); + pthread_join(td3, NULL); +} + +void set_proc_type() +{ + int fd = open("/dev/encaps", O_RDWR); + if (fd < 0) { + t_error("open /dev/encaps failed, errno: %d\n", errno); + return; + } else { + uint32_t type = 4; + ioctl(fd, SET_PROC_TYPE_CMD, &type); + close(fd); + } +} + +void assign_encaps() +{ + int fd = open("/dev/encaps", O_RDWR); + char str[] = "{\"encaps\":{\"ohos.encaps.count\":1, \"ohos.encaps.fork.count\":5}}"; + if (fd < 0) { + t_error("open /dev/encaps failed, errno: %d\n", errno); + return; + } else { + ioctl(fd, ASSIGN_ENCAPS_CMD, str); + close(fd); + } +} + +int main(int argc, char* argv[]) +{ + set_proc_type(); + assign_encaps(); + add_callback_concurrently(); + if (do_iterate_check() < 0) { + return t_status; + } + dlopen_concurrently(); + do_iterate_check(); + return t_status; +} \ No newline at end of file diff --git a/libc.map.txt b/libc.map.txt index 772f52c97..3081a2d04 100644 --- a/libc.map.txt +++ b/libc.map.txt @@ -1527,6 +1527,7 @@ regerror; regexec; regfree; + register_ldso_func_for_add_dso; remainder; remainderf; remainderl; diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 93a150240..f731164eb 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -195,6 +195,12 @@ struct dlopen_time_info { }; #endif +struct notify_dso { + struct dso **dso_list; + size_t capacity; + size_t length; +}; + struct fdpic_loadseg { uintptr_t addr, p_vaddr, p_memsz; }; @@ -302,7 +308,8 @@ hidden void *__dlsym(void *restrict, const char *restrict, void *restrict); hidden void __dl_seterr(const char *, ...); hidden int __dl_invalid_handle(void *); hidden void __dl_vseterr(const char *, va_list); - +typedef void(*notify_call)(uintptr_t dso_base, size_t dso_len, const char *dso_path); +int register_ldso_func_for_add_dso(notify_call callback); hidden ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic(); hidden extern int __malloc_replaced; diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 671ac61bd..86d7514e7 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -296,6 +296,8 @@ hidden extern struct call_tl_lock tl_lock_caller_count; hidden void __tl_lock(void); hidden void __tl_unlock(void); hidden void __tl_sync(pthread_t); +hidden int get_register_count(void); +hidden void update_register_count(void); hidden int get_tl_lock_count(void); hidden int get_tl_lock_waiters(void); hidden int get_tl_lock_tid_fail(void); @@ -309,6 +311,7 @@ hidden int get_thread_list_lock_tid_overlimit(void); hidden struct call_tl_lock *get_tl_lock_caller_count(void); hidden struct pthread* __pthread_list_find(pthread_t, const char*); hidden void __pthread_mutex_unlock_recursive_inner(pthread_mutex_t *m); +hidden void __pthread__rwlock_unlock_inner(pthread_rwlock_t *m); extern hidden volatile int __thread_list_lock; diff --git a/src/sigchain/linux/sigchain.c b/src/sigchain/linux/sigchain.c index d9dbef8e8..7af26bc9e 100644 --- a/src/sigchain/linux/sigchain.c +++ b/src/sigchain/linux/sigchain.c @@ -234,7 +234,8 @@ static void signal_chain_handler(int signo, siginfo_t* siginfo, void* ucontext_r "install_new_tls_tl_lock=%{public}d " "set_syscall_hooks_tl_lock=%{public}d " "set_syscall_hooks_linux_tl_lock=%{public}d " - "fork_tl_lock=%{public}d ", + "fork_tl_lock=%{public}d " + "register_count=%{public}d ", __func__, idx, signo, (unsigned long long)sig_chains[signo - 1].sca_special_actions[idx].sca_sigaction, noreturn, signo, thread_list_lock_status, get_tl_lock_count(), get_tl_lock_waiters(), get_tl_lock_tid_fail(), get_tl_lock_count_tid(), @@ -251,7 +252,8 @@ static void signal_chain_handler(int signo, siginfo_t* siginfo, void* ucontext_r call_tl_lock_dump->install_new_tls_tl_lock, call_tl_lock_dump->set_syscall_hooks_tl_lock, call_tl_lock_dump->set_syscall_hooks_linux_tl_lock, - call_tl_lock_dump->fork_tl_lock); + call_tl_lock_dump->fork_tl_lock, + get_register_count()); if (sig_chains[signo - 1].sca_special_actions[idx].sca_sigaction(signo, siginfo, ucontext_raw)) { set_handling_signal(previous_value); diff --git a/src/thread/linux/pthread_create.c b/src/thread/linux/pthread_create.c index 60a9321af..2f0b21a43 100644 --- a/src/thread/linux/pthread_create.c +++ b/src/thread/linux/pthread_create.c @@ -115,6 +115,7 @@ static int thread_list_lock_after_lock = TID_ERROR_INIT; static int thread_list_lock_pre_unlock = TID_ERROR_INIT; static int thread_list_lock_pthread_exit = TID_ERROR_INIT; static int thread_list_lock_tid_overlimit = TID_ERROR_INIT; +static int register_count = 0; struct call_tl_lock tl_lock_caller_count = { 0 }; @@ -173,6 +174,16 @@ struct call_tl_lock *get_tl_lock_caller_count(void) return &tl_lock_caller_count; } +int get_register_count() +{ + return register_count; +} + +void update_register_count() +{ + register_count++; +} + void __tl_lock(void) { int tid = __pthread_self()->tid; diff --git a/src/thread/pthread_rwlock_unlock.c b/src/thread/pthread_rwlock_unlock.c index 9ae27ad2b..061241185 100644 --- a/src/thread/pthread_rwlock_unlock.c +++ b/src/thread/pthread_rwlock_unlock.c @@ -1,5 +1,14 @@ #include "pthread_impl.h" +// Set a rw lock to init status: PTHREAD_RWLOCK_INITIALIZER +void __pthread__rwlock_unlock_inner(pthread_rwlock_t *m) +{ + char *p = (char *)m; + for (size_t i = 0;i < sizeof(pthread_rwlock_t);i++) { + *(p + i) = 0; + } +} + int __pthread_rwlock_unlock(pthread_rwlock_t *rw) { int val, cnt, waiters, new, priv = rw->_rw_shared^128; -- Gitee