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