From patchwork Fri Dec 5 19:24:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Torvald Riegel X-Patchwork-Id: 4095 Received: (qmail 16209 invoked by alias); 5 Dec 2014 19:24:20 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 16198 invoked by uid 89); 5 Dec 2014 19:24:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_50, LOTS_OF_MONEY, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Subject: Re: [PATCH 3/3] Update to new generic semaphore algorithm. From: Torvald Riegel To: GLIBC Devel In-Reply-To: <1417804668.22797.108.camel@triegel.csb> References: <1417804668.22797.108.camel@triegel.csb> Date: Fri, 05 Dec 2014 20:24:06 +0100 Message-ID: <1417807446.25868.24.camel@triegel.csb> Mime-Version: 1.0 This changes the generic C implementation of semaphores to use different algorithms. The core issue of the old implementation was that it kept two fields for both the value of the semaphore (ie, how many tokens it has that can be acquired by sem_wait calls) and the number of threads waiting to acquire a token using a futex_wait. We want to track the latter to be able to avoid calling futex_wake if there is actually no waiter. We can't put both of these counters into one 32b field because of the number of threads and or tokens we need to support. When users try to use sem_wait in the way discussed in http://austingroupbugs.net/view.php?id=811 then one thread calls sem_post, and another calls sem_wait *and* expects that once it has the token (ie, sem_wait has returned), it can call sem_destroy. Therefore, the implementation needs to ensure that sem_post makes no access to the semaphore data structure after it has provided a token. If we have 64b atomic operations, we can atomically increment the value of the semaphore and load the field counting the number of waiters. If we just have 32b operations, we need to do something more involved. The key here is to track a conservative value for the number of waiters in one bit of the value, and use that. Because it's a conservative value, it may be wrong and we may call futex_wake unnecessarily under some conditions. When we reset this bit (ie, speculate that there are no other waiters), we can be wrong but can make this misspeculation harmless if we wake as many waiters as there are tokens available. We do all these latter steps in sem_wait to still satisfy the requirement for sem_post regarding not accessing the semaphore after providing a token. Detailed comments can be found in the patch itself; see nptl/sem_wait.c. The semaphore data structure is adapted accordingly, as are other related functions: sem_open, sem_init, sem_getvalue, sem_trywait, sem_timedwait. because sem_trywait and sem_timedwait are very small, it seemed best to simply put them all into sem_wait.c I removed nptl/DESIGN-sem.txt because it was outdated and the comments in the code provide much more detail. The changes to tst-sem11 and tst-sem13 are simple adaptions; they peek inside the semaphore data structure. The custom assembler implementations on x86, x86_64, and sh have been removed. alpha and powerpc had custom sem_post implementations, but all that those were lacking compared to the generic version was a write barrier in sem_post. The new algorithm is correctly synchronized; for the old version of sem_post, I have added a call to atomic_write_barrier directly. This allows us to remove the custom alpha and powerpc variants. sparc still has its own semaphore implementation. I'd like to get feedback from sparc maintainers regarding what should happen with it. Note that this patch set is on top of the patch providing a new internal futex API: https://sourceware.org/ml/libc-alpha/2014-12/msg00154.html Tested on x86 and x86_64. I have not tested the old versions (__old_sem*) yet. [BZ #12674] * nptl/sem_wait.c(__new_sem_wait_fast): New function. Implement new semaphore algorithms. (__new_sem_wait_slow): New function. (__sem_wait_32_finish): New function. (__sem_wait_cleanup): Adapt. (do_futex_wait_inner): Adapt. (do_futex_wait): Adapt. (__new_sem_wait): Adapt. (sem_timedwait): New function. (__new_sem_trywait): New function. (__old_sem_trywait): Moved here from nptl/sem_trywait.c. * nptl/sem_post.c (__new_sem_post): Adapt. (__old_sem_post): Add release fence. * nptl/sem_open.c (sem_open): Adapt. * nptl/sem_init.c (__new_sem_init): Adapt. * nptl/sem_getvalue.c (__new_sem_getvalue): Adapt. (__old_sem_getvalue): Add using previous code. * sysdeps/nptl/internaltypes.h: Adapt. * nptl/tst-sem13.c (do_test): Adapt. * nptl/tst-sem11.c (main): Adapt. * nptl/sem_timedwait.c: Remove. * nptl/sem_trywait.c: Remove. * nptl/DESIGN-sem.txt: Remove. * nptl/Makefile (libpthread-routines): Remove sem_trywait, sem_wait. (gen-as-const-headers): Remove structsem.sym. * nptl/structsem.sym: Remove. * sysdeps/unix/sysv/linux/alpha/sem_post.c: Remove. * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Remove. * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Remove. * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Remove. * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Remove. * sysdeps/unix/sysv/linux/i386/i586/sem_post.S: Remove. * sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S: Remove. * sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S: Remove. * sysdeps/unix/sysv/linux/i386/i586/sem_wait.S: Remove. * sysdeps/unix/sysv/linux/i386/i686/sem_post.S: Remove. * sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S: Remove. * sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S: Remove. * sysdeps/unix/sysv/linux/i386/i686/sem_wait.S: Remove. * sysdeps/unix/sysv/linux/powerpc/sem_post.c: Remove. * sysdeps/unix/sysv/linux/sh/sem_post.S: Remove. * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Remove. * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Remove. * sysdeps/unix/sysv/linux/sh/sem_wait.S: Remove. * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Remove. * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Remove. * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Remove. * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Remove. 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