]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
When a thread exits, run the destructors for the thread's specific data.
authorJulian Seward <jseward@acm.org>
Wed, 29 May 2002 01:06:47 +0000 (01:06 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 29 May 2002 01:06:47 +0000 (01:06 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@330

coregrind/arch/x86-linux/vg_libpthread.c
coregrind/vg_include.h
coregrind/vg_libpthread.c
coregrind/vg_scheduler.c
vg_include.h
vg_libpthread.c
vg_scheduler.c

index 7fba3b0f80efa256279d0e6b3a83722c525d929b..d98b73076a8e0510535c06653fa7f8beb23a794f 100644 (file)
@@ -279,8 +279,10 @@ static
 __attribute__((noreturn))
 void thread_exit_wrapper ( void* ret_val )
 {
-   int          detached, res;
-   CleanupEntry cu;
+   int           detached, res;
+   CleanupEntry  cu;
+   pthread_key_t key;
+
    /* Run this thread's cleanup handlers. */
    while (1) {
       VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
@@ -292,7 +294,21 @@ void thread_exit_wrapper ( void* ret_val )
       cu.fn ( cu.arg );
    }
 
-   /* Run this thread's key finalizers. */
+   /* Run this thread's key finalizers.  Really this should be run
+      PTHREAD_DESTRUCTOR_ITERATIONS times. */
+   for (key = 0; key < VG_N_THREAD_KEYS; key++) {
+      VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
+                              VG_USERREQ__GET_KEY_D_AND_S,
+                              key, &cu, 0, 0 );
+      if (res == 0) {
+         /* valid key */
+         if (cu.fn && cu.arg)
+            cu.fn /* destructor for key */ 
+                  ( cu.arg /* specific for key for this thread */ );
+         continue;
+      }
+      assert(res == -1);
+   }
 
    /* Decide on my final disposition. */
    VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
index 6a078f631c4d8fa3924fb9c085b2b7799d900971..290fbec7395f7c24e5120e0be08d868227b502f5 100644 (file)
@@ -476,6 +476,7 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 
 #define VG_USERREQ__CLEANUP_PUSH            0x3020
 #define VG_USERREQ__CLEANUP_POP             0x3021
+#define VG_USERREQ__GET_KEY_D_AND_S         0x3022
 
 /* Cosmetic ... */
 #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101
index 7fba3b0f80efa256279d0e6b3a83722c525d929b..d98b73076a8e0510535c06653fa7f8beb23a794f 100644 (file)
@@ -279,8 +279,10 @@ static
 __attribute__((noreturn))
 void thread_exit_wrapper ( void* ret_val )
 {
-   int          detached, res;
-   CleanupEntry cu;
+   int           detached, res;
+   CleanupEntry  cu;
+   pthread_key_t key;
+
    /* Run this thread's cleanup handlers. */
    while (1) {
       VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
@@ -292,7 +294,21 @@ void thread_exit_wrapper ( void* ret_val )
       cu.fn ( cu.arg );
    }
 
-   /* Run this thread's key finalizers. */
+   /* Run this thread's key finalizers.  Really this should be run
+      PTHREAD_DESTRUCTOR_ITERATIONS times. */
+   for (key = 0; key < VG_N_THREAD_KEYS; key++) {
+      VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
+                              VG_USERREQ__GET_KEY_D_AND_S,
+                              key, &cu, 0, 0 );
+      if (res == 0) {
+         /* valid key */
+         if (cu.fn && cu.arg)
+            cu.fn /* destructor for key */ 
+                  ( cu.arg /* specific for key for this thread */ );
+         continue;
+      }
+      assert(res == -1);
+   }
 
    /* Decide on my final disposition. */
    VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
index 7eeee5181c16a4a78e17df067bb507eaf2541d5c..60c6c28e88c1a596dbe71a4a3db8ffde2eb73bfe 100644 (file)
@@ -2672,7 +2672,8 @@ void do_pthread_key_create ( ThreadId tid,
                  " increase and recompile");
    }
 
-   vg_thread_keys[i].inuse = True;
+   vg_thread_keys[i].inuse      = True;
+   vg_thread_keys[i].destructor = destructor;
 
    /* TODO: check key for addressibility */
    *key = i;
@@ -2762,6 +2763,33 @@ void do_pthread_setspecific ( ThreadId tid,
 }
 
 
+/* Helper for calling destructors at thread exit.  If key is valid,
+   copy the thread's specific value into cu->arg and put the *key*'s
+   destructor fn address in cu->fn.  Then return 0 to the caller.
+   Otherwise return non-zero to the caller. */
+static
+void do__get_key_destr_and_spec ( ThreadId tid, 
+                                  pthread_key_t key,
+                                  CleanupEntry* cu )
+{
+   Char msg_buf[100];
+   if (VG_(clo_trace_pthread_level) >= 1) {
+      VG_(sprintf)(msg_buf, 
+         "get_key_destr_and_arg (key = %d)", key );
+      print_pthread_event(tid, msg_buf);
+   }
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(key >= 0 && key < VG_N_THREAD_KEYS);
+   if (!vg_thread_keys[key].inuse) {
+      SET_EDX(tid, -1);
+      return;
+   }
+   cu->fn = vg_thread_keys[key].destructor;
+   cu->arg = VG_(threads)[tid].specifics[key];
+   SET_EDX(tid, 0);
+}
+
+
 /* ---------------------------------------------------
    SIGNALS
    ------------------------------------------------ */
@@ -2971,6 +2999,12 @@ void do_nontrivial_clientreq ( ThreadId tid )
                                         (void*)arg[2] );
          break;
 
