This patch fixes both sem_wait and sem_timedwait cancellation point for
uncontended case. In this scenario only atomics are involved and thus
the futex cancellable call is not issue and a pending cancellation signal
is not handled.
The fix is straighforward by calling pthread_testcancel is both function
start. Although it would be simpler to call CANCELLATION_P directly, I
decided to add an internal pthread_testcancel alias and use it to export
less internal implementation on such function. A possible change on
how pthread_testcancel is internally implemented would lead to either
continue to force use CANCELLATION_P or to adjust its every use.
GLIBC testcase also does have tests for uncontended cases, test-cancel12
and test-cancel14.c, however both are flawed by adding another
cancellation point just after thread pthread_cleanup_pop:
47 static void *
48 tf (void *arg)
49 {
50 pthread_cleanup_push (cleanup, NULL);
51
52 int e = pthread_barrier_wait (&bar);
53 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
54 {
55 puts ("tf: 1st barrier_wait failed");
56 exit (1);
57 }
58
59 /* This call should block and be cancelable. */
60 sem_wait (&sem);
61
62 pthread_cleanup_pop (0);
63
64 puts ("sem_wait returned");
65
66 return NULL;
67 }
So sem_{timed}wait does not act on cancellation, pthread_cleanup_pop executes
'cleanup' and then 'puts' acts on cancellation. Since pthread_cleanup_pop
removed the clean-up handler, it will ran only once and thus it won't accuse
an error to indicate sem_wait has not acted on the cancellation signal.
This patch also fixes this behavior by removing the cancellation point 'puts'.
It also adds some cleanup on all sem_{timed}wait cancel tests.
It partially fixes BZ #18243. Checked on x86_64.
[BZ #18243]
* nptl/pthreadP.h (__pthread_testcancel): Add prototype and hidden_proto.
* nptl/pthread_testcancel.c (pthread_cancel): Add internal aliais
definition.
* nptl/sem_timedwait.c (sem_timedwait): Add cancellation check for
uncontended case.
* nptl/sem_wait.c (__new_sem_wait): Likewise.
* nptl/tst-cancel12.c (cleanup): Remove wrong cancellation point.
(tf): Fix check for uncontended case.
(do_test): Likewise.
* nptl/tst-cancel13.c (cleanup): Remove wrong cancellation point.
(tf): Fix check for uncontended case.
(do_test): Likewise.
* nptl/tst-cancel14.c (cleanup): Remove wrong cancellation point.
(tf): Fix check for uncontended case.
(do_test): Likewise.
* nptl/tst-cancel15.c (cleanup): Remove wrong cancellation point.
(tf): Fix check for uncontended case.
(do_test): Likewise.
This commit fixes semaphore destruction by either using 64b atomic
operations (where available), or by using two separate fields when only
32b atomic operations are available. In the latter case, we keep a
conservative estimate of whether there are any waiting threads in one
bit of the field that counts the number of available tokens, thus
allowing sem_post to atomically both add a token and determine whether
it needs to call futex_wake.
See:
https://sourceware.org/ml/libc-alpha/2014-12/msg00155.html