From 55d774cbf800ab60830bf525496e088f1bba1949 Mon Sep 17 00:00:00 2001 From: liyiming13 Date: Tue, 12 Nov 2024 20:43:36 +0800 Subject: [PATCH] Add tl_lock more dfx Issue:https://gitee.com/openharmony/third_party_musl/issues/IB3U8Q?from=project-issue Test:libc-test Signed-off-by: liyiming13 --- ldso/linux/dynlink.c | 6 +++ src/internal/pthread_impl.h | 19 ++++++++ src/linux/membarrier.c | 13 ++++++ src/linux/syscall_hooks/syscall_hooks.c | 6 +++ src/process/fork.c | 13 ++++++ src/sigchain/linux/sigchain.c | 35 +++++++++++++- src/syscall_hooks/linux/syscall_hooks.c | 7 +++ src/thread/linux/pthread_create.c | 61 +++++++++++++++++++++++++ src/thread/pthread_key_create.c | 13 ++++++ src/thread/synccall.c | 13 ++++++ 10 files changed, 184 insertions(+), 2 deletions(-) diff --git a/ldso/linux/dynlink.c b/ldso/linux/dynlink.c index c7431d1f3..e8a06b1ac 100644 --- a/ldso/linux/dynlink.c +++ b/ldso/linux/dynlink.c @@ -2848,6 +2848,9 @@ static void install_new_tls(void) __block_app_sigs(&set); __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->install_new_tls_tl_lock++; + } /* Copy existing dtv contents from all existing threads. */ for (i=0, td=self; !i || td!=self; i++, td=td->next) { memcpy(newdtv+i, td->dtv, @@ -2882,6 +2885,9 @@ static void install_new_tls(void) td->dtv = newdtv[j]; } + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->install_new_tls_tl_lock--; + } __tl_unlock(); __restore_sigs(&set); } diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index b84db77bc..1429bdc39 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -277,6 +277,22 @@ hidden void __acquire_ptc(void); hidden void __release_ptc(void); hidden void __inhibit_ptc(void); +typedef struct call_tl_lock { + int tl_lock_unlock_count; + int __pthread_gettid_np_tl_lock; + int __pthread_exit_tl_lock; + int __pthread_create_tl_lock; + int __pthread_key_delete_tl_lock; + int __synccall_tl_lock; + int __membarrier_tl_lock; + int install_new_tls_tl_lock; + int set_syscall_hooks_tl_lock; + int set_syscall_hooks_linux_tl_lock; + int fork_tl_lock; +}; + +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); @@ -288,6 +304,9 @@ hidden int get_tl_lock_count_tid_sub(void); hidden int get_tl_lock_count_fail(void); hidden int get_thread_list_lock_after_lock(void); hidden int get_thread_list_lock_pre_unlock(void); +hidden int get_thread_list_lock_pthread_exit(void); +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); diff --git a/src/linux/membarrier.c b/src/linux/membarrier.c index f64fe7e18..fdfa6398b 100644 --- a/src/linux/membarrier.c +++ b/src/linux/membarrier.c @@ -12,6 +12,13 @@ static void dummy_0(void) weak_alias(dummy_0, __tl_lock); weak_alias(dummy_0, __tl_unlock); +static struct call_tl_lock *dummy_get_tl_lock_caller_count(void) +{ + return NULL; +} + +weak_alias(dummy_get_tl_lock_caller_count, get_tl_lock_caller_count); + static sem_t barrier_sem; static void bcast_barrier(int s) @@ -33,6 +40,9 @@ int __membarrier(int cmd, int flags) sigset_t set; __block_app_sigs(&set); __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__membarrier_tl_lock++; + } sem_init(&barrier_sem, 0, 0); struct sigaction sa = { .sa_flags = SA_RESTART | SA_ONSTACK, @@ -49,6 +59,9 @@ int __membarrier(int cmd, int flags) __libc_sigaction(SIGSYNCCALL, &sa, 0); } sem_destroy(&barrier_sem); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__membarrier_tl_lock--; + } __tl_unlock(); __restore_sigs(&set); } diff --git a/src/linux/syscall_hooks/syscall_hooks.c b/src/linux/syscall_hooks/syscall_hooks.c index 28ddcfd49..787bdd5bf 100644 --- a/src/linux/syscall_hooks/syscall_hooks.c +++ b/src/linux/syscall_hooks/syscall_hooks.c @@ -55,6 +55,9 @@ int set_syscall_hooks(const char *hooks_table, int table_len, void *hooks_entry, if (ret == 0) { __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->set_syscall_hooks_tl_lock++; + } if (!libc.threads_minus_1) { if (reset) { g_syscall_hooks_entry = NULL; @@ -67,6 +70,9 @@ int set_syscall_hooks(const char *hooks_table, int table_len, void *hooks_entry, } else { ret = -EPERM; } + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->set_syscall_hooks_tl_lock--; + } __tl_unlock(); } diff --git a/src/process/fork.c b/src/process/fork.c index 5e44cab53..c1f8d092e 100644 --- a/src/process/fork.c +++ b/src/process/fork.c @@ -45,6 +45,13 @@ static void dummy_0(void) { } weak_alias(dummy_0, __tl_lock); weak_alias(dummy_0, __tl_unlock); +static struct call_tl_lock *dummy_get_tl_lock_caller_count(void) +{ + return NULL; +} + +weak_alias(dummy_get_tl_lock_caller_count, get_tl_lock_caller_count); + pid_t fork(void) { sigset_t set; @@ -60,6 +67,9 @@ pid_t fork(void) if (*atfork_locks[i]) LOCK(*atfork_locks[i]); __malloc_atfork(-1); __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->fork_tl_lock++; + } } pthread_t self=__pthread_self(), next=self->next; pid_t ret = _Fork(); @@ -73,6 +83,9 @@ pid_t fork(void) __vmlock_lockptr[1] = 0; } } + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->fork_tl_lock--; + } __tl_unlock(); __malloc_atfork(!ret); for (int i=0; itl_lock_unlock_count, + call_tl_lock_dump->__pthread_gettid_np_tl_lock, + call_tl_lock_dump->__pthread_exit_tl_lock, + call_tl_lock_dump->__pthread_create_tl_lock, + call_tl_lock_dump->__pthread_key_delete_tl_lock, + call_tl_lock_dump->__synccall_tl_lock, + call_tl_lock_dump->__membarrier_tl_lock, + 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); if (sig_chains[signo - 1].sca_special_actions[idx].sca_sigaction(signo, siginfo, ucontext_raw)) { set_handling_signal(previous_value); diff --git a/src/syscall_hooks/linux/syscall_hooks.c b/src/syscall_hooks/linux/syscall_hooks.c index 28ddcfd49..a78372997 100644 --- a/src/syscall_hooks/linux/syscall_hooks.c +++ b/src/syscall_hooks/linux/syscall_hooks.c @@ -55,6 +55,10 @@ int set_syscall_hooks(const char *hooks_table, int table_len, void *hooks_entry, if (ret == 0) { __tl_lock(); + + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->set_syscall_hooks_linux_tl_lock++; + } if (!libc.threads_minus_1) { if (reset) { g_syscall_hooks_entry = NULL; @@ -67,6 +71,9 @@ int set_syscall_hooks(const char *hooks_table, int table_len, void *hooks_entry, } else { ret = -EPERM; } + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->set_syscall_hooks_linux_tl_lock--; + } __tl_unlock(); } diff --git a/src/thread/linux/pthread_create.c b/src/thread/linux/pthread_create.c index 2a8c03fc5..8617cd9b8 100644 --- a/src/thread/linux/pthread_create.c +++ b/src/thread/linux/pthread_create.c @@ -113,6 +113,10 @@ static int tl_lock_count_tid_sub = TID_ERROR_INIT; static int tl_lock_count_fail = COUNT_ERROR_INIT; 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; + +struct call_tl_lock tl_lock_caller_count = { 0 }; int get_tl_lock_count(void) { @@ -154,6 +158,21 @@ int get_thread_list_lock_pre_unlock(void) return thread_list_lock_pre_unlock; } +int get_thread_list_lock_pthread_exit(void) +{ + return thread_list_lock_pthread_exit; +} + +int get_thread_list_lock_tid_overlimit(void) +{ + return thread_list_lock_tid_overlimit; +} + +struct call_tl_lock *get_tl_lock_caller_count(void) +{ + return &tl_lock_caller_count; +} + void __tl_lock(void) { int tid = __pthread_self()->tid; @@ -161,6 +180,10 @@ void __tl_lock(void) tl_lock_tid_fail = TID_ERROR_0; tid = __syscall(SYS_gettid); } + if ((thread_list_lock_pthread_exit == tid) && + (thread_list_lock_pthread_exit == __thread_list_lock)) { + thread_list_lock_tid_overlimit = __thread_list_lock; + } int val = __thread_list_lock; if (val == tid) { tl_lock_count++; @@ -170,6 +193,9 @@ void __tl_lock(void) while ((val = a_cas(&__thread_list_lock, 0, tid))) __wait(&__thread_list_lock, &tl_lock_waiters, val, 0); thread_list_lock_after_lock = __thread_list_lock; + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->tl_lock_unlock_count++; + } } void __tl_unlock(void) @@ -180,6 +206,9 @@ void __tl_unlock(void) return; } thread_list_lock_pre_unlock = __thread_list_lock; + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->tl_lock_unlock_count--; + } a_store(&__thread_list_lock, 0); if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0); } @@ -251,6 +280,9 @@ _Noreturn void __pthread_exit(void *result) /* The thread list lock must be AS-safe, and thus depends on * application signals being blocked above. */ __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_exit_tl_lock++; + } #ifdef RESERVE_SIGNAL_STACK __pthread_release_signal_stack(); @@ -259,6 +291,9 @@ _Noreturn void __pthread_exit(void *result) * termination of the thread, but restore the previous lock and * signal state to prepare for exit to call atexit handlers. */ if (self->next == self) { + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_exit_tl_lock--; + } __tl_unlock(); UNLOCK(self->killlock); self->detach_state = state; @@ -326,6 +361,15 @@ _Noreturn void __pthread_exit(void *result) /* The following call unmaps the thread's stack mapping * and then exits without touching the stack. */ + if(tl_lock_count != 0) { + tl_lock_count_fail = tl_lock_count; + tl_lock_count = 0; + } + thread_list_lock_pthread_exit = __thread_list_lock; + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_exit_tl_lock--; + get_tl_lock_caller_count()->tl_lock_unlock_count--; + } __unmapself(self->map_base, self->map_size); } @@ -344,6 +388,11 @@ _Noreturn void __pthread_exit(void *result) tl_lock_count_fail = tl_lock_count; tl_lock_count = 0; } + thread_list_lock_pthread_exit = __thread_list_lock; + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_exit_tl_lock--; + get_tl_lock_caller_count()->tl_lock_unlock_count--; + } for (;;) __syscall(SYS_exit, 0); } @@ -560,6 +609,9 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long)))); __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_create_tl_lock++; + } if (!libc.threads_minus_1++) libc.need_locks = 1; ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock); @@ -588,6 +640,9 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att } else { if (!--libc.threads_minus_1) libc.need_locks = 0; } + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_create_tl_lock--; + } __tl_unlock(); __restore_sigs(&set); __release_ptc(); @@ -633,7 +688,13 @@ struct pthread* __pthread_list_find(pthread_t thread_id, const char* info) pid_t __pthread_gettid_np(pthread_t t) { __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_gettid_np_tl_lock++; + } struct pthread* thread = __pthread_list_find(t, "pthread_gettid_np"); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_gettid_np_tl_lock--; + } __tl_unlock(); return thread ? thread->tid : -1; } diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index 95e037a72..2ddf486ae 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -23,6 +23,13 @@ static void dummy_0(void) weak_alias(dummy_0, __tl_lock); weak_alias(dummy_0, __tl_unlock); +static struct call_tl_lock *dummy_get_tl_lock_caller_count(void) +{ + return NULL; +} + +weak_alias(dummy_get_tl_lock_caller_count, get_tl_lock_caller_count); + void __pthread_key_atfork(int who) { if (who<0) __pthread_rwlock_rdlock(&key_lock); @@ -64,8 +71,14 @@ int __pthread_key_delete(pthread_key_t k) __pthread_rwlock_wrlock(&key_lock); __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_key_delete_tl_lock++; + } do td->tsd[k] = 0; while ((td=td->next)!=self); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__pthread_key_delete_tl_lock--; + } __tl_unlock(); keys[k] = 0; diff --git a/src/thread/synccall.c b/src/thread/synccall.c index a6b177c06..bad40eb41 100644 --- a/src/thread/synccall.c +++ b/src/thread/synccall.c @@ -17,6 +17,13 @@ static void dummy(void *p) { } +static struct call_tl_lock *dummy_get_tl_lock_caller_count(void) +{ + return NULL; +} + +weak_alias(dummy_get_tl_lock_caller_count, get_tl_lock_caller_count); + static void handler(int sig) { if (__pthread_self()->tid != target_tid) return; @@ -57,6 +64,9 @@ void __synccall(void (*func)(void *), void *ctx) * with the lock already held. */ __block_app_sigs(&oldmask); __tl_lock(); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__synccall_tl_lock++; + } __block_all_sigs(0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); @@ -115,6 +125,9 @@ single_threaded: sem_destroy(&target_sem); pthread_setcancelstate(cs, 0); + if (get_tl_lock_caller_count()) { + get_tl_lock_caller_count()->__synccall_tl_lock--; + } __tl_unlock(); __restore_sigs(&oldmask); } -- Gitee