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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.