Skip to content

Commit

Permalink
Fix nptl semaphore cleanup invocation.
Browse files Browse the repository at this point in the history
  • Loading branch information
David S. Miller committed Sep 5, 2011
1 parent 3b142ce commit 39c4451
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 57 deletions.
14 changes: 14 additions & 0 deletions nptl/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
2011-09-05 David S. Miller <davem@davemloft.net>

* sysdeps/unix/sysv/linux/sem_timedwait.c (do_futex_timed_wait):
New function.
(sem_timedwait): Call it to force an exception region around
the async cancel enable and the futex operation.
* sysdeps/unix/sysv/linux/sparc/sem_timedwait.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: Likewise.
* sysdeps/unix/sysv/linux/sem_wait.c (do_futex_wait): New function.
(__new_sem_wait): Call it to force an exception region around
the async cancel enable and the futex operation.
* sysdeps/unix/sysv/linux/sparc/sem_wait.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: Likewise.

2011-08-31 Andreas Schwab <schwab@redhat.com>

* allocatestack.c (setxid_mark_thread): Ensure that the exiting
Expand Down
26 changes: 16 additions & 10 deletions nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@

extern void __sem_wait_cleanup (void *arg) attribute_hidden;

/* This is in a seperate function in order to make sure gcc
puts the call site into an exception region, and thus the
cleanups get properly run. */
static int
__attribute__ ((noinline))
do_futex_timed_wait (struct new_sem *isem, struct timespec *rt)
{
int err, oldtype = __pthread_enable_asynccancel ();

err = lll_futex_timed_wait (&isem->value, 0, rt,
isem->private ^ FUTEX_PRIVATE_FLAG);

__pthread_disable_asynccancel (oldtype);
return err;
}

int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
Expand Down Expand Up @@ -80,16 +95,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;

/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();

err = lll_futex_timed_wait (&isem->value, 0, &rt,
isem->private ^ FUTEX_PRIVATE_FLAG);

/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);

err = do_futex_timed_wait(isem, &rt);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);
Expand Down
24 changes: 15 additions & 9 deletions nptl/sysdeps/unix/sysv/linux/sem_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ __sem_wait_cleanup (void *arg)
atomic_decrement (&isem->nwaiters);
}

/* This is in a seperate function in order to make sure gcc
puts the call site into an exception region, and thus the
cleanups get properly run. */
static int
__attribute__ ((noinline))
do_futex_wait (struct new_sem *isem)
{
int err, oldtype = __pthread_enable_asynccancel ();

err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);

__pthread_disable_asynccancel (oldtype);
return err;
}

int
__new_sem_wait (sem_t *sem)
Expand All @@ -53,15 +67,7 @@ __new_sem_wait (sem_t *sem)

while (1)
{
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();

err = lll_futex_wait (&isem->value, 0,
isem->private ^ FUTEX_PRIVATE_FLAG);

/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);

err = do_futex_wait(isem);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);
Expand Down
26 changes: 16 additions & 10 deletions nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@

extern void __sem_wait_cleanup (void *arg) attribute_hidden;

/* This is in a seperate function in order to make sure gcc
puts the call site into an exception region, and thus the
cleanups get properly run. */
static int
__attribute__ ((noinline))
do_futex_timed_wait (struct sparc_new_sem *isem, struct timespec *rt)
{
int err, oldtype = __pthread_enable_asynccancel ();

err = lll_futex_timed_wait (&isem->value, 0, rt,
isem->private ^ FUTEX_PRIVATE_FLAG);

__pthread_disable_asynccancel (oldtype);
return err;
}

int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
Expand Down Expand Up @@ -80,16 +95,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;

/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();

err = lll_futex_timed_wait (&isem->value, 0, &rt,
isem->private ^ FUTEX_PRIVATE_FLAG);

/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);

err = do_futex_timed_wait(isem, &rt);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);
Expand Down
24 changes: 15 additions & 9 deletions nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ __sem_wait_cleanup (void *arg)
atomic_decrement (&isem->nwaiters);
}

/* This is in a seperate function in order to make sure gcc
puts the call site into an exception region, and thus the
cleanups get properly run. */
static int
__attribute__ ((noinline))
do_futex_wait (struct sparc_new_sem *isem)
{
int err, oldtype = __pthread_enable_asynccancel ();

err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);

__pthread_disable_asynccancel (oldtype);
return err;
}

int
__new_sem_wait (sem_t *sem)
Expand All @@ -53,15 +67,7 @@ __new_sem_wait (sem_t *sem)

while (1)
{
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();

err = lll_futex_wait (&isem->value, 0,
isem->private ^ FUTEX_PRIVATE_FLAG);

/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);

err = do_futex_wait(isem);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);
Expand Down
26 changes: 16 additions & 10 deletions nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@

extern void __sem_wait_cleanup (void *arg) attribute_hidden;

/* This is in a seperate function in order to make sure gcc
puts the call site into an exception region, and thus the
cleanups get properly run. */
static int
__attribute__ ((noinline))
do_futex_timed_wait (struct sparc_new_sem *isem, struct timespec *rt)
{
int err, oldtype = __pthread_enable_asynccancel ();

err = lll_futex_timed_wait (&isem->value, 0, rt,
isem->private ^ FUTEX_PRIVATE_FLAG);

__pthread_disable_asynccancel (oldtype);
return err;
}

int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
Expand Down Expand Up @@ -99,16 +114,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;

/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();

err = lll_futex_timed_wait (&isem->value, 0, &rt,
isem->private ^ FUTEX_PRIVATE_FLAG);

/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);

err = do_futex_timed_wait(isem, &rt);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);
Expand Down
24 changes: 15 additions & 9 deletions nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ __sem_wait_cleanup (void *arg)
}
}

/* This is in a seperate function in order to make sure gcc
puts the call site into an exception region, and thus the
cleanups get properly run. */
static int
__attribute__ ((noinline))
do_futex_wait (struct sparc_new_sem *isem)
{
int err, oldtype = __pthread_enable_asynccancel ();

err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);

__pthread_disable_asynccancel (oldtype);
return err;
}

int
__new_sem_wait (sem_t *sem)
Expand Down Expand Up @@ -77,15 +91,7 @@ __new_sem_wait (sem_t *sem)

while (1)
{
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();

err = lll_futex_wait (&isem->value, 0,
isem->private ^ FUTEX_PRIVATE_FLAG);

/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);

err = do_futex_wait(isem);
if (err != 0 && err != -EWOULDBLOCK)
{
__set_errno (-err);
Expand Down

0 comments on commit 39c4451

Please sign in to comment.