commit ccb4868ca6fabd1d44598e2c4856b9815c4f4594 Author: Torvald Riegel Date: Tue Jul 29 21:44:31 2014 +0200 Update to new generic semaphore algorithm. diff --git a/nptl/DESIGN-sem.txt b/nptl/DESIGN-sem.txt deleted file mode 100644 index 17eb0c1..0000000 --- a/nptl/DESIGN-sem.txt +++ /dev/null @@ -1,46 +0,0 @@ -Semaphores pseudocode -============================== - - int sem_wait(sem_t * sem); - int sem_trywait(sem_t * sem); - int sem_post(sem_t * sem); - int sem_getvalue(sem_t * sem, int * sval); - -struct sem_t { - - unsigned int count; - - current semaphore count, also used as a futex -} - -sem_wait(sem_t *sem) -{ - for (;;) { - - if (atomic_decrement_if_positive(sem->count)) - break; - - futex_wait(&sem->count, 0) - } -} - -sem_post(sem_t *sem) -{ - n = atomic_increment(sem->count); - // Pass the new value of sem->count - futex_wake(&sem->count, n + 1); -} - -sem_trywait(sem_t *sem) -{ - if (atomic_decrement_if_positive(sem->count)) { - return 0; - } else { - return EAGAIN; - } -} - -sem_getvalue(sem_t *sem, int *sval) -{ - *sval = sem->count; - read_barrier(); -} diff --git a/nptl/Makefile b/nptl/Makefile index ac76596..f845f67 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -99,7 +99,7 @@ libpthread-routines = nptl-init vars events version \ sem_init sem_destroy \ sem_open sem_close sem_unlink \ sem_getvalue \ - sem_wait sem_trywait sem_timedwait sem_post \ + sem_wait sem_post \ cleanup cleanup_defer cleanup_compat \ cleanup_defer_compat unwind \ pt-longjmp pt-cleanup\ @@ -282,8 +282,7 @@ tests-nolibpthread = tst-unload gen-as-const-headers = pthread-errnos.sym \ lowlevelcond.sym lowlevelrwlock.sym \ lowlevelbarrier.sym unwindbuf.sym \ - lowlevelrobustlock.sym pthread-pi-defines.sym \ - structsem.sym + lowlevelrobustlock.sym pthread-pi-defines.sym LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst diff --git a/nptl/sem_getvalue.c b/nptl/sem_getvalue.c index a4ab41f..a604852 100644 --- a/nptl/sem_getvalue.c +++ b/nptl/sem_getvalue.c @@ -19,23 +19,37 @@ #include #include #include "semaphoreP.h" +#include int -__new_sem_getvalue (sem, sval) - sem_t *sem; - int *sval; +__new_sem_getvalue (sem_t *sem, int *sval) { struct new_sem *isem = (struct new_sem *) sem; /* XXX Check for valid SEM parameter. */ - - *sval = isem->value; + /* FIXME This uses relaxed MO, even though POSIX specifies that this function + should be linearizable. However, its debatable whether linearizability + is the right requirement. We need to follow up with POSIX and, if + necessary, use a stronger MO here and elsewhere (e.g., potentially + release MO in all places where we consume a token). */ + +#if __HAVE_64B_ATOMICS + *sval = atomic_load_relaxed (&isem->data) & SEM_VALUE_MASK; +#else + *sval = atomic_load_relaxed (&isem->value) >> SEM_VALUE_SHIFT; +#endif return 0; } versioned_symbol (libpthread, __new_sem_getvalue, sem_getvalue, GLIBC_2_1); #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) -strong_alias (__new_sem_getvalue, __old_sem_getvalue) +int +__old_sem_getvalue (sem_t *sem, int *sval) +{ + struct old_sem *isem = (struct old_sem *) sem; + *sval = isem->value; + return 0; +} compat_symbol (libpthread, __old_sem_getvalue, sem_getvalue, GLIBC_2_0); #endif diff --git a/nptl/sem_init.c b/nptl/sem_init.c index 7af2775..99dcc4f 100644 --- a/nptl/sem_init.c +++ b/nptl/sem_init.c @@ -18,17 +18,14 @@ #include #include -#include +#include #include #include "semaphoreP.h" #include int -__new_sem_init (sem, pshared, value) - sem_t *sem; - int pshared; - unsigned int value; +__new_sem_init (sem_t *sem, int pshared, unsigned int value) { /* Parameter sanity check. */ if (__glibc_unlikely (value > SEM_VALUE_MAX)) @@ -40,16 +37,15 @@ __new_sem_init (sem, pshared, value) /* Map to the internal type. */ struct new_sem *isem = (struct new_sem *) sem; - /* Use the values the user provided. */ - isem->value = value; -#ifdef __ASSUME_PRIVATE_FUTEX - isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; + /* Use the values the caller provided. */ +#if __HAVE_64B_ATOMICS + isem->data = value; #else - isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, - header.private_futex); + isem->value = value << SEM_VALUE_SHIFT; + isem->nwaiters = 0; #endif - isem->nwaiters = 0; + isem->private = futex_private_if_supported (pshared); return 0; } diff --git a/nptl/sem_open.c b/nptl/sem_open.c index cf91859..11b7c0a 100644 --- a/nptl/sem_open.c +++ b/nptl/sem_open.c @@ -33,6 +33,7 @@ #include #include #include "semaphoreP.h" +#include @@ -309,9 +310,14 @@ sem_open (const char *name, int oflag, ...) struct new_sem newsem; } sem; - sem.newsem.value = value; - sem.newsem.private = 0; +#if __HAVE_64B_ATOMICS + sem.newsem.data = value; +#else + sem.newsem.value = value << SEM_VALUE_SHIFT; sem.newsem.nwaiters = 0; +#endif + /* This always is a shared semaphore. */ + sem.newsem.private = FUTEX_SHARED; /* Initialize the remaining bytes as well. */ memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0', diff --git a/nptl/sem_post.c b/nptl/sem_post.c index 4906adf..0877774 100644 --- a/nptl/sem_post.c +++ b/nptl/sem_post.c @@ -21,39 +21,58 @@ #include #include #include +#include #include #include #include +/* See sem_wait for an explanation of the algorithm. */ int __new_sem_post (sem_t *sem) { struct new_sem *isem = (struct new_sem *) sem; + int private = isem->private; - __typeof (isem->value) cur; +#if __HAVE_64B_ATOMICS + /* Add a token to the semaphore. We use release MO to make sure that a + thread acquiring this token synchronizes with us and other threads that + added tokens before (the release sequence includes atomic RMW operations + by other threads). */ + /* TODO Use atomic_fetch_add to make it scale better than a CAS loop? */ + unsigned long int d = atomic_load_relaxed (&isem->data); do { - cur = isem->value; - if (isem->value == SEM_VALUE_MAX) + if ((d & SEM_VALUE_MASK) == SEM_VALUE_MAX) { __set_errno (EOVERFLOW); return -1; } } - while (atomic_compare_and_exchange_bool_rel (&isem->value, cur + 1, cur)); + while (!atomic_compare_exchange_weak_release (&isem->data, &d, d + 1)); - atomic_full_barrier (); - if (isem->nwaiters > 0) + /* If there is any potentially blocked waiter, wake one of them. */ + if (d >> SEM_NWAITERS_SHIFT > 0) + futex_wake (((unsigned*)&isem->data) + SEM_VALUE_OFFSET, 1, private); +#else + /* Add a token to the semaphore. Similar to 64b version. */ + unsigned int v = atomic_load_relaxed (&isem->value); + do { - int err = lll_futex_wake (&isem->value, 1, - isem->private ^ FUTEX_PRIVATE_FLAG); - if (__builtin_expect (err, 0) < 0) + if ((v << SEM_VALUE_SHIFT) == SEM_VALUE_MAX) { - __set_errno (-err); + __set_errno (EOVERFLOW); return -1; } } + while (!atomic_compare_exchange_weak_release (&isem->value, + &v, v + (1 << SEM_VALUE_SHIFT))); + + /* If there is any potentially blocked waiter, wake one of them. */ + if (v & SEM_NWAITERS_MASK != 0) + futex_wake (&isem->value, 1, private); +#endif + return 0; } versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); @@ -66,6 +85,9 @@ __old_sem_post (sem_t *sem) { int *futex = (int *) sem; + /* We must need to synchronize with consumers of this token, so the atomic + increment must have release MO semantics. */ + atomic_write_barrier (); (void) atomic_increment_val (futex); /* We always have to assume it is a shared semaphore. */ int err = lll_futex_wake (futex, 1, LLL_SHARED); diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c deleted file mode 100644 index 5d4c830..0000000 --- a/nptl/sem_timedwait.c +++ /dev/null @@ -1,117 +0,0 @@ -/* sem_timedwait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -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) -{ - struct new_sem *isem = (struct new_sem *) sem; - int err; - - if (atomic_decrement_if_positive (&isem->value) > 0) - return 0; - - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - { - __set_errno (EINVAL); - return -1; - } - - atomic_increment (&isem->nwaiters); - - pthread_cleanup_push (__sem_wait_cleanup, isem); - - while (1) - { - struct timeval tv; - struct timespec rt; - int sec, nsec; - - /* Get the current time. */ - __gettimeofday (&tv, NULL); - - /* Compute relative timeout. */ - sec = abstime->tv_sec - tv.tv_sec; - nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (nsec < 0) - { - nsec += 1000000000; - --sec; - } - - /* Already timed out? */ - if (sec < 0) - { - __set_errno (ETIMEDOUT); - err = -1; - break; - } - - /* Do wait. */ - rt.tv_sec = sec; - rt.tv_nsec = nsec; - err = do_futex_timed_wait(isem, &rt); - if (err != 0 && err != -EWOULDBLOCK) - { - __set_errno (-err); - err = -1; - break; - } - - if (atomic_decrement_if_positive (&isem->value) > 0) - { - err = 0; - break; - } - } - - pthread_cleanup_pop (0); - - atomic_decrement (&isem->nwaiters); - - return err; -} diff --git a/nptl/sem_trywait.c b/nptl/sem_trywait.c deleted file mode 100644 index 94c323c..0000000 --- a/nptl/sem_trywait.c +++ /dev/null @@ -1,50 +0,0 @@ -/* sem_trywait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include - -#include - - -int -__new_sem_trywait (sem_t *sem) -{ - int *futex = (int *) sem; - int val; - - if (*futex > 0) - { - val = atomic_decrement_if_positive (futex); - if (val > 0) - return 0; - } - - __set_errno (EAGAIN); - return -1; -} -versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); -#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) -strong_alias (__new_sem_trywait, __old_sem_trywait) -compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); -#endif diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c index b12babb..33ac60d 100644 --- a/nptl/sem_wait.c +++ b/nptl/sem_wait.c @@ -22,74 +22,406 @@ #include #include #include +#include +#include #include #include #include -void -attribute_hidden +/* The semaphore provides two main operations: sem_post adds a token to the + semaphore; sem_wait grabs a token from the semaphore, potentially waiting + until there is a token available. A sem_wait needs to synchronize with + the sem_post that provided the token, so that whatever lead to the sem_post + happens before the code after sem_wait. + + Conceptually, available tokens can simply be counted; let's call that the + value of the semaphore. However, we also want to know whether there might + be a sem_wait that is blocked on the value because it was zero (using a + futex with the value being the futex variable); if there is no blocked + sem_wait, sem_post does not need to execute a futex_wake call. Therefore, + we also need to count the number of potentially blocked sem_wait calls + (which we call nwaiters). + + What makes this tricky is that POSIX requires that a semaphore can be + destroyed as soon as the last remaining sem_wait has returned, and no + other sem_wait or sem_post calls are executing concurrently. However, the + sem_post call whose token was consumed by the last sem_wait is considered + to have finished once it provided the token to the sem_wait. + Thus, sem_post must not access the semaphore struct anymore after it has + made a token available; IOW, it needs to be able to atomically provide + a token and check whether any blocked sem_wait calls might exist. + + This is straightforward to do if the architecture provides 64b atomics + because we can just put both the value and nwaiters into one variable that + we access atomically: This is the data field, the value is in the + least-significant 32 bits, and nwaiters in the other bits. When sem_post + makes a value available, it can atomically check nwaiters. + + If we have only 32b atomics available, we cannot put both nwaiters and + value into one 32b value because then we might have too few bits for both + of those counters. Therefore, we need to use two distinct fields. + + To allow sem_post to atomically make a token available and check for + blocked sem_wait calls, we use one bit in value to indicate whether + nwaiters is nonzero. That allows sem_post to use basically the same + algorithm as with 64b atomics, but requires sem_wait to update the bit; it + can't do this atomically with another access to nwaiters, but it can compute + a conservative value for the bit because it's benign if the bit is set + even if nwaiters is zero (all we get is an unnecessary futex wake call by + sem_post). + Specifically, sem_wait will unset the bit speculatively if it believes that + there is no other concurrently executing sem_wait. If it misspeculated, + it will have to clean up by waking any other sem_wait call (i.e., what + sem_post would do otherwise). This does not conflict with the destruction + requirement because the semaphore must not be destructed while any sem_wait + is still executing. */ + +/* Set this to true if you assume that, in contrast to current futex + documentation, futex_wake can return -EINTR only if interrupted by a + signal, not spuriously due to some other reason. */ +static const int sem_assume_only_signals_cause_futex_EINTR = 0; + +#if !__HAVE_64B_ATOMICS +static void +__sem_wait_32_finish (struct new_sem *sem); +#endif + +static void __sem_wait_cleanup (void *arg) { - struct new_sem *isem = (struct new_sem *) arg; + struct new_sem *sem = (struct new_sem *) arg; - atomic_decrement (&isem->nwaiters); +#if __HAVE_64B_ATOMICS + /* Stop being registered as a waiter. See below for MO. */ + atomic_fetch_add_relaxed (&sem->data, -(1UL << SEM_NWAITERS_SHIFT)); +#else + __sem_wait_32_finish (sem); +#endif } -/* This is in a seperate function in order to make sure gcc +/* This is in a separate function in order to make sure gcc puts the call site into an exception region, and thus the - cleanups get properly run. */ + cleanups get properly run. TODO still necessary? Other futex_wait + users don't seem to need it. */ static int __attribute__ ((noinline)) -do_futex_wait (struct new_sem *isem) +do_futex_wait_inner (struct new_sem *sem, struct timespec *rt) { int err, oldtype = __pthread_enable_asynccancel (); - err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG); +#if __HAVE_64B_ATOMICS + if (rt == NULL) + err = futex_wait ((unsigned*)&sem->data + SEM_VALUE_OFFSET, 0, + sem->private); + else + err = futex_timed_wait ((unsigned*)&sem->data + SEM_VALUE_OFFSET, 0, rt, + sem->private); +#else + if (rt == NULL) + err = futex_wait (&sem->value, SEM_NWAITERS_MASK, sem->private); + else + err = futex_timed_wait (&sem->value, SEM_NWAITERS_MASK, rt, sem->private); +#endif __pthread_disable_asynccancel (oldtype); return err; } -int -__new_sem_wait (sem_t *sem) +/* Wait until at least one token is available, possibly with a timeout. */ +static int +do_futex_wait (struct new_sem *sem, const struct timespec *abstime) { - struct new_sem *isem = (struct new_sem *) sem; - int err; + struct timeval tv; + struct timespec rt; + int sec, nsec; - if (atomic_decrement_if_positive (&isem->value) > 0) - return 0; + if (abstime == NULL) + return do_futex_wait_inner (sem, NULL); + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } - atomic_increment (&isem->nwaiters); + /* Already timed out? */ + if (sec < 0) + return ETIMEDOUT; - pthread_cleanup_push (__sem_wait_cleanup, isem); + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + return do_futex_wait_inner (sem, &rt); +} - while (1) +/* Fast path: Try to grab a token without blocking. */ +static int +__new_sem_wait_fast (struct new_sem *sem, int definitive_result) +{ + /* We need acquire MO if we actually grab a token, so that this + synchronizes with all token providers (i.e., the RMW operation we read + from or all those before it in modification order; also see sem_post). + We do not need to guarantee any ordering if we observed that there is + no token (POSIX leaves it unspecified whether functions that fail + synchronize memory); thus, relaxed MO is sufficient for the initial load + and the failure path of the CAS. If the weak CAS fails and we need a + definitive result, retry. */ +#if __HAVE_64B_ATOMICS + unsigned long d = atomic_load_relaxed (&sem->data); + do { - err = do_futex_wait(isem); - if (err != 0 && err != -EWOULDBLOCK) + if ((d & SEM_VALUE_MASK) == 0) + break; + if (atomic_compare_exchange_weak_acquire (&sem->data, &d, d - 1)) + return 0; + } + while (definitive_result); + return -1; +#else + unsigned int v = atomic_load_relaxed (&sem->value); + do + { + if ((v >> SEM_VALUE_SHIFT) == 0) + break; + if (atomic_compare_exchange_weak_acquire (&sem->value, + &v, v - (1 << SEM_VALUE_SHIFT))) + return 0; + } + while (definitive_result); + return -1; +#endif +} + +/* Slow path that blocks. */ +static int +__attribute__ ((noinline)) +__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime) +{ + int err = 0; + +#if __HAVE_64B_ATOMICS + /* Add a waiter. Relaxed MO is sufficient because we can rely on the + ordering provided by the RMW operations we use. */ + unsigned long d = atomic_fetch_add_relaxed (&sem->data, + 1UL << SEM_NWAITERS_SHIFT); + + pthread_cleanup_push (__sem_wait_cleanup, sem); + + /* Wait for a token to be available. Retry until we can grab one. */ + for (;;) + { + /* If there is no token available, sleep until there is. */ + if ((d & SEM_VALUE_MASK) == 0) { - __set_errno (-err); - err = -1; - break; + err = do_futex_wait (sem, abstime); + /* A futex return value of 0 or EAGAIN is due to a real or spurious + wake-up, or due to a change in the number of tokens. We retry in + these cases. + If we timed out, forward this to the caller. + EINTR could be either due to being interrupted by a signal, or + due to a spurious wake-up. Thus, we cannot distinguish between + both, and are not allowed to return EINTR to the caller but have + to retry; this is because we may not have been interrupted by a + signal. However, if we assume that only signals cause a futex + return of EINTR, we forward EINTR to the caller. + + Retrying on EINTR is technically always allowed because to + reliably interrupt sem_wait with a signal, the signal handler + must call sem_post (which is AS-Safe). In executions where the + signal handler does not do that, the implementation can correctly + claim that sem_wait hadn't actually started to execute yet, and + thus the signal never actually interrupted sem_wait. We make no + timing guarantees, so the program can never observe that sem_wait + actually did start to execute. Thus, in a correct program, we + can expect a signal that wanted to interrupt the sem_wait to have + provided a token, and can just try to grab this token if + futex_wait returns EINTR. */ + if (err == ETIMEDOUT || + (err == EINTR && sem_assume_only_signals_cause_futex_EINTR)) + { + __set_errno (err); + err = -1; + /* Stop being registered as a waiter. */ + atomic_fetch_add_relaxed (&sem->data, + -(1UL << SEM_NWAITERS_SHIFT)); + break; + } + /* Relaxed MO is sufficient; see below. */ + d = atomic_load_relaxed (&sem->data); + } + else + { + /* Try to grab both a token and stop being a waiter. We need + acquire MO so this synchronizes with all token providers (i.e., + the RMW operation we read from or all those before it in + modification order; also see sem_post). On the failure path, + relaxed MO is sufficient because we only eventually need the + up-to-date value; the futex_wait or the CAS perform the real + work. */ + if (atomic_compare_exchange_weak_acquire (&sem->data, + &d, d - 1 - (1UL << SEM_NWAITERS_SHIFT))) + { + err = 0; + break; + } } + } + + pthread_cleanup_pop (0); +#else + /* The main difference to the 64b-atomics implementation is that we need to + access value and nwaiters in separate steps, and that the nwaiters bit + in the value can temporarily not be set even if nwaiters is nonzero. + We work around incorrectly unsetting the nwaiters bit by letting sem_wait + set the bit again and waking the number of waiters that could grab a + token. There are two additional properties we need to ensure: + (1) We make sure that whenever unsetting the bit, we see the increment of + nwaiters by the other thread that set the bit. IOW, we will notice if + we make a mistake. + (2) When setting the nwaiters bit, we make sure that we see the unsetting + of the bit by another waiter that happened before us. This avoids having + to blindly set the bit whenever we need to block on it. We set/unset + the bit while having incremented nwaiters (i.e., are a registered + waiter), and the problematic case only happens when one waiter indeed + followed another (i.e., nwaiters was never larger than 1); thus, this + works similarly as with a critical section using nwaiters (see the MOs + and related comments below). + + An alternative approach would be to unset the bit after decrementing + nwaiters; however, that would result in needing Dekker-like + synchronization and thus full memory barriers. We also would not be able + to prevent misspeculation, so this alternative scheme does not seem + beneficial. */ + unsigned int v; + + /* Add a waiter. We need acquire MO so this synchronizes with the release + MO we use when decrementing nwaiters below; it ensures that if another + waiter unset the bit before us, we see that and set it again. Also see + property (2) above. */ + atomic_fetch_add_acquire (&sem->nwaiters, 1); - if (atomic_decrement_if_positive (&isem->value) > 0) + pthread_cleanup_push (__sem_wait_cleanup, sem); + + /* Wait for a token to be available. Retry until we can grab one. */ + /* We do not need any ordering wrt. to this load's reads-from, so relaxed + MO is sufficient. The acquire MO above ensures that in the problematic + case, we do see the unsetting of the bit by another waiter. */ + v = atomic_load_relaxed (&sem->value); + do + { + do { - err = 0; - break; + /* We are about to block, so make sure that the nwaiters bit is + set. We need release MO on the CAS to ensure that when another + waiter unsets the nwaiters bit, it will also observe that we + incremented nwaiters in the meantime (also see the unsetting of + the bit below). Relaxed MO on CAS failure is sufficient (see + above). */ + do + { + if ((v & SEM_NWAITERS_MASK) != 0) + break; + } + while (!atomic_compare_exchange_weak_release (&sem->value, + &v, v | SEM_NWAITERS_MASK)); + /* If there is no token, wait. */ + if ((v >> SEM_VALUE_SHIFT) == 0) + { + /* See __HAVE_64B_ATOMICS variant. */ + err = do_futex_wait(sem, abstime); + if (err == ETIMEDOUT || + (err == EINTR && sem_assume_only_signals_cause_futex_EINTR)) + { + __set_errno (err); + err = -1; + goto error; + } + err = 0; + /* We blocked, so there might be a token now. Relaxed MO is + sufficient (see above). */ + v = atomic_load_relaxed (&sem->value); + } } + /* If there is no token, we must not try to grab one. */ + while ((v >> SEM_VALUE_SHIFT) == 0); } + /* Try to grab a token. We need acquire MO so this synchronizes with + all token providers (i.e., the RMW operation we read from or all those + before it in modification order; also see sem_post). */ + while (!atomic_compare_exchange_weak_acquire (&sem->value, + &v, v - (1 << SEM_VALUE_SHIFT))); +error: pthread_cleanup_pop (0); - atomic_decrement (&isem->nwaiters); + __sem_wait_32_finish (sem); +#endif return err; } -versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); +/* Stop being a registered waiter (non-64b-atomics code only). */ +#if !__HAVE_64B_ATOMICS +static void +__sem_wait_32_finish (struct new_sem *sem) +{ + /* The nwaiters bit is still set, try to unset it now if this seems + necessary. We do this before decrementing nwaiters so that the unsetting + is visible to other waiters entering after us. Relaxed MO is sufficient + because we are just speculating here; a stronger MO would not prevent + misspeculation. */ + unsigned int wguess = atomic_load_relaxed (&sem->nwaiters); + if (wguess == 1) + /* We might be the last waiter, so unset. This needs acquire MO so that + it syncronizes with the release MO when setting the bit above; if we + overwrite someone else that set the bit, we'll read in the following + decrement of nwaiters at least from that release sequence, so we'll + see if the other waiter is still active or if another writer entered + in the meantime (i.e., using the check below). */ + atomic_fetch_and_acquire (&sem->value, ~SEM_NWAITERS_MASK); + + /* Now stop being a waiter, and see whether our guess was correct. + This needs release MO so that it synchronizes with the acquire MO when + a waiter increments nwaiters; this makes sure that newer writers see that + we reset the waiters_present bit. */ + unsigned int wfinal = atomic_fetch_add_release (&sem->nwaiters, -1); + if (wfinal > 1 && wguess == 1) + { + /* We guessed wrong, and so need to clean up after the mistake and + unblock any waiters that could have not been woken. There is no + additional ordering that we need to set up, so relaxed MO is + sufficient. */ + unsigned int v = atomic_fetch_or_relaxed (&sem->value, + SEM_NWAITERS_MASK); + /* If there are available tokens, then wake as many waiters. If there + aren't any, then there is no need to wake anyone because there is + none to grab for another waiter. If tokens become available + subsequently, then the respective sem_post calls will do the wake-up + due to us having set the nwaiters bit again. */ + v >>= SEM_VALUE_SHIFT; + if (v > 0) + futex_wake (&sem->value, v, sem->private); + } +} +#endif + +int +__new_sem_wait (sem_t *sem) +{ + if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0) + return 0; + else + return __new_sem_wait_slow((struct new_sem *) sem, NULL); +} +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); #if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) int @@ -121,3 +453,49 @@ __old_sem_wait (sem_t *sem) compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); #endif + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0) + return 0; + else + return __new_sem_wait_slow((struct new_sem *) sem, abstime); +} + +int +__new_sem_trywait (sem_t *sem) +{ + /* We must not fail spuriously, so require a definitive result even if this + may lead to a long execution time. */ + if (__new_sem_wait_fast ((struct new_sem *) sem, 1) == 0) + return 0; + __set_errno (EAGAIN); + return -1; +} +versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +int +__old_sem_trywait (sem_t *sem) +{ + int *futex = (int *) sem; + int val; + + if (*futex > 0) + { + val = atomic_decrement_if_positive (futex); + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); +#endif diff --git a/nptl/structsem.sym b/nptl/structsem.sym deleted file mode 100644 index 0e2a15f..0000000 --- a/nptl/structsem.sym +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include -#include "internaltypes.h" - --- - -VALUE offsetof (struct new_sem, value) -PRIVATE offsetof (struct new_sem, private) -NWAITERS offsetof (struct new_sem, nwaiters) -SEM_VALUE_MAX SEM_VALUE_MAX diff --git a/nptl/tst-sem11.c b/nptl/tst-sem11.c index 5248eba..1a2dbaf 100644 --- a/nptl/tst-sem11.c +++ b/nptl/tst-sem11.c @@ -34,8 +34,11 @@ main (void) puts ("sem_init failed"); return 1; } - +#if __HAVE_64B_ATOMICS + if ((u.ns.data >> SEM_NWAITERS_SHIFT) != 0) +#else if (u.ns.nwaiters != 0) +#endif { puts ("nwaiters not initialized"); return 1; @@ -68,7 +71,11 @@ main (void) goto again; } +#if __HAVE_64B_ATOMICS + if ((u.ns.data >> SEM_NWAITERS_SHIFT) != 0) +#else if (u.ns.nwaiters != 0) +#endif { puts ("nwaiters not reset"); return 1; diff --git a/nptl/tst-sem13.c b/nptl/tst-sem13.c index 068d79e..1560e91 100644 --- a/nptl/tst-sem13.c +++ b/nptl/tst-sem13.c @@ -33,9 +33,14 @@ do_test (void) perror ("sem_timedwait did not fail with EINVAL"); return 1; } - if (u.ns.nwaiters != 0) +#if __HAVE_64B_ATOMICS + unsigned int nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT); +#else + unsigned int nwaiters = u.ns.nwaiters; +#endif + if (nwaiters != 0) { - printf ("sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters); + printf ("sem_timedwait modified nwaiters: %d\n", nwaiters); return 1; } @@ -52,9 +57,14 @@ do_test (void) perror ("2nd sem_timedwait did not fail with ETIMEDOUT"); return 1; } - if (u.ns.nwaiters != 0) +#if __HAVE_64B_ATOMICS + nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT); +#else + nwaiters = u.ns.nwaiters; +#endif + if (nwaiters != 0) { - printf ("2nd sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters); + printf ("2nd sem_timedwait modified nwaiters: %d\n", nwaiters); return 1; } diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h index d127f68..39ba18b 100644 --- a/sysdeps/nptl/internaltypes.h +++ b/sysdeps/nptl/internaltypes.h @@ -20,6 +20,8 @@ #define _INTERNALTYPES_H 1 #include +#include +#include struct pthread_attr @@ -141,9 +143,29 @@ struct pthread_key_struct /* Semaphore variable structure. */ struct new_sem { +#if __HAVE_64B_ATOMICS + /* The data field holds both value (in the least-significant 32 bytes) and + nwaiters. */ +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define SEM_VALUE_OFFSET 0 +# elif __BYTE_ORDER == __BIG_ENDIAN +# define SEM_VALUE_OFFSET 1 +# else +# error Unsupported byte order. +# endif +# define SEM_NWAITERS_SHIFT 32 +# define SEM_VALUE_MASK (~(unsigned int)0) + unsigned long int data; + int private; + int pad; +#else +# define SEM_VALUE_SHIFT 1 +# define SEM_NWAITERS_MASK ((unsigned int)1) unsigned int value; int private; - unsigned long int nwaiters; + int pad; + unsigned int nwaiters; +#endif }; struct old_sem diff --git a/sysdeps/unix/sysv/linux/alpha/sem_post.c b/sysdeps/unix/sysv/linux/alpha/sem_post.c deleted file mode 100644 index 9d44953..0000000 --- a/sysdeps/unix/sysv/linux/alpha/sem_post.c +++ /dev/null @@ -1,5 +0,0 @@ -/* ??? This is an ass-backwards way to do this. We should simply define - the acquire/release semantics of atomic_exchange_and_add. And even if - we don't do this, we should be using atomic_full_barrier or otherwise. */ -#define __lll_rel_instr "mb" -#include diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/sysdeps/unix/sysv/linux/i386/i486/sem_post.S deleted file mode 100644 index bc091a0..0000000 --- a/sysdeps/unix/sysv/linux/i386/i486/sem_post.S +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include - - - .text - - .globl __new_sem_post - .type __new_sem_post,@function - .align 16 -__new_sem_post: - cfi_startproc - pushl %ebx - cfi_adjust_cfa_offset(4) - cfi_offset(%ebx, -8) - - movl 8(%esp), %ebx - -#if VALUE == 0 - movl (%ebx), %eax -#else - movl VALUE(%ebx), %eax -#endif -0: cmpl $SEM_VALUE_MAX, %eax - je 3f - leal 1(%eax), %edx - LOCK -#if VALUE == 0 - cmpxchgl %edx, (%ebx) -#else - cmpxchgl %edx, VALUE(%ebx) -#endif - jnz 0b - - cmpl $0, NWAITERS(%ebx) - je 2f - - movl $FUTEX_WAKE, %ecx - orl PRIVATE(%ebx), %ecx - movl $1, %edx - movl $SYS_futex, %eax - ENTER_KERNEL - - testl %eax, %eax - js 1f - -2: xorl %eax, %eax - popl %ebx - cfi_adjust_cfa_offset(-4) - cfi_restore(%ebx) - ret - - cfi_adjust_cfa_offset(4) - cfi_offset(%ebx, -8) -1: -#ifdef PIC - SETUP_PIC_REG(bx) -#else - movl $4f, %ebx -4: -#endif - addl $_GLOBAL_OFFSET_TABLE_, %ebx -#ifdef NO_TLS_DIRECT_SEG_REFS - movl errno@gotntpoff(%ebx), %edx - addl %gs:0, %edx - movl $EINVAL, (%edx) -#else - movl errno@gotntpoff(%ebx), %edx - movl $EINVAL, %gs:(%edx) -#endif - - orl $-1, %eax - popl %ebx - ret - -3: -#ifdef PIC - SETUP_PIC_REG(bx) -#else - movl $5f, %ebx -5: -#endif - addl $_GLOBAL_OFFSET_TABLE_, %ebx -#ifdef NO_TLS_DIRECT_SEG_REFS - movl errno@gotntpoff(%ebx), %edx - addl %gs:0, %edx - movl $EOVERFLOW, (%edx) -#else - movl errno@gotntpoff(%ebx), %edx - movl $EOVERFLOW, %gs:(%edx) -#endif - - orl $-1, %eax - popl %ebx - cfi_adjust_cfa_offset(-4) - cfi_restore(%ebx) - ret - cfi_endproc - .size __new_sem_post,.-__new_sem_post - versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) -#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) - .global __old_sem_post - .type __old_sem_post,@function -__old_sem_post: - cfi_startproc - pushl %ebx - cfi_adjust_cfa_offset(4) - cfi_offset(%ebx, -8) - - movl 8(%esp), %ebx - LOCK - addl $1, (%ebx) - - movl $SYS_futex, %eax - movl $FUTEX_WAKE, %ecx - movl $1, %edx - ENTER_KERNEL - - testl %eax, %eax - js 1b - - xorl %eax, %eax - popl %ebx - cfi_adjust_cfa_offset(-4) - cfi_restore(%ebx) - ret - cfi_endproc - .size __old_sem_post,.-__old_sem_post - compat_symbol(libpthread, __old_sem_post, sem_post, GLIBC_2_0) -#endif diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S deleted file mode 100644 index 94d052a..0000000 --- a/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include - - -#if VALUE != 0 -# error "code needs to be rewritten for VALUE != 0" -#endif - - - .text - - .globl sem_timedwait - .type sem_timedwait,@function - .align 16 -sem_timedwait: -.LSTARTCODE: - movl 4(%esp), %ecx - - movl (%ecx), %eax -2: testl %eax, %eax - je 1f - - leal -1(%eax), %edx - LOCK - cmpxchgl %edx, (%ecx) - jne 2b - - xorl %eax, %eax - ret - - /* Check whether the timeout value is valid. */ -1: pushl %esi -.Lpush_esi: - pushl %edi -.Lpush_edi: - pushl %ebx -.Lpush_ebx: - subl $12, %esp -.Lsub_esp: - - movl 32(%esp), %edi - - /* Check for invalid nanosecond field. */ - cmpl $1000000000, 4(%edi) - movl $EINVAL, %esi - jae .Lerrno_exit - - LOCK - incl NWAITERS(%ecx) - -7: xorl %ecx, %ecx - movl %esp, %ebx - movl %ecx, %edx - movl $__NR_gettimeofday, %eax - ENTER_KERNEL - - /* Compute relative timeout. */ - movl 4(%esp), %eax - movl $1000, %edx - mul %edx /* Milli seconds to nano seconds. */ - movl (%edi), %ecx - movl 4(%edi), %edx - subl (%esp), %ecx - subl %eax, %edx - jns 5f - addl $1000000000, %edx - subl $1, %ecx -5: testl %ecx, %ecx - movl $ETIMEDOUT, %esi - js 6f /* Time is already up. */ - - movl %ecx, (%esp) /* Store relative timeout. */ - movl %edx, 4(%esp) - -.LcleanupSTART: - call __pthread_enable_asynccancel - movl %eax, 8(%esp) - - movl 28(%esp), %ebx /* Load semaphore address. */ -#if FUTEX_WAIT == 0 - movl PRIVATE(%ebx), %ecx -#else - movl $FUTEX_WAIT, %ecx - orl PRIVATE(%ebx), %ecx -#endif - movl %esp, %esi - xorl %edx, %edx - movl $SYS_futex, %eax - ENTER_KERNEL - movl %eax, %esi - - movl 8(%esp), %eax - call __pthread_disable_asynccancel -.LcleanupEND: - - testl %esi, %esi - je 9f - cmpl $-EWOULDBLOCK, %esi - jne 3f - -9: movl (%ebx), %eax -8: testl %eax, %eax - je 7b - - leal -1(%eax), %ecx - LOCK - cmpxchgl %ecx, (%ebx) - jne 8b - - xorl %eax, %eax - - LOCK - decl NWAITERS(%ebx) - -10: addl $12, %esp -.Ladd_esp: - popl %ebx -.Lpop_ebx: - popl %edi -.Lpop_edi: - popl %esi -.Lpop_esi: - ret - -.Lafter_ret: -3: negl %esi -6: - movl 28(%esp), %ebx /* Load semaphore address. */ - LOCK - decl NWAITERS(%ebx) -.Lerrno_exit: -#ifdef PIC - SETUP_PIC_REG(bx) -#else - movl $4f, %ebx -4: -#endif - addl $_GLOBAL_OFFSET_TABLE_, %ebx -#ifdef NO_TLS_DIRECT_SEG_REFS - movl errno@gotntpoff(%ebx), %edx - addl %gs:0, %edx - movl %esi, (%edx) -#else - movl errno@gotntpoff(%ebx), %edx - movl %esi, %gs:(%edx) -#endif - - orl $-1, %eax - jmp 10b - .size sem_timedwait,.-sem_timedwait - - - .type sem_wait_cleanup,@function -sem_wait_cleanup: - LOCK - decl NWAITERS(%ebx) - movl %eax, (%esp) -.LcallUR: - call _Unwind_Resume@PLT - hlt -.LENDCODE: - .size sem_wait_cleanup,.-sem_wait_cleanup - - - .section .gcc_except_table,"a",@progbits -.LexceptSTART: - .byte 0xff # @LPStart format (omit) - .byte 0xff # @TType format (omit) - .byte 0x01 # call-site format - # DW_EH_PE_uleb128 - .uleb128 .Lcstend-.Lcstbegin -.Lcstbegin: - .uleb128 .LcleanupSTART-.LSTARTCODE - .uleb128 .LcleanupEND-.LcleanupSTART - .uleb128 sem_wait_cleanup-.LSTARTCODE - .uleb128 0 - .uleb128 .LcallUR-.LSTARTCODE - .uleb128 .LENDCODE-.LcallUR - .uleb128 0 - .uleb128 0 -.Lcstend: - - - .section .eh_frame,"a",@progbits -.LSTARTFRAME: - .long .LENDCIE-.LSTARTCIE # Length of the CIE. -.LSTARTCIE: - .long 0 # CIE ID. - .byte 1 # Version number. -#ifdef SHARED - .string "zPLR" # NUL-terminated augmentation - # string. -#else - .string "zPL" # NUL-terminated augmentation - # string. -#endif - .uleb128 1 # Code alignment factor. - .sleb128 -4 # Data alignment factor. - .byte 8 # Return address register - # column. -#ifdef SHARED - .uleb128 7 # Augmentation value length. - .byte 0x9b # Personality: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4 - # + DW_EH_PE_indirect - .long DW.ref.__gcc_personality_v0-. - .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4. - .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4. -#else - .uleb128 6 # Augmentation value length. - .byte 0x0 # Personality: absolute - .long __gcc_personality_v0 - .byte 0x0 # LSDA Encoding: absolute -#endif - .byte 0x0c # DW_CFA_def_cfa - .uleb128 4 - .uleb128 4 - .byte 0x88 # DW_CFA_offset, column 0x10 - .uleb128 1 - .align 4 -.LENDCIE: - - .long .LENDFDE-.LSTARTFDE # Length of the FDE. -.LSTARTFDE: - .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. -#ifdef SHARED - .long .LSTARTCODE-. # PC-relative start address - # of the code. -#else - .long .LSTARTCODE # Start address of the code. -#endif - .long .LENDCODE-.LSTARTCODE # Length of the code. - .uleb128 4 # Augmentation size -#ifdef SHARED - .long .LexceptSTART-. -#else - .long .LexceptSTART -#endif - - .byte 4 # DW_CFA_advance_loc4 - .long .Lpush_esi-.LSTARTCODE - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 8 - .byte 0x86 # DW_CFA_offset %esi - .uleb128 2 - .byte 4 # DW_CFA_advance_loc4 - .long .Lpush_edi-.Lpush_esi - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 12 - .byte 0x87 # DW_CFA_offset %edi - .uleb128 3 - .byte 4 # DW_CFA_advance_loc4 - .long .Lpush_ebx-.Lpush_edi - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 16 - .byte 0x83 # DW_CFA_offset %ebx - .uleb128 4 - .byte 4 # DW_CFA_advance_loc4 - .long .Lsub_esp-.Lpush_ebx - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 28 - .byte 4 # DW_CFA_advance_loc4 - .long .Ladd_esp-.Lsub_esp - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 16 - .byte 4 # DW_CFA_advance_loc4 - .long .Lpop_ebx-.Ladd_esp - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 12 - .byte 0xc3 # DW_CFA_restore %ebx - .byte 4 # DW_CFA_advance_loc4 - .long .Lpop_edi-.Lpop_ebx - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 8 - .byte 0xc7 # DW_CFA_restore %edi - .byte 4 # DW_CFA_advance_loc4 - .long .Lpop_esi-.Lpop_edi - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 4 - .byte 0xc6 # DW_CFA_restore %esi - .byte 4 # DW_CFA_advance_loc4 - .long .Lafter_ret-.Lpop_esi - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 28 - .byte 0x86 # DW_CFA_offset %esi - .uleb128 2 - .byte 0x87 # DW_CFA_offset %edi - .uleb128 3 - .byte 0x83 # DW_CFA_offset %ebx - .uleb128 4 - .align 4 -.LENDFDE: - - -#ifdef SHARED - .hidden DW.ref.__gcc_personality_v0 - .weak DW.ref.__gcc_personality_v0 - .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits - .align 4 - .type DW.ref.__gcc_personality_v0, @object - .size DW.ref.__gcc_personality_v0, 4 -DW.ref.__gcc_personality_v0: - .long __gcc_personality_v0 -#endif diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S deleted file mode 100644 index 69611ea..0000000 --- a/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include - - .text - - .globl __new_sem_trywait - .type __new_sem_trywait,@function - .align 16 -__new_sem_trywait: - movl 4(%esp), %ecx - - movl (%ecx), %eax -2: testl %eax, %eax - jz 1f - - leal -1(%eax), %edx - LOCK - cmpxchgl %edx, (%ecx) - jne 2b - xorl %eax, %eax - ret - -1: -#ifdef PIC - SETUP_PIC_REG(cx) -#else - movl $3f, %ecx -3: -#endif - addl $_GLOBAL_OFFSET_TABLE_, %ecx -#ifdef NO_TLS_DIRECT_SEG_REFS - movl errno@gotntpoff(%ecx), %edx - addl %gs:0, %edx - movl $EAGAIN, (%edx) -#else - movl errno@gotntpoff(%ecx), %edx - movl $EAGAIN, %gs:(%edx) -#endif - orl $-1, %eax - ret - .size __new_sem_trywait,.-__new_sem_trywait - versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) -#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) - .global __old_sem_trywait -__old_sem_trywait = __new_sem_trywait - compat_symbol(libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0) -#endif diff --git a/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S deleted file mode 100644 index 14d616f..0000000 --- a/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S +++ /dev/null @@ -1,343 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include - - -#if VALUE != 0 -# error "code needs to be rewritten for VALUE != 0" -#endif - - .text - - .globl __new_sem_wait - .type __new_sem_wait,@function - .align 16 -__new_sem_wait: -.LSTARTCODE: - pushl %ebx -.Lpush_ebx: - pushl %esi -.Lpush_esi: - subl $4, %esp -.Lsub_esp: - - movl 16(%esp), %ebx - - movl (%ebx), %eax -2: testl %eax, %eax - je 1f - - leal -1(%eax), %edx - LOCK - cmpxchgl %edx, (%ebx) - jne 2b -7: xorl %eax, %eax - -9: movl 4(%esp), %esi - movl 8(%esp), %ebx - addl $12, %esp -.Ladd_esp: - ret - -.Lafter_ret: -1: LOCK - incl NWAITERS(%ebx) - -.LcleanupSTART: -6: call __pthread_enable_asynccancel - movl %eax, (%esp) - -#if FUTEX_WAIT == 0 - movl PRIVATE(%ebx), %ecx -#else - movl $FUTEX_WAIT, %ecx - orl PRIVATE(%ebx), %ecx -#endif - xorl %esi, %esi - xorl %edx, %edx - movl $SYS_futex, %eax - ENTER_KERNEL - movl %eax, %esi - - movl (%esp), %eax - call __pthread_disable_asynccancel -.LcleanupEND: - - testl %esi, %esi - je 3f - cmpl $-EWOULDBLOCK, %esi - jne 4f - -3: - movl (%ebx), %eax -5: testl %eax, %eax - je 6b - - leal -1(%eax), %edx - LOCK - cmpxchgl %edx, (%ebx) - jne 5b - - LOCK - decl NWAITERS(%ebx) - jmp 7b - -4: LOCK - decl NWAITERS(%ebx) - - negl %esi -#ifdef PIC - SETUP_PIC_REG(bx) -#else - movl $8f, %ebx -8: -#endif - addl $_GLOBAL_OFFSET_TABLE_, %ebx -#ifdef NO_TLS_DIRECT_SEG_REFS - movl errno@gotntpoff(%ebx), %edx - addl %gs:0, %edx - movl %esi, (%edx) -#else - movl errno@gotntpoff(%ebx), %edx - movl %esi, %gs:(%edx) -#endif - orl $-1, %eax - - jmp 9b - .size __new_sem_wait,.-__new_sem_wait - versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) - - - .type sem_wait_cleanup,@function -sem_wait_cleanup: - LOCK - decl NWAITERS(%ebx) - movl %eax, (%esp) -.LcallUR: - call _Unwind_Resume@PLT - hlt -.LENDCODE: - .size sem_wait_cleanup,.-sem_wait_cleanup - - - .section .gcc_except_table,"a",@progbits -.LexceptSTART: - .byte 0xff # @LPStart format (omit) - .byte 0xff # @TType format (omit) - .byte 0x01 # call-site format - # DW_EH_PE_uleb128 - .uleb128 .Lcstend-.Lcstbegin -.Lcstbegin: - .uleb128 .LcleanupSTART-.LSTARTCODE - .uleb128 .LcleanupEND-.LcleanupSTART - .uleb128 sem_wait_cleanup-.LSTARTCODE - .uleb128 0 - .uleb128 .LcallUR-.LSTARTCODE - .uleb128 .LENDCODE-.LcallUR - .uleb128 0 - .uleb128 0 -.Lcstend: - - - .section .eh_frame,"a",@progbits -.LSTARTFRAME: - .long .LENDCIE-.LSTARTCIE # Length of the CIE. -.LSTARTCIE: - .long 0 # CIE ID. - .byte 1 # Version number. -#ifdef SHARED - .string "zPLR" # NUL-terminated augmentation - # string. -#else - .string "zPL" # NUL-terminated augmentation - # string. -#endif - .uleb128 1 # Code alignment factor. - .sleb128 -4 # Data alignment factor. - .byte 8 # Return address register - # column. -#ifdef SHARED - .uleb128 7 # Augmentation value length. - .byte 0x9b # Personality: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4 - # + DW_EH_PE_indirect - .long DW.ref.__gcc_personality_v0-. - .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4. - .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel - # + DW_EH_PE_sdata4. -#else - .uleb128 6 # Augmentation value length. - .byte 0x0 # Personality: absolute - .long __gcc_personality_v0 - .byte 0x0 # LSDA Encoding: absolute -#endif - .byte 0x0c # DW_CFA_def_cfa - .uleb128 4 - .uleb128 4 - .byte 0x88 # DW_CFA_offset, column 0x10 - .uleb128 1 - .align 4 -.LENDCIE: - - .long .LENDFDE-.LSTARTFDE # Length of the FDE. -.LSTARTFDE: - .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. -#ifdef SHARED - .long .LSTARTCODE-. # PC-relative start address - # of the code. -#else - .long .LSTARTCODE # Start address of the code. -#endif - .long .LENDCODE-.LSTARTCODE # Length of the code. - .uleb128 4 # Augmentation size -#ifdef SHARED - .long .LexceptSTART-. -#else - .long .LexceptSTART -#endif - - .byte 4 # DW_CFA_advance_loc4 - .long .Lpush_ebx-.LSTARTCODE - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 8 - .byte 0x83 # DW_CFA_offset %ebx - .uleb128 2 - .byte 4 # DW_CFA_advance_loc4 - .long .Lpush_esi-.Lpush_ebx - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 12 - .byte 0x86 # DW_CFA_offset %esi - .uleb128 3 - .byte 4 # DW_CFA_advance_loc4 - .long .Lsub_esp-.Lpush_esi - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 16 - .byte 4 # DW_CFA_advance_loc4 - .long .Ladd_esp-.Lsub_esp - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 4 - .byte 0xc3 # DW_CFA_restore %ebx - .byte 0xc6 # DW_CFA_restore %esi - .byte 4 # DW_CFA_advance_loc4 - .long .Lafter_ret-.Ladd_esp - .byte 14 # DW_CFA_def_cfa_offset - .uleb128 16 - .byte 0x83 # DW_CFA_offset %ebx - .uleb128 2 - .byte 0x86 # DW_CFA_offset %esi - .uleb128 3 - .align 4 -.LENDFDE: - - -#ifdef SHARED - .hidden DW.ref.__gcc_personality_v0 - .weak DW.ref.__gcc_personality_v0 - .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits - .align 4 - .type DW.ref.__gcc_personality_v0, @object - .size DW.ref.__gcc_personality_v0, 4 -DW.ref.__gcc_personality_v0: - .long __gcc_personality_v0 -#endif - - -#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) - .section ".text.compat", "ax" - .global __old_sem_wait - .type __old_sem_wait,@function - .align 16 - cfi_startproc -__old_sem_wait: - pushl %ebx - cfi_adjust_cfa_offset(4) - pushl %esi - cfi_adjust_cfa_offset(4) - subl $4, %esp - cfi_adjust_cfa_offset(4) - - movl 16(%esp), %ebx - cfi_offset(ebx, -8) - - cfi_offset(esi, -12) -3: movl (%ebx), %eax -2: testl %eax, %eax - je 1f - - leal -1(%eax), %edx - LOCK - cmpxchgl %edx, (%ebx) - jne 2b - xorl %eax, %eax - -5: movl 4(%esp), %esi - movl 8(%esp), %ebx - addl $12, %esp - cfi_restore(ebx) - cfi_restore(esi) - cfi_adjust_cfa_offset(-12) - ret - - cfi_adjust_cfa_offset(12) - cfi_offset(ebx, -8) - cfi_offset(esi, -12) -1: call __pthread_enable_asynccancel - movl %eax, (%esp) - - xorl %esi, %esi - movl $SYS_futex, %eax - movl %esi, %ecx - movl %esi, %edx - ENTER_KERNEL - movl %eax, %esi - - movl (%esp), %eax - call __pthread_disable_asynccancel - - testl %esi, %esi - je 3b - cmpl $-EWOULDBLOCK, %esi - je 3b - negl %esi -#ifdef PIC - SETUP_PIC_REG(bx) -#else - movl $4f, %ebx -4: -#endif - addl $_GLOBAL_OFFSET_TABLE_, %ebx -#ifdef NO_TLS_DIRECT_SEG_REFS - movl errno@gotntpoff(%ebx), %edx - addl %gs:0, %edx - movl %esi, (%edx) -#else - movl errno@gotntpoff(%ebx), %edx - movl %esi, %gs:(%edx) -#endif - orl $-1, %eax - jmp 5b - cfi_endproc - .size __old_sem_wait,.-__old_sem_wait - compat_symbol(libpthread, __old_sem_wait, sem_wait, GLIBC_2_0) -#endif diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_post.S b/sysdeps/unix/sysv/linux/i386/i586/sem_post.S deleted file mode 100644 index 28ebd27..0000000 --- a/sysdeps/unix/sysv/linux/i386/i586/sem_post.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_post.S" diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S b/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S deleted file mode 100644 index 46f1959..0000000 --- a/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_timedwait.S" diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S b/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S deleted file mode 100644 index bce1cbc..0000000 --- a/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_trywait.S" diff --git a/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S b/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S deleted file mode 100644 index abe0e9f..0000000 --- a/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_wait.S" diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_post.S b/sysdeps/unix/sysv/linux/i386/i686/sem_post.S deleted file mode 100644 index 28ebd27..0000000 --- a/sysdeps/unix/sysv/linux/i386/i686/sem_post.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_post.S" diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S b/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S deleted file mode 100644 index 46f1959..0000000 --- a/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_timedwait.S" diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S b/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S deleted file mode 100644 index bce1cbc..0000000 --- a/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_trywait.S" diff --git a/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S b/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S deleted file mode 100644 index abe0e9f..0000000 --- a/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include "../i486/sem_wait.S" diff --git a/sysdeps/unix/sysv/linux/powerpc/sem_post.c b/sysdeps/unix/sysv/linux/powerpc/sem_post.c deleted file mode 100644 index 831a8dd..0000000 --- a/sysdeps/unix/sysv/linux/powerpc/sem_post.c +++ /dev/null @@ -1,71 +0,0 @@ -/* sem_post -- post to a POSIX semaphore. Powerpc version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include - -#include - -int -__new_sem_post (sem_t *sem) -{ - struct new_sem *isem = (struct new_sem *) sem; - - __asm __volatile (__ARCH_REL_INSTR ::: "memory"); - atomic_increment (&isem->value); - __asm __volatile (__ARCH_ACQ_INSTR ::: "memory"); - if (isem->nwaiters > 0) - { - int err = lll_futex_wake (&isem->value, 1, - isem->private ^ FUTEX_PRIVATE_FLAG); - if (__builtin_expect (err, 0) < 0) - { - __set_errno (-err); - return -1; - } - } - return 0; -} -versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); - -#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) - -int -attribute_compat_text_section -__old_sem_post (sem_t *sem) -{ - int *futex = (int *) sem; - - __asm __volatile (__ARCH_REL_INSTR ::: "memory"); - (void) atomic_increment_val (futex); - /* We always have to assume it is a shared semaphore. */ - int err = lll_futex_wake (futex, 1, LLL_SHARED); - if (__builtin_expect (err, 0) < 0) - { - __set_errno (-err); - return -1; - } - return 0; -} - -compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); -#endif diff --git a/sysdeps/unix/sysv/linux/sh/sem_post.S b/sysdeps/unix/sysv/linux/sh/sem_post.S deleted file mode 100644 index ccc6255..0000000 --- a/sysdeps/unix/sysv/linux/sh/sem_post.S +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include "lowlevel-atomic.h" - - - .text - - .globl __new_sem_post - .type __new_sem_post,@function - .align 5 - cfi_startproc -__new_sem_post: - mov.l @(VALUE,r4), r2 -0: - mov.l .Lmax, r1 - cmp/eq r1, r2 - bt/s 3f - mov r2, r3 - mov r3, r5 - add #1, r5 - CMPXCHG (r3, @(VALUE,r4), r5, r2) - bf 0b - mov.l @(NWAITERS,r4), r2 - tst r2, r2 - bt 2f - mov #FUTEX_WAKE, r5 - mov.l @(PRIVATE,r4), r1 - or r1, r5 - mov #1, r6 - mov #0, r7 - mov #SYS_futex, r3 - extu.b r3, r3 - trapa #0x14 - SYSCALL_INST_PAD - - cmp/pz r0 - bf 1f -2: - rts - mov #0, r0 - -1: - bra 4f - mov #EINVAL, r2 - -3: - mov #EOVERFLOW, r2 -4: - mov.l r12, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r12, 0) - mov.l r8, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r8, 0) - sts.l pr, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (pr, 0) - mova .Lgot3, r0 - mov.l .Lgot3, r12 - add r0, r12 - - mov.l .Lerrno3, r0 - stc gbr, r1 - mov.l @(r0, r12), r0 - bra .Lexit - add r1, r0 - .align 2 -.Lerrno3: - .long errno@GOTTPOFF -.Lexit: - mov.l r2, @r0 - lds.l @r15+, pr - cfi_adjust_cfa_offset (-4) - cfi_restore (pr) - mov.l @r15+, r8 - cfi_adjust_cfa_offset (-4) - cfi_restore (r8) - mov.l @r15+, r12 - cfi_adjust_cfa_offset (-4) - cfi_restore (r12) - rts - mov #-1, r0 - cfi_endproc - - .align 2 -.Lmax: - .long SEM_VALUE_MAX -.Lgot3: - .long _GLOBAL_OFFSET_TABLE_ - .size __new_sem_post,.-__new_sem_post - versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) diff --git a/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/sysdeps/unix/sysv/linux/sh/sem_timedwait.S deleted file mode 100644 index 4803d03..0000000 --- a/sysdeps/unix/sysv/linux/sh/sem_timedwait.S +++ /dev/null @@ -1,281 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include -#include "lowlevel-atomic.h" - - -#if VALUE != 0 -# error "code needs to be rewritten for VALUE != 0" -#endif - - .text - - .globl sem_timedwait - .type sem_timedwait,@function - .align 5 - cfi_startproc -sem_timedwait: -.LSTARTCODE: -#ifdef SHARED - cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, - DW.ref.__gcc_personality_v0) - cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) -#else - cfi_personality(DW_EH_PE_absptr, __gcc_personality_v0) - cfi_lsda(DW_EH_PE_absptr, .LexceptSTART) -#endif - mov.l @r4, r0 -2: - tst r0, r0 - bt 1f - mov r0, r3 - mov r0, r6 - add #-1, r3 - CMPXCHG (r6, @r4, r3, r2) - bf/s 2b - mov r2, r0 - rts - mov #0, r0 - -1: - /* Check whether the timeout value is valid. */ - mov.l r8, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r8, 0) - mov.l r9, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r9, 0) - mov.l r10, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r10, 0) - mov.l r12, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r12, 0) - sts.l pr, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (pr, 0) - add #-8, r15 - cfi_adjust_cfa_offset (8) - - mov r4, r8 - mov r5, r9 - - /* Check for invalid nanosecond field. */ - mov.l @(4,r9), r0 - mov.l .L1g, r1 - cmp/hs r1, r0 - bt/s .Lerrno_exit - mov #EINVAL, r10 - INC (@(NWAITERS,r8),r2) - -7: - /* Compute relative timeout. */ - mov r15, r4 - mov #0, r5 - mov #__NR_gettimeofday, r3 - trapa #0x12 - SYSCALL_INST_PAD - - mov.l @(4,r15), r0 - mov.w .L1k, r1 - dmulu.l r0, r1 /* Milli seconds to nano seconds. */ - mov.l @r9, r2 - mov.l @(4,r9), r3 - mov.l @r15, r0 - sts macl, r1 - sub r0, r2 - clrt - subc r1, r3 - bf 5f - mov.l .L1g, r1 - add r1, r3 - add #-1, r2 -5: - cmp/pz r2 - bf/s 6f /* Time is already up. */ - mov #ETIMEDOUT, r0 - - /* Store relative timeout. */ - mov.l r2, @r15 - mov.l r3, @(4,r15) - -.LcleanupSTART: - mov.l .Lenable0, r1 - bsrf r1 - nop -.Lenable0b: - mov r0, r10 - - mov r8, r4 -#if FUTEX_WAIT == 0 - mov.l @(PRIVATE,r8), r5 -#else - mov.l @(PRIVATE,r8), r5 - mov #FUTEX_WAIT, r0 - or r0, r5 -#endif - mov #0, r6 - mov r15, r7 - mov #SYS_futex, r3 - extu.b r3, r3 - trapa #0x14 - SYSCALL_INST_PAD - - mov.l .Ldisable0, r1 - mov r10, r4 - bsrf r1 - mov r0, r10 -.Ldisable0b: - mov r10, r0 -.LcleanupEND: - - tst r0, r0 - bt 9f - cmp/eq #-EWOULDBLOCK, r0 - bf 3f -9: - mov.l @r8, r0 -8: - tst r0, r0 - bt 7b - - mov r0, r3 - mov r0, r4 - add #-1, r3 - CMPXCHG (r4, @r8, r3, r2) - bf/s 8b - mov r2, r0 - - DEC (@(NWAITERS,r8), r2) - mov #0, r0 - -10: - cfi_remember_state - add #8, r15 - cfi_adjust_cfa_offset (-8) - lds.l @r15+, pr - cfi_adjust_cfa_offset (-4) - cfi_restore (pr) - mov.l @r15+, r12 - cfi_adjust_cfa_offset (-4) - cfi_restore (r12) - mov.l @r15+, r10 - cfi_adjust_cfa_offset (-4) - cfi_restore (r10) - mov.l @r15+, r9 - cfi_adjust_cfa_offset (-4) - cfi_restore (r9) - mov.l @r15+, r8 - cfi_adjust_cfa_offset (-4) - cfi_restore (r8) - rts - nop - cfi_restore_state - -3: - neg r0, r0 -6: - mov r0, r10 - DEC (@(NWAITERS,r8), r2) -.Lerrno_exit: - mova .Lgot2, r0 - mov.l .Lgot2, r12 - add r0, r12 - - mov.l .Lerrno2, r0 - stc gbr, r1 - mov.l @(r0, r12), r0 - bra .Lexit - add r1, r0 - .align 2 -.Lerrno2: - .long errno@GOTTPOFF -.Lexit: - mov.l r10, @r0 - bra 10b - mov #-1, r0 - -.L1k: - .word 1000 - .align 2 -.L1g: - .long 1000000000 -.Lgot2: - .long _GLOBAL_OFFSET_TABLE_ -.Lenable0: - .long __pthread_enable_asynccancel-.Lenable0b -.Ldisable0: - .long __pthread_disable_asynccancel-.Ldisable0b - .size sem_timedwait,.-sem_timedwait - - .type sem_wait_cleanup,@function -sem_wait_cleanup: - DEC (@(NWAITERS,r8), r2) -.LcallUR: - mov.l .Lresume, r1 -#ifdef PIC - add r12, r1 -#endif - jsr @r1 - nop - sleep - - .align 2 -.Lresume: -#ifdef PIC - .long _Unwind_Resume@GOTOFF -#else - .long _Unwind_Resume -#endif -.LENDCODE: - cfi_endproc - .size sem_wait_cleanup,.-sem_wait_cleanup - - - .section .gcc_except_table,"a",@progbits -.LexceptSTART: - .byte DW_EH_PE_omit ! @LPStart format (omit) - .byte DW_EH_PE_omit ! @TType format (omit) - .byte DW_EH_PE_uleb128 ! call-site format - .uleb128 .Lcstend-.Lcstbegin -.Lcstbegin: - .uleb128 .LcleanupSTART-.LSTARTCODE - .uleb128 .LcleanupEND-.LcleanupSTART - .uleb128 sem_wait_cleanup-.LSTARTCODE - .uleb128 0 - .uleb128 .LcallUR-.LSTARTCODE - .uleb128 .LENDCODE-.LcallUR - .uleb128 0 - .uleb128 0 -.Lcstend: - -#ifdef SHARED - .hidden DW.ref.__gcc_personality_v0 - .weak DW.ref.__gcc_personality_v0 - .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits - .align 4 - .type DW.ref.__gcc_personality_v0, @object - .size DW.ref.__gcc_personality_v0, 4 -DW.ref.__gcc_personality_v0: - .long __gcc_personality_v0 -#endif diff --git a/sysdeps/unix/sysv/linux/sh/sem_trywait.S b/sysdeps/unix/sysv/linux/sh/sem_trywait.S deleted file mode 100644 index 8ff8792..0000000 --- a/sysdeps/unix/sysv/linux/sh/sem_trywait.S +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include "lowlevel-atomic.h" - - - .text - - .globl __new_sem_trywait - .type __new_sem_trywait,@function - .align 5 - cfi_startproc -__new_sem_trywait: - mov.l r12, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r12, 0) - mov.l r8, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r8, 0) - sts.l pr, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (pr, 0) - mov r4, r8 - mov.l @r8, r0 -2: - tst r0, r0 - bt 1f - - mov r0, r3 - mov r0, r4 - add #-1, r3 - CMPXCHG (r4, @r8, r3, r2) - bf/s 2b - mov r2, r0 - - cfi_remember_state - lds.l @r15+, pr - cfi_adjust_cfa_offset (-4) - cfi_restore (pr) - mov.l @r15+, r8 - cfi_adjust_cfa_offset (-4) - cfi_restore (r8) - mov.l @r15+, r12 - cfi_adjust_cfa_offset (-4) - cfi_restore (r12) - rts - mov #0, r0 - cfi_restore_state - -1: - mov #EAGAIN, r8 - mova .Lgot1, r0 - mov.l .Lgot1, r12 - add r0, r12 - - mov.l .Lerrno1, r0 - stc gbr, r1 - mov.l @(r0, r12), r0 - bra .Lexit - add r1, r0 - .align 2 -.Lerrno1: - .long errno@GOTTPOFF -.Lexit: - mov.l r8, @r0 - lds.l @r15+, pr - cfi_adjust_cfa_offset (-4) - cfi_restore (pr) - mov.l @r15+, r8 - cfi_adjust_cfa_offset (-4) - cfi_restore (r8) - mov.l @r15+, r12 - cfi_adjust_cfa_offset (-4) - cfi_restore (r12) - rts - mov #-1, r0 - - cfi_endproc - - .align 2 -.Lgot1: - .long _GLOBAL_OFFSET_TABLE_ - .size __new_sem_trywait,.-__new_sem_trywait - versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) diff --git a/sysdeps/unix/sysv/linux/sh/sem_wait.S b/sysdeps/unix/sysv/linux/sh/sem_wait.S deleted file mode 100644 index 04a6a40..0000000 --- a/sysdeps/unix/sysv/linux/sh/sem_wait.S +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include -#include "lowlevel-atomic.h" - - -#if VALUE != 0 -# error "code needs to be rewritten for VALUE != 0" -#endif - - .text - - .globl __new_sem_wait - .type __new_sem_wait,@function - .align 5 - cfi_startproc -__new_sem_wait: -.LSTARTCODE: -#ifdef SHARED - cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, - DW.ref.__gcc_personality_v0) - cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) -#else - cfi_personality(DW_EH_PE_absptr, __gcc_personality_v0) - cfi_lsda(DW_EH_PE_absptr, .LexceptSTART) -#endif - mov.l r8, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r8, 0) - mov.l r10, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r10, 0) - mov.l r12, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (r12, 0) - sts.l pr, @-r15 - cfi_adjust_cfa_offset (4) - cfi_rel_offset (pr, 0) - - mov r4, r8 - mov.l @r8, r0 -2: - tst r0, r0 - bt 1f - mov r0, r3 - mov r0, r4 - add #-1, r3 - CMPXCHG (r4, @r8, r3, r2) - bf/s 2b - mov r2, r0 -7: - mov #0, r0 -9: - cfi_remember_state - lds.l @r15+, pr - cfi_adjust_cfa_offset (-4) - cfi_restore (pr) - mov.l @r15+, r12 - cfi_adjust_cfa_offset (-4) - cfi_restore (r12) - mov.l @r15+, r10 - cfi_adjust_cfa_offset (-4) - cfi_restore (r10) - rts - mov.l @r15+, r8 - /* Omit CFI for restore in delay slot. */ - cfi_restore_state - -.Lafter_ret: -1: - INC (@(NWAITERS,r8),r2) - -.LcleanupSTART: -6: - mov.l .Lenable0, r1 - bsrf r1 - nop -.Lenable0b: - mov r0, r10 - - mov r8, r4 -#if FUTEX_WAIT == 0 - mov.l @(PRIVATE,r8), r5 -#else - mov.l @(PRIVATE,r8), r5 - mov #FUTEX_WAIT, r0 - or r0, r5 -#endif - mov #0, r6 - mov #0, r7 - mov #SYS_futex, r3 - extu.b r3, r3 - trapa #0x14 - SYSCALL_INST_PAD - - mov.l .Ldisable0, r1 - mov r10, r4 - bsrf r1 - mov r0, r10 -.Ldisable0b: - mov r10, r0 -.LcleanupEND: - - tst r0, r0 - bt 3f - cmp/eq #-EWOULDBLOCK, r0 - bf 4f - -3: - mov.l @r8, r0 -5: - tst r0, r0 - bt 6b - - mov r0, r3 - mov r0, r4 - add #-1, r3 - CMPXCHG (r4, @r8, r3, r2) - bf/s 5b - mov r2, r0 - - DEC (@(NWAITERS,r8), r2) - bra 7b - nop - -4: - neg r0, r0 - mov r0, r4 - DEC (@(NWAITERS,r8), r2) - mov r4, r8 - mova .Lgot0, r0 - mov.l .Lgot0, r12 - add r0, r12 - - mov.l .Lerrno0, r0 - stc gbr, r1 - mov.l @(r0, r12), r0 - bra .Lexit - add r1, r0 - .align 2 -.Lerrno0: - .long errno@GOTTPOFF -.Lexit: - mov.l r8, @r0 - bra 9b - mov #-1, r0 - - .align 2 -.Lgot0: - .long _GLOBAL_OFFSET_TABLE_ -.Lenable0: - .long __pthread_enable_asynccancel-.Lenable0b -.Ldisable0: - .long __pthread_disable_asynccancel-.Ldisable0b - .size __new_sem_wait,.-__new_sem_wait - versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1) - - - .type sem_wait_cleanup,@function -sem_wait_cleanup: - DEC (@(NWAITERS,r8), r2) -.LcallUR: - mov.l .Lresume, r1 -#ifdef PIC - add r12, r1 -#endif - jsr @r1 - nop - sleep - - .align 2 -.Lresume: -#ifdef PIC - .long _Unwind_Resume@GOTOFF -#else - .long _Unwind_Resume -#endif -.LENDCODE: - cfi_endproc - .size sem_wait_cleanup,.-sem_wait_cleanup - - - .section .gcc_except_table,"a",@progbits -.LexceptSTART: - .byte DW_EH_PE_omit ! @LPStart format (omit) - .byte DW_EH_PE_omit ! @TType format (omit) - .byte DW_EH_PE_uleb128 ! call-site format - .uleb128 .Lcstend-.Lcstbegin -.Lcstbegin: - .uleb128 .LcleanupSTART-.LSTARTCODE - .uleb128 .LcleanupEND-.LcleanupSTART - .uleb128 sem_wait_cleanup-.LSTARTCODE - .uleb128 0 - .uleb128 .LcallUR-.LSTARTCODE - .uleb128 .LENDCODE-.LcallUR - .uleb128 0 - .uleb128 0 -.Lcstend: - -#ifdef SHARED - .hidden DW.ref.__gcc_personality_v0 - .weak DW.ref.__gcc_personality_v0 - .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits - .align 4 - .type DW.ref.__gcc_personality_v0, @object - .size DW.ref.__gcc_personality_v0, 4 -DW.ref.__gcc_personality_v0: - .long __gcc_personality_v0 -#endif diff --git a/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/sysdeps/unix/sysv/linux/x86_64/sem_post.S deleted file mode 100644 index 1c11600..0000000 --- a/sysdeps/unix/sysv/linux/x86_64/sem_post.S +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include - - - .text - - .globl sem_post - .type sem_post,@function - .align 16 -sem_post: -#if VALUE == 0 - movl (%rdi), %eax -#else - movl VALUE(%rdi), %eax -#endif -0: cmpl $SEM_VALUE_MAX, %eax - je 3f - leal 1(%rax), %esi - LOCK -#if VALUE == 0 - cmpxchgl %esi, (%rdi) -#else - cmpxchgl %esi, VALUE(%rdi) -#endif - jnz 0b - - LP_OP(cmp) $0, NWAITERS(%rdi) - je 2f - - movl $SYS_futex, %eax - movl $FUTEX_WAKE, %esi - orl PRIVATE(%rdi), %esi - movl $1, %edx - syscall - - testq %rax, %rax - js 1f - -2: xorl %eax, %eax - retq - -1: - movl $EINVAL, %eax - jmp 4f - -3: - movl $EOVERFLOW, %eax - -4: - movq errno@gottpoff(%rip), %rdx - movl %eax, %fs:(%rdx) - orl $-1, %eax - retq - .size sem_post,.-sem_post diff --git a/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S deleted file mode 100644 index 880610e..0000000 --- a/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S +++ /dev/null @@ -1,380 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include - - .text - - .globl sem_timedwait - .type sem_timedwait,@function - .align 16 -sem_timedwait: -.LSTARTCODE: - cfi_startproc -#ifdef SHARED - cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, - DW.ref.__gcc_personality_v0) - cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) -#else - cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) - cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) -#endif -#if VALUE == 0 - movl (%rdi), %eax -#else - movl VALUE(%rdi), %eax -#endif -2: testl %eax, %eax - je 1f - - leaq -1(%rax), %rdx - LOCK -#if VALUE == 0 - cmpxchgl %edx, (%rdi) -#else - cmpxchgl %edx, VALUE(%rdi) -#endif - jne 2b - - xorl %eax, %eax - retq - - /* Check whether the timeout value is valid. */ -1: cmpq $1000000000, 8(%rsi) - jae 6f - -#ifndef __ASSUME_FUTEX_CLOCK_REALTIME -# ifdef PIC - cmpl $0, __have_futex_clock_realtime(%rip) -# else - cmpl $0, __have_futex_clock_realtime -# endif - je .Lreltmo -#endif - - cmpq $0, (%rsi) - js 16f - - /* This push is only needed to store the sem_t pointer for the - exception handler. */ - pushq %rdi - cfi_adjust_cfa_offset(8) - - movq %rsi, %r10 - - LOCK - LP_OP(add) $1, NWAITERS(%rdi) - -.LcleanupSTART: -13: call __pthread_enable_asynccancel - movl %eax, %r8d - -#if VALUE != 0 - leaq VALUE(%rdi), %rdi -#endif - movl $0xffffffff, %r9d - movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi - orl PRIVATE(%rdi), %esi - movl $SYS_futex, %eax - xorl %edx, %edx - syscall - movq %rax, %r9 -#if VALUE != 0 - leaq -VALUE(%rdi), %rdi -#endif - - xchgq %r8, %rdi - call __pthread_disable_asynccancel -.LcleanupEND: - movq %r8, %rdi - - testq %r9, %r9 - je 11f - cmpq $-EWOULDBLOCK, %r9 - jne 3f - -11: -#if VALUE == 0 - movl (%rdi), %eax -#else - movl VALUE(%rdi), %eax -#endif -14: testl %eax, %eax - je 13b - - leaq -1(%rax), %rcx - LOCK -#if VALUE == 0 - cmpxchgl %ecx, (%rdi) -#else - cmpxchgl %ecx, VALUE(%rdi) -#endif - jne 14b - - xorl %eax, %eax - -15: LOCK - LP_OP(sub) $1, NWAITERS(%rdi) - - leaq 8(%rsp), %rsp - cfi_adjust_cfa_offset(-8) - retq - - cfi_adjust_cfa_offset(8) -3: negq %r9 - movq errno@gottpoff(%rip), %rdx - movl %r9d, %fs:(%rdx) - - orl $-1, %eax - jmp 15b - - cfi_adjust_cfa_offset(-8) -6: - movq errno@gottpoff(%rip), %rdx - movl $EINVAL, %fs:(%rdx) - - orl $-1, %eax - - retq - -16: - movq errno@gottpoff(%rip), %rdx - movl $ETIMEDOUT, %fs:(%rdx) - - orl $-1, %eax - - retq - -#ifndef __ASSUME_FUTEX_CLOCK_REALTIME -.Lreltmo: - pushq %r12 - cfi_adjust_cfa_offset(8) - cfi_rel_offset(%r12, 0) - pushq %r13 - cfi_adjust_cfa_offset(8) - cfi_rel_offset(%r13, 0) - pushq %r14 - cfi_adjust_cfa_offset(8) - cfi_rel_offset(%r14, 0) - -#ifdef __ASSUME_FUTEX_CLOCK_REALTIME -# define STACKFRAME 8 -#else -# define STACKFRAME 24 -#endif - subq $STACKFRAME, %rsp - cfi_adjust_cfa_offset(STACKFRAME) - - movq %rdi, %r12 - movq %rsi, %r13 - - LOCK - LP_OP(add) $1, NWAITERS(%r12) - -7: xorl %esi, %esi - movq %rsp,%rdi - /* This call works because we directly jump to a system call entry - which preserves all the registers. */ - call JUMPTARGET(__gettimeofday) - - /* Compute relative timeout. */ - movq 8(%rsp), %rax - movl $1000, %edi - mul %rdi /* Milli seconds to nano seconds. */ - movq (%r13), %rdi - movq 8(%r13), %rsi - subq (%rsp), %rdi - subq %rax, %rsi - jns 5f - addq $1000000000, %rsi - decq %rdi -5: testq %rdi, %rdi - movl $ETIMEDOUT, %r14d - js 36f /* Time is already up. */ - - movq %rdi, (%rsp) /* Store relative timeout. */ - movq %rsi, 8(%rsp) - -.LcleanupSTART2: - call __pthread_enable_asynccancel - movl %eax, 16(%rsp) - - movq %rsp, %r10 -# if VALUE == 0 - movq %r12, %rdi -# else - leaq VALUE(%r12), %rdi -# endif -# if FUTEX_WAIT == 0 - movl PRIVATE(%rdi), %esi -# else - movl $FUTEX_WAIT, %esi - orl PRIVATE(%rdi), %esi -# endif - movl $SYS_futex, %eax - xorl %edx, %edx - syscall - movq %rax, %r14 - - movl 16(%rsp), %edi - call __pthread_disable_asynccancel -.LcleanupEND2: - - testq %r14, %r14 - je 9f - cmpq $-EWOULDBLOCK, %r14 - jne 33f - -9: -# if VALUE == 0 - movl (%r12), %eax -# else - movl VALUE(%r12), %eax -# endif -8: testl %eax, %eax - je 7b - - leaq -1(%rax), %rcx - LOCK -# if VALUE == 0 - cmpxchgl %ecx, (%r12) -# else - cmpxchgl %ecx, VALUE(%r12) -# endif - jne 8b - - xorl %eax, %eax - -45: LOCK - LP_OP(sub) $1, NWAITERS(%r12) - - addq $STACKFRAME, %rsp - cfi_adjust_cfa_offset(-STACKFRAME) - popq %r14 - cfi_adjust_cfa_offset(-8) - cfi_restore(%r14) - popq %r13 - cfi_adjust_cfa_offset(-8) - cfi_restore(%r13) - popq %r12 - cfi_adjust_cfa_offset(-8) - cfi_restore(%r12) - retq - - cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) - cfi_rel_offset(%r12, STACKFRAME + 2 * 8) - cfi_rel_offset(%r13, STACKFRAME + 1 * 8) - cfi_rel_offset(%r14, STACKFRAME) -33: negq %r14 -36: - movq errno@gottpoff(%rip), %rdx - movl %r14d, %fs:(%rdx) - - orl $-1, %eax - jmp 45b -#endif - cfi_endproc - .size sem_timedwait,.-sem_timedwait - - - .type sem_timedwait_cleanup,@function -sem_timedwait_cleanup: - cfi_startproc - cfi_adjust_cfa_offset(8) - - movq (%rsp), %rdi - LOCK - LP_OP(sub) $1, NWAITERS(%rdi) - movq %rax, %rdi -.LcallUR: - call _Unwind_Resume@PLT - hlt -.LENDCODE: - cfi_endproc - .size sem_timedwait_cleanup,.-sem_timedwait_cleanup - - -#ifndef __ASSUME_FUTEX_CLOCK_REALTIME - .type sem_timedwait_cleanup2,@function -sem_timedwait_cleanup2: - cfi_startproc - cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) - cfi_rel_offset(%r12, STACKFRAME + 2 * 8) - cfi_rel_offset(%r13, STACKFRAME + 1 * 8) - cfi_rel_offset(%r14, STACKFRAME) - - LOCK - LP_OP(sub) $1, NWAITERS(%r12) - movq %rax, %rdi - movq STACKFRAME(%rsp), %r14 - movq STACKFRAME+8(%rsp), %r13 - movq STACKFRAME+16(%rsp), %r12 -.LcallUR2: - call _Unwind_Resume@PLT - hlt -.LENDCODE2: - cfi_endproc - .size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2 -#endif - - - .section .gcc_except_table,"a",@progbits -.LexceptSTART: - .byte DW_EH_PE_omit # @LPStart format - .byte DW_EH_PE_omit # @TType format - .byte DW_EH_PE_uleb128 # call-site format - .uleb128 .Lcstend-.Lcstbegin -.Lcstbegin: - .uleb128 .LcleanupSTART-.LSTARTCODE - .uleb128 .LcleanupEND-.LcleanupSTART - .uleb128 sem_timedwait_cleanup-.LSTARTCODE - .uleb128 0 -#ifndef __ASSUME_FUTEX_CLOCK_REALTIME - .uleb128 .LcleanupSTART2-.LSTARTCODE - .uleb128 .LcleanupEND2-.LcleanupSTART2 - .uleb128 sem_timedwait_cleanup2-.LSTARTCODE - .uleb128 0 -#endif - .uleb128 .LcallUR-.LSTARTCODE - .uleb128 .LENDCODE-.LcallUR - .uleb128 0 - .uleb128 0 -#ifndef __ASSUME_FUTEX_CLOCK_REALTIME - .uleb128 .LcallUR2-.LSTARTCODE - .uleb128 .LENDCODE2-.LcallUR2 - .uleb128 0 - .uleb128 0 -#endif -.Lcstend: - - -#ifdef SHARED - .hidden DW.ref.__gcc_personality_v0 - .weak DW.ref.__gcc_personality_v0 - .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits - .align LP_SIZE - .type DW.ref.__gcc_personality_v0, @object - .size DW.ref.__gcc_personality_v0, LP_SIZE -DW.ref.__gcc_personality_v0: - ASM_ADDR __gcc_personality_v0 -#endif diff --git a/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S deleted file mode 100644 index 1893a34..0000000 --- a/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include - - .text - - .globl sem_trywait - .type sem_trywait,@function - .align 16 -sem_trywait: - movl (%rdi), %eax -2: testl %eax, %eax - jz 1f - - leal -1(%rax), %edx - LOCK - cmpxchgl %edx, (%rdi) - jne 2b - - xorl %eax, %eax - retq - -1: - movq errno@gottpoff(%rip), %rdx - movl $EAGAIN, %fs:(%rdx) - orl $-1, %eax - retq - .size sem_trywait,.-sem_trywait diff --git a/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/sysdeps/unix/sysv/linux/x86_64/sem_wait.S deleted file mode 100644 index 8f4d068..0000000 --- a/sysdeps/unix/sysv/linux/x86_64/sem_wait.S +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include - - - .text - - .globl sem_wait - .type sem_wait,@function - .align 16 -sem_wait: -.LSTARTCODE: - cfi_startproc -#ifdef SHARED - cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, - DW.ref.__gcc_personality_v0) - cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) -#else - cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) - cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) -#endif - -#if VALUE == 0 - movl (%rdi), %eax -#else - movl VALUE(%rdi), %eax -#endif -2: testl %eax, %eax - je 1f - - leal -1(%rax), %edx - LOCK -#if VALUE == 0 - cmpxchgl %edx, (%rdi) -#else - cmpxchgl %edx, VALUE(%rdi) -#endif - jne 2b - - xorl %eax, %eax - retq - - /* This push is only needed to store the sem_t pointer for the - exception handler. */ -1: pushq %rdi - cfi_adjust_cfa_offset(8) - - LOCK - LP_OP(add) $1, NWAITERS(%rdi) - -.LcleanupSTART: -6: call __pthread_enable_asynccancel - movl %eax, %r8d - - xorq %r10, %r10 - movl $SYS_futex, %eax -#if FUTEX_WAIT == 0 - movl PRIVATE(%rdi), %esi -#else - movl $FUTEX_WAIT, %esi - orl PRIVATE(%rdi), %esi -#endif - xorl %edx, %edx - syscall - movq %rax, %rcx - - xchgq %r8, %rdi - call __pthread_disable_asynccancel -.LcleanupEND: - movq %r8, %rdi - - testq %rcx, %rcx - je 3f - cmpq $-EWOULDBLOCK, %rcx - jne 4f - -3: -#if VALUE == 0 - movl (%rdi), %eax -#else - movl VALUE(%rdi), %eax -#endif -5: testl %eax, %eax - je 6b - - leal -1(%rax), %edx - LOCK -#if VALUE == 0 - cmpxchgl %edx, (%rdi) -#else - cmpxchgl %edx, VALUE(%rdi) -#endif - jne 5b - - xorl %eax, %eax - -9: LOCK - LP_OP(sub) $1, NWAITERS(%rdi) - - leaq 8(%rsp), %rsp - cfi_adjust_cfa_offset(-8) - - retq - - cfi_adjust_cfa_offset(8) -4: negq %rcx - movq errno@gottpoff(%rip), %rdx - movl %ecx, %fs:(%rdx) - orl $-1, %eax - - jmp 9b - .size sem_wait,.-sem_wait - - - .type sem_wait_cleanup,@function -sem_wait_cleanup: - movq (%rsp), %rdi - LOCK - LP_OP(sub) $1, NWAITERS(%rdi) - movq %rax, %rdi -.LcallUR: - call _Unwind_Resume@PLT - hlt -.LENDCODE: - cfi_endproc - .size sem_wait_cleanup,.-sem_wait_cleanup - - - .section .gcc_except_table,"a",@progbits -.LexceptSTART: - .byte DW_EH_PE_omit # @LPStart format - .byte DW_EH_PE_omit # @TType format - .byte DW_EH_PE_uleb128 # call-site format - .uleb128 .Lcstend-.Lcstbegin -.Lcstbegin: - .uleb128 .LcleanupSTART-.LSTARTCODE - .uleb128 .LcleanupEND-.LcleanupSTART - .uleb128 sem_wait_cleanup-.LSTARTCODE - .uleb128 0 - .uleb128 .LcallUR-.LSTARTCODE - .uleb128 .LENDCODE-.LcallUR - .uleb128 0 - .uleb128 0 -.Lcstend: - - -#ifdef SHARED - .hidden DW.ref.__gcc_personality_v0 - .weak DW.ref.__gcc_personality_v0 - .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits - .align LP_SIZE - .type DW.ref.__gcc_personality_v0, @object - .size DW.ref.__gcc_personality_v0, LP_SIZE -DW.ref.__gcc_personality_v0: - ASM_ADDR __gcc_personality_v0 -#endif