From: Julian Seward Date: Thu, 30 May 2002 00:40:03 +0000 (+0000) Subject: Implement __pthread_kill_other_threads_np properly. It does seem to X-Git-Tag: svn/VALGRIND_1_0_3~124 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=89ff2f0b24217bfa990706c860b7d5f202efd40d;p=thirdparty%2Fvalgrind.git Implement __pthread_kill_other_threads_np properly. It does seem to be needed after all. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@342 --- diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c index c92d54c8f5..6f51b04aae 100644 --- a/coregrind/arch/x86-linux/vg_libpthread.c +++ b/coregrind/arch/x86-linux/vg_libpthread.c @@ -897,28 +897,19 @@ void pthread_testcancel ( void ) } -/*-------------------*/ -/* If this is indeed used by LinuxThreads to implement thread nuking - post fork and pre exec, we should really nuke em, not do - pthread_cancel. */ -static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER; - +/* Not really sure what this is for. I suspect for doing the POSIX + requirements for fork() and exec(). We do this internally anyway + whenever those syscalls are observed, so this could be superfluous, + but hey ... +*/ void __pthread_kill_other_threads_np ( void ) { - /* If we need this, implement it properly! */ - vgPlain_unimp("__pthread_kill_other_threads_np"); -#if 0 - int i, res, me; - __pthread_mutex_lock(&massacre_mx); - me = pthread_self(); - for (i = 1; i < VG_N_THREADS; i++) { - if (i == me) continue; - res = pthread_cancel(i); - if (0 && res == 0) - printf("----------- NUKED %d\n", i); - } - __pthread_mutex_unlock(&massacre_mx); -#endif + int res; + ensure_valgrind("__pthread_kill_other_threads_np"); + VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */, + VG_USERREQ__NUKE_OTHER_THREADS, + 0, 0, 0, 0); + assert(res == 0); } diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 840282b200..f5e665823b 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -478,6 +478,8 @@ extern Bool VG_(is_empty_arena) ( ArenaId aid ); #define VG_USERREQ__CLEANUP_POP 0x3021 #define VG_USERREQ__GET_KEY_D_AND_S 0x3022 +#define VG_USERREQ__NUKE_OTHER_THREADS 0x3023 + /* Cosmetic ... */ #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101 diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c index c92d54c8f5..6f51b04aae 100644 --- a/coregrind/vg_libpthread.c +++ b/coregrind/vg_libpthread.c @@ -897,28 +897,19 @@ void pthread_testcancel ( void ) } -/*-------------------*/ -/* If this is indeed used by LinuxThreads to implement thread nuking - post fork and pre exec, we should really nuke em, not do - pthread_cancel. */ -static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER; - +/* Not really sure what this is for. I suspect for doing the POSIX + requirements for fork() and exec(). We do this internally anyway + whenever those syscalls are observed, so this could be superfluous, + but hey ... +*/ void __pthread_kill_other_threads_np ( void ) { - /* If we need this, implement it properly! */ - vgPlain_unimp("__pthread_kill_other_threads_np"); -#if 0 - int i, res, me; - __pthread_mutex_lock(&massacre_mx); - me = pthread_self(); - for (i = 1; i < VG_N_THREADS; i++) { - if (i == me) continue; - res = pthread_cancel(i); - if (0 && res == 0) - printf("----------- NUKED %d\n", i); - } - __pthread_mutex_unlock(&massacre_mx); -#endif + int res; + ensure_valgrind("__pthread_kill_other_threads_np"); + VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */, + VG_USERREQ__NUKE_OTHER_THREADS, + 0, 0, 0, 0); + assert(res == 0); } diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 9db5021e69..228a8a3d75 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -1706,8 +1706,9 @@ void VG_(nuke_all_threads_except) ( ThreadId me ) if (tid == me || VG_(threads)[tid].status == VgTs_Empty) continue; - VG_(printf)( - "VG_(nuke_all_threads_except): nuking tid %d\n", tid); + if (0) + VG_(printf)( + "VG_(nuke_all_threads_except): nuking tid %d\n", tid); VG_(threads)[tid].status = VgTs_Empty; cleanup_after_thread_exited( tid ); } @@ -3044,6 +3045,11 @@ void do_nontrivial_clientreq ( ThreadId tid ) (CleanupEntry*)arg[2] ); break; + case VG_USERREQ__NUKE_OTHER_THREADS: + VG_(nuke_all_threads_except) ( tid ); + SET_EDX(tid, 0); + break; + case VG_USERREQ__MAKE_NOACCESS: case VG_USERREQ__MAKE_WRITABLE: case VG_USERREQ__MAKE_READABLE: diff --git a/vg_include.h b/vg_include.h index 840282b200..f5e665823b 100644 --- a/vg_include.h +++ b/vg_include.h @@ -478,6 +478,8 @@ extern Bool VG_(is_empty_arena) ( ArenaId aid ); #define VG_USERREQ__CLEANUP_POP 0x3021 #define VG_USERREQ__GET_KEY_D_AND_S 0x3022 +#define VG_USERREQ__NUKE_OTHER_THREADS 0x3023 + /* Cosmetic ... */ #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101 diff --git a/vg_libpthread.c b/vg_libpthread.c index c92d54c8f5..6f51b04aae 100644 --- a/vg_libpthread.c +++ b/vg_libpthread.c @@ -897,28 +897,19 @@ void pthread_testcancel ( void ) } -/*-------------------*/ -/* If this is indeed used by LinuxThreads to implement thread nuking - post fork and pre exec, we should really nuke em, not do - pthread_cancel. */ -static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER; - +/* Not really sure what this is for. I suspect for doing the POSIX + requirements for fork() and exec(). We do this internally anyway + whenever those syscalls are observed, so this could be superfluous, + but hey ... +*/ void __pthread_kill_other_threads_np ( void ) { - /* If we need this, implement it properly! */ - vgPlain_unimp("__pthread_kill_other_threads_np"); -#if 0 - int i, res, me; - __pthread_mutex_lock(&massacre_mx); - me = pthread_self(); - for (i = 1; i < VG_N_THREADS; i++) { - if (i == me) continue; - res = pthread_cancel(i); - if (0 && res == 0) - printf("----------- NUKED %d\n", i); - } - __pthread_mutex_unlock(&massacre_mx); -#endif + int res; + ensure_valgrind("__pthread_kill_other_threads_np"); + VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */, + VG_USERREQ__NUKE_OTHER_THREADS, + 0, 0, 0, 0); + assert(res == 0); } diff --git a/vg_scheduler.c b/vg_scheduler.c index 9db5021e69..228a8a3d75 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -1706,8 +1706,9 @@ void VG_(nuke_all_threads_except) ( ThreadId me ) if (tid == me || VG_(threads)[tid].status == VgTs_Empty) continue; - VG_(printf)( - "VG_(nuke_all_threads_except): nuking tid %d\n", tid); + if (0) + VG_(printf)( + "VG_(nuke_all_threads_except): nuking tid %d\n", tid); VG_(threads)[tid].status = VgTs_Empty; cleanup_after_thread_exited( tid ); } @@ -3044,6 +3045,11 @@ void do_nontrivial_clientreq ( ThreadId tid ) (CleanupEntry*)arg[2] ); break; + case VG_USERREQ__NUKE_OTHER_THREADS: + VG_(nuke_all_threads_except) ( tid ); + SET_EDX(tid, 0); + break; + case VG_USERREQ__MAKE_NOACCESS: case VG_USERREQ__MAKE_WRITABLE: case VG_USERREQ__MAKE_READABLE: