]> sourceware.org Git - glibc.git/commitdiff
C11 threads: Fix timeout and locking issues
authorFlorian Weimer <fweimer@redhat.com>
Wed, 25 Jul 2018 14:31:45 +0000 (16:31 +0200)
committerFlorian Weimer <fweimer@redhat.com>
Wed, 25 Jul 2018 14:31:45 +0000 (16:31 +0200)
ChangeLog
nptl/tst-cnd-basic.c
nptl/tst-cnd-broadcast.c
nptl/tst-cnd-timedwait.c
nptl/tst-mtx-timedlock.c

index 3cf72827072e5366dd5f5e888e0a8917dd21acd7..a7fcb6dfb2fbe585e03e43c4ca5bdec23467a336 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2018-07-25  Florian Weimer  <fweimer@redhat.com>
+
+       * nptl/tst-mtx-timedlock.c (do_test): Implement carry from
+       nanoseconds into seconds.
+       * nptl/tst-cnd-basic.c (signal_parent): Lock and unlock mutex.
+       (do_test): Likewise.
+       * nptl/tst-cnd-timedwait.c (signal_parent): Likewise.
+       (do_test): Likewise.  Avoid nanosecond overflow and spurious
+       timeouts due to system load.
+       * nptl/tst-cnd-broadcast.c (waiting_threads): New variable.
+       (child_wait): Increment it.
+       (do_test): Wait as long as necessary until all expected threads
+       have arrived.
+
 2018-07-25  Vedvyas Shanbhogue  <vedvyas.shanbhogue@intel.com>
            H.J. Lu  <hongjiu.lu@intel.com>
 
index 84b7f5f6476bb287fa8b4682000ff65894088e9e..eb2fb6a77ebf33d4bce0897dc93d28da21316a0b 100644 (file)
@@ -31,8 +31,14 @@ static mtx_t mutex;
 static int
 signal_parent (void)
 {
+  /* Acquire the lock so that cnd_signal does not run until
+     cnd_timedwait has been called.  */
+  if (mtx_lock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_lock failed");
   if (cnd_signal (&cond) != thrd_success)
     FAIL_EXIT1 ("cnd_signal");
+  if (mtx_unlock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_unlock");
 
   thrd_exit (thrd_success);
 }
@@ -47,6 +53,9 @@ do_test (void)
   if (mtx_init (&mutex, mtx_plain) != thrd_success)
     FAIL_EXIT1 ("mtx_init failed");
 
+  if (mtx_lock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_lock failed");
+
   if (thrd_create (&id, (thrd_start_t) signal_parent, NULL)
       != thrd_success)
     FAIL_EXIT1 ("thrd_create failed");
@@ -59,6 +68,9 @@ do_test (void)
   if (thrd_join (id, NULL) != thrd_success)
     FAIL_EXIT1 ("thrd_join failed");
 
+  if (mtx_unlock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_unlock");
+
   mtx_destroy (&mutex);
   cnd_destroy (&cond);
 
index 90d68431543466c7d3f8557920e9fd185a021859..62a4ab5a397812fcb252f333c41053ca3bed70b1 100644 (file)
@@ -17,6 +17,7 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <threads.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -28,12 +29,16 @@ static cnd_t cond;
 /* Mutex to control wait on cond.  */
 static mtx_t mutex;
 
+/* Number of threads which have entered the cnd_wait region.  */
+static unsigned int waiting_threads;
+
 /* Code executed by each thread.  */
 static int
 child_wait (void* data)
 {
   /* Wait until parent thread sends broadcast here.  */
   mtx_lock (&mutex);
+  ++waiting_threads;
   cnd_wait (&cond, &mutex);
   mtx_unlock (&mutex);
 
@@ -61,7 +66,16 @@ do_test (void)
     }
 
   /* Wait for other threads to reach their wait func.  */
-  thrd_sleep (&((struct timespec){.tv_sec = 2}), NULL);
+  while (true)
+    {
+      mtx_lock (&mutex);
+      TEST_VERIFY (waiting_threads <= N);
+      bool done_waiting = waiting_threads == N;
+      mtx_unlock (&mutex);
+      if (done_waiting)
+       break;
+      thrd_sleep (&((struct timespec){.tv_nsec = 100 * 1000 * 1000}), NULL);
+    }
 
   mtx_lock (&mutex);
   if (cnd_broadcast (&cond) != thrd_success)
index 45a15129406fc07c61af137bf6522c4e1f44d3f2..7d8a8e355780a8de2129fc17b858e9971bff0ef5 100644 (file)
@@ -31,8 +31,14 @@ static mtx_t mutex;
 static int
 signal_parent (void *arg)
 {
+  /* Acquire the lock so that cnd_signal does not run until
+     cnd_timedwait has been called.  */
+  if (mtx_lock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_lock failed");
   if (cnd_signal (&cond) != thrd_success)
     FAIL_EXIT1 ("cnd_signal failed");
+  if (mtx_unlock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_unlock");
 
   thrd_exit (thrd_success);
 }
@@ -47,10 +53,15 @@ do_test (void)
     FAIL_EXIT1 ("cnd_init failed");
   if (mtx_init (&mutex, mtx_plain) != thrd_success)
     FAIL_EXIT1 ("mtx_init failed");
+  if (mtx_lock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_lock failed");
 
   if (clock_gettime (CLOCK_REALTIME, &w_time) != 0)
     FAIL_EXIT1 ("clock_gettime failed");
-  w_time.tv_nsec += 150000;
+
+  /* This needs to be sufficiently long to prevent the cnd_timedwait
+     call from timing out.  */
+  w_time.tv_sec += 3600;
 
   if (thrd_create (&id, signal_parent, NULL) != thrd_success)
     FAIL_EXIT1 ("thrd_create failed");
@@ -61,6 +72,9 @@ do_test (void)
   if (thrd_join (id, NULL) != thrd_success)
     FAIL_EXIT1 ("thrd_join failed");
 
+  if (mtx_unlock (&mutex) != thrd_success)
+    FAIL_EXIT1 ("mtx_unlock");
+
   mtx_destroy (&mutex);
   cnd_destroy (&cond);
 
index dcae828fb2a52303c57eed98409e155e02b886a9..616db722eb5800e43842e3b1f28bfe2b33310a62 100644 (file)
@@ -78,6 +78,11 @@ do_test (void)
   /* Tiny amount of time, to assure that if any thread finds it busy.
      It will receive thrd_timedout.  */
   wait_time.tv_nsec += 1;
+  if (wait_time.tv_nsec == 1000 * 1000 * 1000)
+    {
+      wait_time.tv_sec += 1;
+      wait_time.tv_nsec = 0;
+    }
 
   if (thrd_create (&id, child_add, NULL) != thrd_success)
     FAIL_EXIT1 ("thrd_create failed");
This page took 0.187113 seconds and 5 git commands to generate.