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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c
index c92d54c..6f51b04 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -897,28 +897,19 @@
 }
 
 
-/*-------------------*/
-/* 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 840282b..f5e6658 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -478,6 +478,8 @@
 #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 c92d54c..6f51b04 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -897,28 +897,19 @@
 }
 
 
-/*-------------------*/
-/* 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 9db5021..228a8a3 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -1706,8 +1706,9 @@
       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 @@
                                       (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 840282b..f5e6658 100644
--- a/vg_include.h
+++ b/vg_include.h
@@ -478,6 +478,8 @@
 #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 c92d54c..6f51b04 100644
--- a/vg_libpthread.c
+++ b/vg_libpthread.c
@@ -897,28 +897,19 @@
 }
 
 
-/*-------------------*/
-/* 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 9db5021..228a8a3 100644
--- a/vg_scheduler.c
+++ b/vg_scheduler.c
@@ -1706,8 +1706,9 @@
       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 @@
                                       (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: