5f7b84
commit 6c29942cbf059aca47fd4bbd852ea42c9d46b71f
5f7b84
Author: Stefan Liebler <stli@linux.ibm.com>
5f7b84
Date:   Mon Feb 18 16:12:01 2019 +0100
5f7b84
5f7b84
    misc/tst-clone3: Fix waiting for exited thread.
5f7b84
    
5f7b84
    From time to time the test misc/tst-clone3 fails with a timeout.
5f7b84
    Then futex_wait is blocking.  Usually ctid should be set to zero
5f7b84
    due to CLONE_CHILD_CLEARTID and the futex should be waken up.
5f7b84
    But the fail occures if the thread has already exited before
5f7b84
    ctid is set to the return value of clone().  Then futex_wait() will
5f7b84
    block as there will be nobody who wakes the futex up again.
5f7b84
    
5f7b84
    This patch initializes ctid to a known value before calling clone
5f7b84
    and the kernel is the only one who updates the value to zero after clone.
5f7b84
    If futex_wait is called then it is either waked up due to the exited thread
5f7b84
    or the futex syscall fails as *ctid_ptr is already zero instead of the
5f7b84
    specified value 1.
5f7b84
    
5f7b84
    ChangeLog:
5f7b84
    
5f7b84
            * sysdeps/unix/sysv/linux/tst-clone3.c (do_test):
5f7b84
            Initialize ctid with a known value and remove update of ctid
5f7b84
            after clone.
5f7b84
            (wait_tid): Adjust arguments and call futex_wait with ctid_val
5f7b84
            as assumed current value of ctid_ptr.
5f7b84
5f7b84
diff --git a/sysdeps/unix/sysv/linux/tst-clone3.c b/sysdeps/unix/sysv/linux/tst-clone3.c
5f7b84
index 784ce18f5343ec72..9f1ed6355e7acffd 100644
5f7b84
--- a/sysdeps/unix/sysv/linux/tst-clone3.c
5f7b84
+++ b/sysdeps/unix/sysv/linux/tst-clone3.c
5f7b84
@@ -27,6 +27,7 @@
5f7b84
 
5f7b84
 #include <stackinfo.h>  /* For _STACK_GROWS_{UP,DOWN}.  */
5f7b84
 #include <support/check.h>
5f7b84
+#include <stdatomic.h>
5f7b84
 
5f7b84
 /* Test if clone call with CLONE_THREAD does not call exit_group.  The 'f'
5f7b84
    function returns '1', which will be used by clone thread to call the
5f7b84
@@ -42,11 +43,14 @@ f (void *a)
5f7b84
 
5f7b84
 /* Futex wait for TID argument, similar to pthread_join internal
5f7b84
    implementation.  */
5f7b84
-#define wait_tid(tid) \
5f7b84
-  do {					\
5f7b84
-    __typeof (tid) __tid;		\
5f7b84
-    while ((__tid = (tid)) != 0)	\
5f7b84
-      futex_wait (&(tid), __tid);	\
5f7b84
+#define wait_tid(ctid_ptr, ctid_val)					\
5f7b84
+  do {									\
5f7b84
+    __typeof (*(ctid_ptr)) __tid;					\
5f7b84
+    /* We need acquire MO here so that we synchronize with the		\
5f7b84
+       kernel's store to 0 when the clone terminates.  */		\
5f7b84
+    while ((__tid = atomic_load_explicit (ctid_ptr,			\
5f7b84
+					  memory_order_acquire)) != 0)	\
5f7b84
+      futex_wait (ctid_ptr, ctid_val);					\
5f7b84
   } while (0)
5f7b84
 
5f7b84
 static inline int
5f7b84
@@ -64,7 +68,11 @@ do_test (void)
5f7b84
   clone_flags |= CLONE_VM | CLONE_SIGHAND;
5f7b84
   /* We will used ctid to call on futex to wait for thread exit.  */
5f7b84
   clone_flags |= CLONE_CHILD_CLEARTID;
5f7b84
-  pid_t ctid, tid;
5f7b84
+  /* Initialize with a known value.  ctid is set to zero by the kernel after the
5f7b84
+     cloned thread has exited.  */
5f7b84
+#define CTID_INIT_VAL 1
5f7b84
+  pid_t ctid = CTID_INIT_VAL;
5f7b84
+  pid_t tid;
5f7b84
 
5f7b84
 #ifdef __ia64__
5f7b84
   extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
5f7b84
@@ -86,8 +94,7 @@ do_test (void)
5f7b84
   if (tid == -1)
5f7b84
     FAIL_EXIT1 ("clone failed: %m");
5f7b84
 
5f7b84
-  ctid = tid;
5f7b84
-  wait_tid (ctid);
5f7b84
+  wait_tid (&ctid, CTID_INIT_VAL);
5f7b84
 
5f7b84
   return 2;
5f7b84
 }