diff options
author | David S. Miller <davem@davemloft.net> | 2011-09-05 10:01:52 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-09-05 10:01:52 -0700 |
commit | 39c4451cecac1bc3c3bccf53521333cef18d37c6 (patch) | |
tree | c2785b3b70516e8e0f0aab0f9d38398d4a84a710 | |
parent | 3b142ce5728f6d683f3375fb33099ebf243f6681 (diff) | |
download | glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.tar.gz glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.tar.xz glibc-39c4451cecac1bc3c3bccf53521333cef18d37c6.zip |
Fix nptl semaphore cleanup invocation.
-rw-r--r-- | nptl/ChangeLog | 14 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sem_timedwait.c | 26 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sem_wait.c | 24 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c | 26 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c | 24 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c | 26 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c | 24 |
7 files changed, 107 insertions, 57 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index c44ce2af6f..caae5dcf3c 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -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 diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c index fdf0d74011..cb3b78fe67 100644 --- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c +++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c @@ -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) @@ -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); diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c index 20e2b481df..602c38246f 100644 --- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -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) @@ -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); diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c index 01952f3f9a..fdd09affea 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c @@ -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) @@ -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); diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c index a846f20601..4a2c9357a0 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c @@ -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) @@ -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); diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c index 55f3e2e075..90edbc5dd0 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c @@ -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) @@ -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); diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c index b14f976a61..8fba4b7d7e 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c @@ -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) @@ -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); |