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