about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-03-24 06:36:06 +0000
committerUlrich Drepper <drepper@redhat.com>2004-03-24 06:36:06 +0000
commit2c0b891afe29dd28d0e6d75e0da8681db7fd100d (patch)
tree06fead8fc58acefbe9a9ebe353f0d596e73522ad /nptl/sysdeps/unix/sysv
parent565699e492f741bc4563c73046f457924c6f708a (diff)
downloadglibc-2c0b891afe29dd28d0e6d75e0da8681db7fd100d.tar.gz
glibc-2c0b891afe29dd28d0e6d75e0da8681db7fd100d.tar.xz
glibc-2c0b891afe29dd28d0e6d75e0da8681db7fd100d.zip
Update.
	* sysdeps/unix/sysv/linux/smp.h: New file.
	* sysdeps/unix/sysv/linux/sh/smp.h: New file.
	* init.c: Define __is_smp.
	(__pthread_initialize_minimal_internal): Call is_smp_system to
	initialize __is_smp.
	* pthreadP.h: Declare __is_smp.
	Define MAX_ADAPTIVE_COUNT is necessary.
	* pthread_mutex_init.c: Add comment regarding __spins field.
	* pthread_mutex_lock.c: Implement adaptive mutex type.
	* pthread_mutex_timedlock.c: Likewise.
	* sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise.
	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t):
	Add __spins field.
	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define
	lll_mutex_cond_trylock.
	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise.
	Define BUSY_WAIT_NOP.
	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise.

	* tst-mutex5.c: Add support for testing adaptive mutexes.
	* tst-mutex7.c: Likewise.
	* tst-mutex5a.c: New file.
	* tst-mutex7a.c: New file.
	* Makefile (tests): Add tst-mutex5a and tst-mutex7a.
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h14
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h17
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h16
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h25
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/smp.h24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/smp.h50
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h25
19 files changed, 210 insertions, 18 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
index 2d8a00b93f..0fed5cc918 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
@@ -1,5 +1,5 @@
 /* Machine-specific pthread type layouts.  Alpha version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 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
@@ -56,6 +56,7 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
index 9d125e0d6d..a7079a8490 100644
--- a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 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
@@ -80,6 +80,14 @@ __lll_mutex_trylock(int *futex)
 #define lll_mutex_trylock(lock)	__lll_mutex_trylock (&(lock))
 
 
+static inline int __attribute__((always_inline))
+__lll_mutex_cond_trylock(int *futex)
+{
+  return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
+}
+#define lll_mutex_cond_trylock(lock)	__lll_mutex_cond_trylock (&(lock))
+
+
 extern void __lll_lock_wait (int *futex) attribute_hidden;
 
 static inline void __attribute__((always_inline))
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
index fc0a54c036..f998138d7e 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 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
@@ -56,6 +56,7 @@ typedef union
        binary compatibility.  */
     int __kind;
     unsigned int __nusers;
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index a9823d8d4b..b86f11c9b4 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -40,6 +40,7 @@
 /* Initializer for compatibility lock.  */
 #define LLL_MUTEX_LOCK_INITIALIZER		(0)
 #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1)
+#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2)
 
 
 #ifdef PIC
@@ -60,6 +61,9 @@
 # define LLL_ENTER_KERNEL	"int $0x80\n\t"
 #endif
 
+/* Delay in spinlock loop.  */
+#define BUSY_WAIT_NOP          asm ("rep; nop")
+
 
 #define lll_futex_wait(futex, val) \
   do {									      \
@@ -117,6 +121,16 @@ extern int __lll_mutex_unlock_wake (int *__futex)
      ret; })
 
 
