mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
C11 threads: Fix timeout and locking issues
This commit is contained in:
parent
25123a1c5c
commit
d6b8f84709
14
ChangeLog
14
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>
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user