@@ -1,7 +1,7 @@
2015-01-20 Torvald Riegel <triegel@redhat.com>
[BZ #12674]
- * nptl/sem_waitcommon.c: New file. Implement new semaphore algorithm.
+ * nptl/sem_waitcommon.c: New file.
* nptl/sem_wait.c: Include sem_waitcommon.c.
(__sem_wait_cleanup, do_futex_wait): Remove.
(__new_sem_wait): Adapt.
@@ -77,7 +77,7 @@ __new_sem_post (sem_t *sem)
while (!atomic_compare_exchange_weak_release (&isem->data, &d, d + 1));
/* If there is any potentially blocked waiter, wake one of them. */
- if (d >> SEM_NWAITERS_SHIFT > 0)
+ if ((d >> SEM_NWAITERS_SHIFT) > 0)
futex_wake (((unsigned int *) &isem->data) + SEM_VALUE_OFFSET, 1, private);
#else
/* Add a token to the semaphore. Similar to 64b version. */
@@ -32,11 +32,17 @@
TODO Remove when cleaning up the futex API throughout glibc. */
static __always_inline int
futex_abstimed_wait (unsigned int* futex, unsigned int expected,
- const struct timespec* abstime, int private)
+ const struct timespec* abstime, int private, bool cancel)
{
- int err;
+ int err, oldtype;
if (abstime == NULL)
- err = lll_futex_wait (futex, expected, private);
+ {
+ if (cancel)
+ oldtype = __pthread_enable_asynccancel ();
+ err = lll_futex_wait (futex, expected, private);
+ if (cancel)
+ __pthread_disable_asynccancel (oldtype);
+ }
else
{
struct timeval tv;
@@ -62,8 +68,11 @@ futex_abstimed_wait (unsigned int* futex, unsigned int expected,
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;
-
+ if (cancel)
+ oldtype = __pthread_enable_asynccancel ();
err = lll_futex_timed_wait (futex, expected, &rt, private);
+ if (cancel)
+ __pthread_disable_asynccancel (oldtype);
}
switch (err)
{
@@ -193,17 +202,16 @@ static int
__attribute__ ((noinline))
do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
{
- int err, oldtype = __pthread_enable_asynccancel ();
+ int err;
#if __HAVE_64B_ATOMICS
err = futex_abstimed_wait ((unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0,
- abstime, sem->private);
+ abstime, sem->private, true);
#else
err = futex_abstimed_wait (&sem->value, SEM_NWAITERS_MASK, abstime,
- sem->private);
+ sem->private, true);
#endif
- __pthread_disable_asynccancel (oldtype);
return err;
}