+      case VG_USERREQ__GET_KEY_D_AND_S:
+         do__get_key_destr_and_spec ( tid, 
+                                      (pthread_key_t)arg[1],
+                                      (CleanupEntry*)arg[2] );
+         break;
+
       case VG_USERREQ__MAKE_NOACCESS:
       case VG_USERREQ__MAKE_WRITABLE:
       case VG_USERREQ__MAKE_READABLE:
index 6a078f631c4d8fa3924fb9c085b2b7799d900971..290fbec7395f7c24e5120e0be08d868227b502f5 100644 (file)
@@ -476,6 +476,7 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 
 #define VG_USERREQ__CLEANUP_PUSH            0x3020
 #define VG_USERREQ__CLEANUP_POP             0x3021
+#define VG_USERREQ__GET_KEY_D_AND_S         0x3022
 
 /* Cosmetic ... */
 #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101
index 7fba3b0f80efa256279d0e6b3a83722c525d929b..d98b73076a8e0510535c06653fa7f8beb23a794f 100644 (file)
@@ -279,8 +279,10 @@ static
 __attribute__((noreturn))
 void thread_exit_wrapper ( void* ret_val )
 {
-   int          detached, res;
-   CleanupEntry cu;
+   int           detached, res;
+   CleanupEntry  cu;
+   pthread_key_t key;
+
    /* Run this thread's cleanup handlers. */
    while (1) {
       VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
@@ -292,7 +294,21 @@ void thread_exit_wrapper ( void* ret_val )
       cu.fn ( cu.arg );
    }
 
-   /* Run this thread's key finalizers. */
+   /* Run this thread's key finalizers.  Really this should be run
+      PTHREAD_DESTRUCTOR_ITERATIONS times. */
+   for (key = 0; key < VG_N_THREAD_KEYS; key++) {
+      VALGRIND_MAGIC_SEQUENCE(res, (-2) /* default */,
+                              VG_USERREQ__GET_KEY_D_AND_S,
+                              key, &cu, 0, 0 );
+      if (res == 0) {
+         /* valid key */
+         if (cu.fn && cu.arg)
+            cu.fn /* destructor for key */ 
+                  ( cu.arg /* specific for key for this thread */ );
+         continue;
+      }
+      assert(res == -1);
+   }
 
    /* Decide on my final disposition. */
    VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
index 7eeee5181c16a4a78e17df067bb507eaf2541d5c..60c6c28e88c1a596dbe71a4a3db8ffde2eb73bfe 100644 (file)
@@ -2672,7 +2672,8 @@ void do_pthread_key_create ( ThreadId tid,
                  " increase and recompile");
    }
 
-   vg_thread_keys[i].inuse = True;
+   vg_thread_keys[i].inuse      = True;
+   vg_thread_keys[i].destructor = destructor;
 
    /* TODO: check key for addressibility */
    *key = i;
@@ -2762,6 +2763,33 @@ void do_pthread_setspecific ( ThreadId tid,
 }
 
 
+/* Helper for calling destructors at thread exit.  If key is valid,
+   copy the thread's specific value into cu->arg and put the *key*'s
+   destructor fn address in cu->fn.  Then return 0 to the caller.
+   Otherwise return non-zero to the caller. */
+static
+void do__get_key_destr_and_spec ( ThreadId tid, 
+                                  pthread_key_t key,
+                                  CleanupEntry* cu )
+{
+   Char msg_buf[100];
+   if (VG_(clo_trace_pthread_level) >= 1) {
+      VG_(sprintf)(msg_buf, 
+         "get_key_destr_and_arg (key = %d)", key );
+      print_pthread_event(tid, msg_buf);
+   }
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(key >= 0 && key < VG_N_THREAD_KEYS);
+   if (!vg_thread_keys[key].inuse) {
+      SET_EDX(tid, -1);
+      return;
+   }
+   cu->fn = vg_thread_keys[key].destructor;
+   cu->arg = VG_(threads)[tid].specifics[key];
+   SET_EDX(tid, 0);
+}
+
+
 /* ---------------------------------------------------
    SIGNALS
    ------------------------------------------------ */
@@ -2971,6 +2999,12 @@ void do_nontrivial_clientreq ( ThreadId tid )
                                         (void*)arg[2] );
          break;
 
+      case VG_USERREQ__GET_KEY_D_AND_S:
+         do__get_key_destr_and_spec ( tid, 
+                                      (pthread_key_t)arg[1],
+                                      (CleanupEntry*)arg[2] );
+         break;
+
       case VG_USERREQ__MAKE_NOACCESS:
       case VG_USERREQ__MAKE_WRITABLE:
       case VG_USERREQ__MAKE_READABLE: