generic locking
Ian Wienand <[email protected]>
| Newsgroups | gmane.comp.lib.phil |
|---|---|
| Message-ID | <[email protected]> |
On Sat, Mar 08, 2003 at 03:37:05AM -0800, Roland McGrath wrote: > Looks pretty good! I count five, maybe seven, macros in lowlevellock.h > that are machine-dependent, and the rest of that file and all the rest of > the locking code (except spinlocks) can move up to linux/ and be common to > all the machines where compare_and_swap is as good as it gets. Attached is what I was thinking to make the locking code more generic. It applies on top of the previous IA64 patch (apply from the NPTL directory). I don't expect it to be much more than a warning for other people as to what they *shouldn't* do but I appreciate feedback. -i [email protected] http://www.gelato.unsw.edu.au
lock-generic.patch
(text/plain, 55.3 KB)
diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c ./sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,19 +0,0 @@ -/* Copyright (C) 2003 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* Not needed. lll_mutex_* implementation is the same as lll_*. */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c ./sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,21 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* No difference to lowlevelmutex.c */ -#include "lowlevelmutex.c" diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevel-atomic.h ./sysdeps/unix/sysv/linux/ia64/lowlevel-atomic.h --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevel-atomic.h 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/ia64/lowlevel-atomic.h 2003-03-10 14:27:50.000000000 +1100 @@ -0,0 +1,106 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELATOMIC_H +#define _LOWLEVELATOMIC_H 1 + +#include <ia64intrin.h> + +#define SYS_futex 1230 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define lll_futex_clobbers \ + "out4", "out5", "out6", "out7", \ + /* Non-stacked integer registers, minus r8, r15. */ \ + "r2", "r3", "r9", "r10", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ + "r28", "r29", "r30", "r31", \ + /* Predicate registers. */ \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + /* Non-rotating fp registers. */ \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + /* Branch registers. */ \ + "b6", "b7", \ + "memory" + +#define lll_futex_wait(futex, val) \ + ({ \ + register unsigned long int __o0 asm ("out0") \ + = (unsigned long int) (futex); \ + register unsigned long int __o1 asm ("out1") = FUTEX_WAIT; \ + register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\ + register unsigned long int __o3 asm ("out3") = 0ul; \ + register unsigned long int __r8 asm ("r8"); \ + register unsigned long int __r15 asm ("r15") = SYS_futex; \ + \ + __asm __volatile ("break %2;;" \ + : "=r" (__r8), "=r" (__r15) \ + : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1), \ + "r" (__o2), "r" (__o3) \ + : lll_futex_clobbers); \ + __r8; \ + }) + + +#define lll_futex_timed_wait(futex, val, timespec) \ + ({ \ + register unsigned long int __o0 asm ("out0") \ + = (unsigned long int) (futex); \ + register unsigned long int __o1 asm ("out1") = FUTEX_WAIT; \ + register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\ + register unsigned long int __o3 asm ("out3") \ + = (unsigned long int) (timespec); \ + register unsigned long int __r8 asm ("r8"); \ + register unsigned long int __r15 asm ("r15") = SYS_futex; \ + \ + __asm __volatile ("break %2;;" \ + : "=r" (__r8), "=r" (__r15) \ + : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1), \ + "r" (__o2), "r" (__o3) \ + : lll_futex_clobbers); \ + __r8; \ + }) + + +#define lll_futex_wake(futex, nr) \ + ({ \ + register unsigned long int __o0 asm ("out0") \ + = (unsigned long int) (futex); \ + register unsigned long int __o1 asm ("out1") = FUTEX_WAKE; \ + register unsigned long int __o2 asm ("out2") = (unsigned long int) (nr); \ + register unsigned long int __r8 asm ("r8"); \ + register unsigned long int __r15 asm ("r15") = SYS_futex; \ + \ + __asm __volatile ("break %2;;" \ + : "=r" (__r8), "=r" (__r15) \ + : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1), \ + "r" (__o2) \ + : "out3", lll_futex_clobbers); \ + __r8; \ + }) + +#define lll_compare_and_swap(futex, oldval, newval) \ + __sync_val_compare_and_swap_si ((futex), (oldval), (newval)) + +#define lll_atomic_increment(mem) __sync_add_and_fetch(mem, 1) + +#define lll_atomic_decrement(mem) __sync_sub_and_fetch(mem, 1) + +#endif /* lowlevellock.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c ./sysdeps/unix/sysv/linux/ia64/lowlevellock.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/lowlevellock.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,85 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevellock.h> -#include <sys/time.h> - - -int -lll_unlock_wake_cb (futex) - int *futex; -{ - int oldval; - int val = *futex; - - do - oldval = val; - while ((val = lll_compare_and_swap (futex, oldval, 0)) != oldval); - if (oldval > 1) - lll_futex_wake (futex, 1); - return 0; -} -hidden_proto (lll_unlock_wake_cb) - - -int -___lll_timedwait_tid (ptid, abstime) - int *ptid; - const struct timespec *abstime; -{ - int tid; - - if (abstime == NULL || abstime->tv_nsec >= 1000000000) - return EINVAL; - - /* Repeat until thread terminated. */ - while ((tid = *ptid) != 0) - { - /* Get current time. */ - struct timeval tv; - gettimeofday (&tv, NULL); - - /* Determine relative timeout. */ - struct timespec rt; - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - rt.tv_sec--; - } - /* Already timed out? */ - if (rt.tv_sec < 0) - return ETIMEDOUT; - - /* Wait until thread terminates. */ - int err = lll_futex_timed_wait (ptid, tid, &rt); - - /* Woken due to timeout? */ - if (err == -ETIMEDOUT) - /* Yes. */ - return ETIMEDOUT; - } - - return 0; -} - -hidden_proto (___lll_timedwait_tid) diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h ./sysdeps/unix/sysv/linux/ia64/lowlevellock.h --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/lowlevellock.h 1970-01-01 10:00:00.000000000 +1000 @@ -1,248 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _LOWLEVELLOCK_H -#define _LOWLEVELLOCK_H 1 - -#include <time.h> -#include <sys/param.h> -#include <bits/pthreadtypes.h> -#include <ia64intrin.h> - -#define SYS_futex 1230 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 - -/* Initializer for compatibility lock. */ -#define LLL_MUTEX_LOCK_INITIALIZER (0) - -#define lll_futex_clobbers \ - "out4", "out5", "out6", "out7", \ - /* Non-stacked integer registers, minus r8, r15. */ \ - "r2", "r3", "r9", "r10", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ - "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ - "r28", "r29", "r30", "r31", \ - /* Predicate registers. */ \ - "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ - /* Non-rotating fp registers. */ \ - "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ - /* Branch registers. */ \ - "b6", "b7", \ - "memory" - -#define lll_futex_wait(futex, val) \ - ({ \ - register unsigned long int __o0 asm ("out0") \ - = (unsigned long int) (futex); \ - register unsigned long int __o1 asm ("out1") = FUTEX_WAIT; \ - register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\ - register unsigned long int __o3 asm ("out3") = 0ul; \ - register unsigned long int __r8 asm ("r8"); \ - register unsigned long int __r15 asm ("r15") = SYS_futex; \ - \ - __asm __volatile ("break %2;;" \ - : "=r" (__r8), "=r" (__r15) \ - : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1), \ - "r" (__o2), "r" (__o3) \ - : lll_futex_clobbers); \ - __r8; \ - }) - - -#define lll_futex_timed_wait(futex, val, timespec) \ - ({ \ - register unsigned long int __o0 asm ("out0") \ - = (unsigned long int) (futex); \ - register unsigned long int __o1 asm ("out1") = FUTEX_WAIT; \ - register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\ - register unsigned long int __o3 asm ("out3") \ - = (unsigned long int) (timespec); \ - register unsigned long int __r8 asm ("r8"); \ - register unsigned long int __r15 asm ("r15") = SYS_futex; \ - \ - __asm __volatile ("break %2;;" \ - : "=r" (__r8), "=r" (__r15) \ - : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1), \ - "r" (__o2), "r" (__o3) \ - : lll_futex_clobbers); \ - __r8; \ - }) - - -#define lll_futex_wake(futex, nr) \ - ({ \ - register unsigned long int __o0 asm ("out0") \ - = (unsigned long int) (futex); \ - register unsigned long int __o1 asm ("out1") = FUTEX_WAKE; \ - register unsigned long int __o2 asm ("out2") = (unsigned long int) (nr); \ - register unsigned long int __r8 asm ("r8"); \ - register unsigned long int __r15 asm ("r15") = SYS_futex; \ - \ - __asm __volatile ("break %2;;" \ - : "=r" (__r8), "=r" (__r15) \ - : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1), \ - "r" (__o2) \ - : "out3", lll_futex_clobbers); \ - __r8; \ - }) - -#define lll_compare_and_swap(futex, oldval, newval) \ - __sync_val_compare_and_swap_si ((futex), (oldval), (newval)) - -static inline int -__attribute__ ((always_inline)) -__lll_mutex_trylock (int *futex) -{ - return lll_compare_and_swap (futex, 0, 1) != 0; -} -#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) - - -extern void ___lll_mutex_lock (int *, int) attribute_hidden; - - -static inline void -__attribute__ ((always_inline)) -__lll_mutex_lock (int *futex) -{ - int oldval; - int val = *futex; - - do - oldval = val; - while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) != oldval); - if (oldval > 0) - ___lll_mutex_lock (futex, oldval + 1); -} -#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) - - -extern int ___lll_mutex_timedlock (int *, const struct timespec *, int) - attribute_hidden; - - -static inline int -__attribute__ ((always_inline)) -__lll_mutex_timedlock (int *futex, const struct timespec *abstime) -{ - int oldval; - int val = *futex; - int result = 0; - - do - oldval = val; - while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) != oldval); - if (oldval > 0) - result = ___lll_mutex_timedlock (futex, abstime, oldval + 1); - - return result; -} -#define lll_mutex_timedlock(futex, abstime) \ - __lll_mutex_timedlock (&(futex), abstime) - - -static inline void -__attribute__ ((always_inline)) -__lll_mutex_unlock (int *futex) -{ - int oldval; - int val = *futex; - - do - oldval = val; - while ((val = lll_compare_and_swap (futex, oldval, 0)) != oldval); - if (oldval > 1) - lll_futex_wake (futex, 1); -} -#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) - -#define lll_mutex_islocked(futex) \ - (futex != 0) - - -/* We have a separate internal lock implementation which is not tied - to binary compatibility. We can use the lll_mutex_*. */ - -/* Type for lock object. */ -typedef int lll_lock_t; - -extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; - -/* Initializers for lock. */ -#define LLL_LOCK_INITIALIZER (0) -#define LLL_LOCK_INITIALIZER_LOCKED (1) - -#define lll_trylock(futex) lll_mutex_trylock (futex) -#define lll_lock(futex) lll_mutex_lock (futex) -#define lll_unlock(futex) lll_mutex_unlock (futex) -#define lll_islocked(futex) lll_mutex_islocked (futex) - - -/* The kernel notifies a process with uses CLONE_CLEARTID via futex - wakeup when the clone terminates. The memory location contains the - thread ID while the clone is running and is reset to zero - afterwards. */ -static inline void -__attribute__ ((always_inline)) -__lll_wait_tid (int *ptid) -{ - int tid; - - while ((tid = *ptid) != 0) - lll_futex_wait (ptid, tid); -} -#define lll_wait_tid(tid) __lll_wait_tid(&(tid)) - - -extern int ___lll_timedwait_tid (int *, const struct timespec *) - attribute_hidden; -static inline int -__attribute__ ((always_inline)) -__lll_timedwait_tid (int *ptid, const struct timespec *abstime) -{ - if (*ptid == 0) - return 0; - - return ___lll_timedwait_tid (ptid, abstime); -} -#define lll_timedwait_tid(tid, abstime) __lll_timedwait_tid (&(tid), abstime) - - -/* Conditional variable handling. */ - -extern void __lll_cond_wait (pthread_cond_t *cond) - attribute_hidden; -extern int __lll_cond_timedwait (pthread_cond_t *cond, - const struct timespec *abstime) - attribute_hidden; -extern void __lll_cond_wake (pthread_cond_t *cond) - attribute_hidden; -extern void __lll_cond_broadcast (pthread_cond_t *cond) - attribute_hidden; - -#define lll_cond_wait(cond) \ - __lll_cond_wait (cond) -#define lll_cond_timedwait(cond, abstime) \ - __lll_cond_timedwait (cond, abstime) -#define lll_cond_wake(cond) \ - __lll_cond_wake (cond) -#define lll_cond_broadcast(cond) \ - __lll_cond_broadcast (cond) - -#endif /* lowlevellock.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c ./sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,100 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevellock.h> -#include <sys/time.h> - - -void -___lll_mutex_lock (futex, newval) - int *futex; - int newval; -{ - int oldval, val; - - do - { - lll_futex_wait (futex, newval); - val = *futex; - do - oldval = val; - while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) - != oldval); - newval = val + 1; - } - while (val != 0); - - *futex = 2; -} -hidden_proto (___lll_mutex_lock) - - -int -___lll_mutex_timedlock (futex, abstime, newval) - int *futex; - const struct timespec *abstime; - int newval; -{ - /* Reject invalid timeouts. */ - if (abstime->tv_nsec >= 1000000000) - return EINVAL; - - int oldval, val; - do - { - /* Get the current time. */ - struct timeval tv; - gettimeofday (&tv, NULL); - - /* Compute relative timeout. */ - struct timespec rt; - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - --rt.tv_sec; - } - /* Already timed out? */ - if (rt.tv_sec < 0) - return ETIMEDOUT; - - /* Wait. */ - int err = lll_futex_timed_wait (futex, newval, &rt); - - /* If timed out return with an appropriate error. */ - if (err == -ETIMEDOUT) - return ETIMEDOUT; - - val = *futex; - do - oldval = val; - while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) - != oldval); - newval = val + 1; - } - while (val != 0); - - *futex = 2; - - return 0; -} -hidden_proto (___lll_mutex_timedlock) diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelsem.h ./sysdeps/unix/sysv/linux/ia64/lowlevelsem.h --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelsem.h 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/lowlevelsem.h 1970-01-01 10:00:00.000000000 +1000 @@ -1,79 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _LOWLEVELSEM_H -#define _LOWLEVELSEM_H 1 - -#include <dl-sysdep.h> -#include <tls.h> -#include <lowlevellock.h> -#include <semaphore.h> - - -static inline int -__attribute__ ((always_inline)) -lll_sem_wait (sem_t *sem) -{ - int oldval, val; - - val = *(int *) sem; - do - { - if (__builtin_expect (val == 0, 0)) - { - /* Do wait. */ - int err = lll_futex_wait ((int *) sem, 0); - - /* Handle EINTR. */ - if (err != 0 && err != -EWOULDBLOCK) - return -err; - - val = *(int *) sem; - } - oldval = val; - } - while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) - != oldval); - return 0; -} - - -#if 0 -/* Not defined anywhere. */ -extern int __lll_sem_timedwait (sem_t *sem, const struct timespec *ts) - attribute_hidden; -#define lll_sem_timedwait(sem, timeout) \ - __lll_sem_timedwait (sem, timeout) -#endif - -static inline void -__attribute__ ((always_inline)) -lll_sem_post (sem_t *sem) -{ - int oldval, val; - - val = *(int *) sem; - do - oldval = val; - while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval + 1)) - != oldval); - lll_futex_wake ((int *) sem, oldval + 1); -} - -#endif /* lowlevelsem.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c ./sysdeps/unix/sysv/linux/ia64/sem_post.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/sem_post.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,51 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevelsem.h> -#include <internaltypes.h> - -#include <shlib-compat.h> - - -int -__new_sem_post (sem_t *sem) -{ - int oldval, val; - int err; - - val = *(int *) sem; - do - oldval = val; - while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval + 1)) - != oldval); - err = lll_futex_wake ((int *) sem, oldval + 1); - if (err < 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) -strong_alias (__new_sem_post, __old_sem_post) -compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); -#endif diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c ./sysdeps/unix/sysv/linux/ia64/sem_timedwait.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/sem_timedwait.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,91 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevelsem.h> -#include <internaltypes.h> - -#include <shlib-compat.h> - - -int -sem_timedwait (sem, abstime) - sem_t *sem; - const struct timespec *abstime; -{ - int oldval, val; - - val = *(int *) sem; - do - { - while (__builtin_expect (val == 0, 0)) - { - /* Check for invalid timeout values. */ - if (abstime->tv_nsec >= 1000000000) - { - __set_errno(EINVAL); - return -1; - } - - /* Get the current time. */ - struct timeval tv; - gettimeofday(&tv, NULL); - - /* Compute the relative timeout. */ - struct timespec rt; - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - rt.tv_sec--; - } - /* Already timed out. */ - if (rt.tv_sec < 0) - { - __set_errno (ETIMEDOUT); - return -1; - } - - /* Do wait. */ - int err = lll_futex_timed_wait ((int *) sem, 0, &rt); - - /* Returned after timing out? */ - if (err == -ETIMEDOUT) - { - __set_errno (ETIMEDOUT); - return -1; - } - - /* Handle EINTR. */ - if (err != 0 && err != -EWOULDBLOCK) - { - __set_errno (-err); - return -1; - } - - val = *(int *) sem; - } - oldval = val; - } - while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) - != oldval); - return 0; -} diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c ./sysdeps/unix/sysv/linux/ia64/sem_trywait.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/sem_trywait.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,50 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevelsem.h> -#include <internaltypes.h> - -#include <shlib-compat.h> - - -int -__new_sem_trywait (sem_t *sem) -{ - int oldval, val = *(int *) sem; - - do - { - if (__builtin_expect (val == 0, 0)) - { - __set_errno (EAGAIN); - return -1; - } - oldval = val; - } - while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) - != oldval); - return 0; -} -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 -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c ./sysdeps/unix/sysv/linux/ia64/sem_wait.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c 2003-03-10 15:56:36.000000000 +1100 +++ ./sysdeps/unix/sysv/linux/ia64/sem_wait.c 1970-01-01 10:00:00.000000000 +1000 @@ -1,63 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sysdep.h> -#include <lowlevelsem.h> -#include <internaltypes.h> - -#include <shlib-compat.h> - - -int -__new_sem_wait (sem_t *sem) -{ - int oldval, val; - - /* Atomically decrement semaphore counter if it is > 0. */ - val = *(int *) sem; - do - { - while (__builtin_expect (val == 0, 0)) - { - /* Do wait. */ - int err = lll_futex_wait ((int *) sem, 0); - - /* Handle EINTR. */ - if (err != 0 && err != -EWOULDBLOCK) - { - __set_errno (-err); - return -1; - } - - val = *(int *) sem; - } - oldval = val; - } - while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) - != oldval); - - return 0; -} - -versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); -#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) -strong_alias (__new_sem_wait, __old_sem_wait) -compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); -#endif diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c ./sysdeps/unix/sysv/linux/libc-lowlevellock.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/libc-lowlevellock.c 2003-03-10 08:44:57.000000000 +1100 @@ -0,0 +1,19 @@ +/* Copyright (C) 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Not needed. lll_mutex_* implementation is the same as lll_*. */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/libc-lowlevelmutex.c ./sysdeps/unix/sysv/linux/libc-lowlevelmutex.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/libc-lowlevelmutex.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/libc-lowlevelmutex.c 2003-03-10 11:26:19.000000000 +1100 @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* all in lowlevellock.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevellock.c ./sysdeps/unix/sysv/linux/lowlevellock.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevellock.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/lowlevellock.c 2003-03-10 12:30:39.000000000 +1100 @@ -0,0 +1,132 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> + + +int +___lll_timedlock (int *futex, const struct timespec *abstime) +{ + + lll_atomic_increment(futex); + if ( *futex > 1 ) + { + /* Reject invalid timeouts. */ + if (abstime->tv_nsec >= 1000000000) + return EINVAL; + + int oldval; + do + { + /* Get the current time. */ + struct timeval tv; + gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + int err = lll_futex_timed_wait (futex, *futex, &rt); + + /* If timed out return with an appropriate error. */ + if (err == -ETIMEDOUT) + return ETIMEDOUT; + + lll_atomic_increment(futex); + } + while (*futex != 1); + + *futex = 2; + } + return 0; +} + + +hidden_proto (___lll_timedlock) + + +int +lll_unlock_wake_cb (futex) + int *futex; +{ + lll_atomic_increment(futex); + + if ( *futex < 0 ) + lll_futex_wake(futex, 1); + + return 0; +} +hidden_proto (lll_unlock_wake_cb) + + +int +___lll_timedwait_tid (ptid, abstime) + int *ptid; + const struct timespec *abstime; +{ + int tid; + + if (abstime == NULL || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *ptid) != 0) + { + /* Get current time. */ + struct timeval tv; + gettimeofday (&tv, NULL); + + /* Determine relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + rt.tv_sec--; + } + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. */ + int err = lll_futex_timed_wait (ptid, tid, &rt); + + /* Woken due to timeout? */ + if (err == -ETIMEDOUT) + /* Yes. */ + return ETIMEDOUT; + } + + return 0; +} + +hidden_proto (___lll_timedwait_tid) diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevellock.h ./sysdeps/unix/sysv/linux/lowlevellock.h --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevellock.h 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/lowlevellock.h 2003-03-10 14:26:14.000000000 +1100 @@ -0,0 +1,157 @@ + /* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <tcb-offsets.h> + +#include <lowlevel-atomic.h> + +/* Initializer for compatibility lock. */ +#define LLL_MUTEX_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER (0) +typedef int lll_lock_t; + +static inline int +__attribute__ ((always_inline)) +__lll_trylock (int *futex) +{ + int result; + result = lll_compare_and_swap(futex, 0, 1); + return (result != 0); +} +#define lll_mutex_trylock(futex) __lll_trylock (&(futex)) +#define lll_trylock(futex) __lll_trylock(&(futex)) + +static inline void +__attribute__ ((always_inline)) +__lll_lock (int *futex) +{ + + int val = *futex; + lll_atomic_increment(futex); + if ( *futex > 1 ) + do { + lll_futex_wait(futex, val); + lll_atomic_increment(futex); + } while ( *futex != 1 ); + + *futex = 2; +} +#define lll_mutex_lock(futex) __lll_lock (&(futex)) +#define lll_lock(futex) __lll_lock(&(futex)) + +extern int ___lll_timedlock (int *, const struct timespec *) + attribute_hidden; + +static inline int +__attribute__ ((always_inline)) +__lll_timedlock (int *futex, struct timespec *abstime) +{ + return ___lll_timedlock( futex, abstime); +} +#define lll_mutex_timedlock(futex, abstime) \ + __lll_timedlock (&(futex), abstime) +#define lll_timedlock(futex, abstime) \ + __lll_timedlock (&(futex), abstime) + +static inline void +__attribute__ ((always_inline)) +__lll_unlock (int *futex) +{ + lll_atomic_decrement(futex); + if ( *futex > 0 ) + lll_futex_wake (futex, 1); + *futex = 0; +} +#define lll_mutex_unlock(futex) __lll_unlock(&(futex)) +#define lll_unlock(futex) __lll_unlock(&(futex)) + +#define lll_mutex_islocked(futex) lll_islocked(futex) +#define lll_islocked(futex) (futex != 0) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +static inline void +__attribute__ ((always_inline)) +__lll_wait_tid (int *ptid) +{ + int tid; + + while ((tid = *ptid) != 0) + lll_futex_wait (ptid, tid); +} +#define lll_wait_tid(tid) __lll_wait_tid(&(tid)) + + +extern int ___lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; +static inline int +__attribute__ ((always_inline)) +__lll_timedwait_tid (int *ptid, const struct timespec *abstime) +{ + if (*ptid == 0) + return 0; + + return ___lll_timedwait_tid (ptid, abstime); +} +#define lll_timedwait_tid(tid, abstime) __lll_timedwait_tid (&(tid), abstime) + + +static inline void +__attribute__ ((always_inline)) +__lll_wake_tid (int *ptid) +{ + *ptid = 0; + lll_futex_wake (ptid, INT_MAX); +} +#define lll_wake_tid(tid) __lll_wake_tid (&(tid)) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + + +/* Conditional variable handling. */ + +extern void __lll_cond_wait (pthread_cond_t *cond) + attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, + const struct timespec *abstime) + attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) + attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) + attribute_hidden; + +#define lll_cond_wait(cond) \ + __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ + __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ + __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ + __lll_cond_broadcast (cond) + +#endif /* lowlevellock.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevelmutex.c ./sysdeps/unix/sysv/linux/lowlevelmutex.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevelmutex.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/lowlevelmutex.c 2003-03-10 12:06:03.000000000 +1100 @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* we use the same implementation which is all in lowlevellock.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevelsem.h ./sysdeps/unix/sysv/linux/lowlevelsem.h --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/lowlevelsem.h 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/lowlevelsem.h 2003-03-10 15:46:17.000000000 +1100 @@ -0,0 +1,69 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELSEM_H +#define _LOWLEVELSEM_H 1 + +#include <dl-sysdep.h> +#include <tls.h> +#include <lowlevellock.h> +#include <semaphore.h> + +/* sem_wait holds the thread until we decrement the value to zero */ +static inline int +__attribute__ ((always_inline)) +lll_sem_wait (sem_t *sem) +{ + /* decrement the semaphore until it's zero (i.e we get it) */ + do { + /* we expect we can take it */ + if ( __builtin_expect( *(int *)sem == 0, 0) ) + { + /* Do wait. */ + int err = lll_futex_wait ((int *) sem, 0); + + /* Handle EINTR. */ + if (err != 0 && err != -EWOULDBLOCK) + return -err; + } + lll_atomic_decrement( (int *)sem ); + } while ( *(int *)sem != 0 ); + +} + +#if 0 +/* Not defined anywhere. */ +extern int __lll_sem_timedwait (sem_t *sem, const struct timespec *ts) + attribute_hidden; +#define lll_sem_timedwait(sem, timeout) \ + __lll_sem_timedwait (sem, timeout) +#endif + +static inline void +__attribute__ ((always_inline)) +lll_sem_post (sem_t *sem) +{ + + /* signal release of the semaphore */ + lll_atomic_increment( (int *)sem ); + lll_futex_wake((int *) sem, *(int *)sem); + +} + +#endif /* lowlevelsem.h */ diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_post.c ./sysdeps/unix/sysv/linux/sem_post.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_post.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/sem_post.c 2003-03-10 15:45:14.000000000 +1100 @@ -0,0 +1,51 @@ + + +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevelsem.h> +#include <internaltypes.h> + +#include <shlib-compat.h> + +/* + * increment the semaphore and wake anyone who might be waiting on it + */ + +int +__new_sem_post (sem_t *sem) +{ + int err; + + lll_atomic_increment( (int *)sem ); + err = lll_futex_wake ((int *) sem, *(int *)sem ); + if (err < 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) +strong_alias (__new_sem_post, __old_sem_post) +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c ./sysdeps/unix/sysv/linux/sem_timedwait.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/sem_timedwait.c 2003-03-10 15:42:18.000000000 +1100 @@ -0,0 +1,87 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevelsem.h> +#include <internaltypes.h> + +#include <shlib-compat.h> + +/* like sem_wait, but with a timeout on the wait */ +int +sem_timedwait (sem, abstime) + sem_t *sem; + const struct timespec *abstime; +{ + do + { + while (__builtin_expect ( *(int *)sem == 0, 0)) + { + /* Check for invalid timeout values. */ + if (abstime->tv_nsec >= 1000000000) + { + __set_errno(EINVAL); + return -1; + } + + /* Get the current time. */ + struct timeval tv; + gettimeofday(&tv, NULL); + + /* Compute the relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + rt.tv_sec--; + } + /* Already timed out. */ + if (rt.tv_sec < 0) + { + __set_errno (ETIMEDOUT); + return -1; + } + + /* Do wait. */ + int err = lll_futex_timed_wait ((int *) sem, 0, &rt); + + /* Returned after timing out? */ + if (err == -ETIMEDOUT) + { + __set_errno (ETIMEDOUT); + return -1; + } + + /* Handle EINTR. */ + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + return -1; + } + + + } + lll_atomic_decrement((int *)sem); + } + while ( *(int *)sem != 0 ); + return 0; +} diff -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_trywait.c ./sysdeps/unix/sysv/linux/sem_trywait.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_trywait.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/sem_trywait.c 2003-03-10 15:41:28.000000000 +1100 @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevelsem.h> +#include <internaltypes.h> + +#include <shlib-compat.h> + +/* + * sem_trywait is a non blocking version of sem_wait -- instead of + * blocking until the semaphore becomes > 0, we just return an error. + */ + +int +__new_sem_trywait (sem_t *sem) +{ + do + { + /* we expect to get the lock */ + while (__builtin_expect ( *(int *)sem == 0, 0)) + /* don't wait just return an error */ + { + __set_errno (EAGAIN); + return -1; + } + + lll_atomic_decrement((int *)sem); + } + while ( *(int *)sem != 0 ); + + return 0; +} + + +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 -ruN /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_wait.c ./sysdeps/unix/sysv/linux/sem_wait.c --- /usr/src/ianw/libc-jj/nptl/sysdeps/unix/sysv/linux/sem_wait.c 1970-01-01 10:00:00.000000000 +1000 +++ ./sysdeps/unix/sysv/linux/sem_wait.c 2003-03-10 15:38:47.000000000 +1100 @@ -0,0 +1,61 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <[email protected]>, 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevelsem.h> +#include <internaltypes.h> + +#include <shlib-compat.h> + +/* + * Sem_wait holds the thread until the semaphore value is greater than + * zero. Once it is, it is decremented and we continue. + */ + +int +__new_sem_wait (sem_t *sem) +{ + do + { + /* we expect to get the lock */ + while (__builtin_expect ( *(int *)sem == 0, 0)) + { + /* Do wait. */ + int err = lll_futex_wait ((int *) sem, 0); + + /* Handle EINTR. */ + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + return -1; + } + } + lll_atomic_decrement((int *)sem); + } + while ( *(int *)sem != 0 ); + + return 0; +} + +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_wait, __old_sem_wait) +compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); +#endif