+#define lll_mutex_cond_trylock(futex) \
+  ({ int ret;								      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS),	      \
+			  "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER)	      \
+		       : "memory");					      \
+     ret; })
+
+
 #define lll_mutex_lock(futex) \
   (void) ({ int ignore1, ignore2;					      \
 	    __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"		      \
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
index 6cd6c05705..e4c15d1e20 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -56,6 +56,7 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
index e462776c02..6ed21fdc14 100644
--- a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -31,6 +31,9 @@
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
 
+/* Delay in spinlock loop.  */
+#define BUSY_WAIT_NOP          asm ("hint @pause")
+
 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
 
@@ -62,6 +65,11 @@
 #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
 
 
+#define __lll_mutex_cond_trylock(futex) \
+  (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0)
+#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
+
+
 extern void __lll_lock_wait (int *futex) attribute_hidden;
 
 
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
index 2d98a80e36..d6d94cda24 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
@@ -1,5 +1,5 @@
 /* Machine-specific pthread type layouts.  PowerPC version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
 
@@ -76,6 +76,7 @@ typedef union
 #if __WORDSIZE != 64
     unsigned int __nusers;
 #endif
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
index a715879dbd..e9f895d6e8 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
 
@@ -100,6 +100,21 @@
 
 #define lll_mutex_trylock(lock)	__lll_trylock (&(lock))
 
+/* Set *futex to 2 if it is 0, atomically.  Returns the old value */
+#define lll_mutex_cond_trylock(futex) \
+  ({ int __val;								      \
+     __asm __volatile ("1:	lwarx	%0,0,%2\n"			      \
+		       "	cmpwi	0,%0,0\n"			      \
+		       "	bne	2f\n"				      \
+		       "	stwcx.	%3,0,%2\n"			      \
+		       "	bne-	1b\n"				      \
+		       "2:	" __lll_acq_instr			      \
+		       : "=&r" (__val), "=m" (*futex)			      \
+		       : "r" (futex), "r" (2), "1" (*futex)		      \
+		       : "cr0", "memory");				      \
+     __val;								      \
+  })
+
 
 extern void __lll_lock_wait (int *futex) attribute_hidden;
 
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c
index d253c72ea4..990db87416 100644
--- a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c
@@ -1,6 +1,7 @@
 #include <pthreadP.h>
 
 #define LLL_MUTEX_LOCK(mutex) lll_mutex_cond_lock(mutex)
+#define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_cond_trylock(mutex)
 #define __pthread_mutex_lock __pthread_mutex_cond_lock
 #define NO_INCR
 
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
index 022ba4982b..e2606aff8e 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
@@ -75,6 +75,7 @@ typedef union
 #if __WORDSIZE != 64
     unsigned int __nusers;
 #endif
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
index 5751206dd9..8b460eb98f 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
@@ -127,6 +127,20 @@ __lll_mutex_trylock (int *futex)
 #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
 
 
+static inline int
+__attribute__ ((always_inline))
+__lll_mutex_cond_trylock (int *futex)
+{
+    unsigned int old;
+
+    __asm __volatile ("cs %0,%3,%1"
+		       : "=d" (old), "=Q" (*futex)
+		       : "0" (0), "d" (2), "m" (*futex) : "cc" );
+    return old != 0;
+}
+#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
+
+
 extern void __lll_lock_wait (int *futex) attribute_hidden;
 
 static inline void
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h
index 3cd84864f4..7d05908778 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -57,6 +57,7 @@ typedef union
        binary compatibility.  */
     int __kind;
     unsigned int __nusers;
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
index 37842263b6..00ff1b20fb 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 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
@@ -31,6 +31,7 @@
 /* Initializer for compatibility lock.  */
 #define LLL_MUTEX_LOCK_INITIALIZER		(0)
 #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1)
+#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2)
 
 extern int __lll_mutex_lock_wait (int val, int *__futex) attribute_hidden;
 extern int __lll_mutex_timedlock_wait (int val, int *__futex,
@@ -61,6 +62,28 @@ extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden;
 	: "r0", "r1", "r2", "t", "memory"); \
      __result; })
 
+#define lll_mutex_cond_trylock(futex) \
+  ({ unsigned char __result; \
+     __asm __volatile ("\
+	.align 2\n\
+	mova 1f,r0\n\
+	nop\n\
+	mov r15,r1\n\
+	mov #-8,r15\n\
+     0: mov.l @%1,r2\n\
+	cmp/eq r2,%3\n\
+	bf 1f\n\
+	mov.l %2,@%1\n\
+     1: mov r1,r15\n\
+	mov #-1,%0\n\
+	negc %0,%0"\
+	: "=r" (__result) \
+	: "r" (&(futex)), \
+	  "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \
+	  "r" (LLL_MUTEX_LOCK_INITIALIZER) \
+	: "r0", "r1", "r2", "t", "memory"); \
+     __result; })
+
 #define lll_mutex_lock(futex) \
   (void) ({ int __result, val, *__futex = &(futex); \
 	    __asm __volatile ("\
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/smp.h b/nptl/sysdeps/unix/sysv/linux/sh/smp.h
new file mode 100644
index 0000000000..2c0cbe99ac
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/sh/smp.h
@@ -0,0 +1,24 @@
+/* Determine whether the host has multiple processors.  SH version.
+   Copyright (C) 2002 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+static inline int
+is_smp_system (void)
+{
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/smp.h b/nptl/sysdeps/unix/sysv/linux/smp.h
new file mode 100644
index 0000000000..718fab683b
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/smp.h
@@ -0,0 +1,50 @@
+/* Determine whether the host has multiple processors.  Linux version.
+   Copyright (C) 1996, 2002, 2004 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/sysctl.h>
+
+/* Test whether the machine has more than one processor.  This is not the
+   best test but good enough.  More complicated tests would require `malloc'
+   which is not available at that time.  */
+static inline int
+is_smp_system (void)
+{
+  static const int sysctl_args[] = { CTL_KERN, KERN_VERSION };
+  char buf[512];
+  size_t reslen = sizeof (buf);
+
+  /* Try reading the number using `sysctl' first.  */
+  if (__sysctl ((int *) sysctl_args,
+		sizeof (sysctl_args) / sizeof (sysctl_args[0]),
+		buf, &reslen, NULL, 0) < 0)
+    {
+      /* This was not successful.  Now try reading the /proc filesystem.  */
+      int fd = __open ("/proc/sys/kernel/version", O_RDONLY);
+      if (__builtin_expect (fd, 0) == -1
+	  || (reslen = __read (fd, buf, sizeof (buf))) <= 0)
+	/* This also didn't work.  We give up and say it's a UP machine.  */
+	buf[0] = '\0';
+
+      __close (fd);
+    }
+
+  return strstr (buf, "SMP") != NULL;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
index b947439e34..d123fd059f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h
@@ -1,5 +1,5 @@
 /* Machine-specific pthread type layouts.  SPARC version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -76,6 +76,7 @@ typedef union
 #if __WORDSIZE != 64
     unsigned int __nusers;
 #endif
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
index 76ec431a6c..05bc5a2974 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
 
@@ -86,6 +86,14 @@ __lll_mutex_trylock (int *futex)
 }
 #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
 
+static inline int
+__attribute__ ((always_inline))
+__lll_mutex_cond_trylock (int *futex)
+{
+  return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
+}
+#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
+
 
 extern void __lll_lock_wait (int *futex) attribute_hidden;
 
@@ -124,7 +132,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
 {
   int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
   int result = 0;
-  
+
   if (__builtin_expect (val != 0, 0))
     result = __lll_timedlock_wait (futex, abstime);
   return result;
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
index 3f151d04ed..1b4820eb0c 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -56,6 +56,7 @@ typedef union
     /* KIND must stay at this position in the structure to maintain
        binary compatibility.  */
     int __kind;
+    int __spins;
   } __data;
   char __size[__SIZEOF_PTHREAD_MUTEX_T];
   long int __align;
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
index 156d1f7c64..ca8d568038 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -40,6 +40,10 @@
 /* Initializer for compatibility lock.  */
 #define LLL_MUTEX_LOCK_INITIALIZER		(0)
 #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1)
+#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2)
+
+/* Delay in spinlock loop.  */
+#define BUSY_WAIT_NOP          asm ("rep; nop")
 
 
 #define lll_futex_wait(futex, val) \
@@ -77,9 +81,14 @@ extern int __lll_mutex_timedlock_wait (int *__futex, int __val,
 extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
 
 
+/* NB: in the lll_mutex_trylock macro we simply return the value in %eax
+   after the cmpxchg instruction.  In case the operation succeded this
+   value is zero.  In case the operation failed, the cmpxchg instruction
+   has loaded the current value of the memory work which is guaranteed
+   to be nonzero.  */
 #define lll_mutex_trylock(futex) \
-  ({ unsigned char ret;							      \
-     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0"		      \
+  ({ int ret;								      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
 		       : "=a" (ret), "=m" (futex)			      \
 		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\
 			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \
@@ -87,6 +96,16 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden;
      ret; })
 
 
+#define lll_mutex_cond_trylock(futex) \
+  ({ int ret;								      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS),	      \
+			 "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER)	      \
+		       : "memory");					      \
+     ret; })
+
+
 #define lll_mutex_lock(futex) \
   (void) ({ int ignore1, ignore2, ignore3;				      \
 	    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \