This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] NPTL i386 port


Hi!

This patch adds an i386 NPTL port.
Because i386 lacks atomic instructions powerful enough for NPTL needs,
this port is slightly limited, particularly that TSH option cannot be
supported.
Within one process, i386 NPTL uses an array of spinlocks around a few
assembly instructions containing non-atomic code.
Shared libraries use only this spinlock around non-atomic code stuff,
while .a libraries detect during startup whether it is run on i486+
and if so, use lock cmpxchg*, lock xadd* etc., and on real i386
use the spinlock+non-atomic stuff.  One should not install i386 NPTL
shared libraries unless on real < i486 system.

Passed make check in i386 and i686 NPTL build (with one sole failure
on i386, tst-clock2 - _POSIX_CPUTIME should be probably defined to
0 in i[345]86 NPTL and linuxthreads as opposed to i686 which is the
only one with HP_TIMING).

The i486/i586/i686 NPTL ports aside from some file reshuffling ought
to remain untouched (ok, will link in empty {,rt-,ptw-,nscd-}atomic.o*
and will have different line numbers in debug builds.

2004-05-10  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/i386/Makefile (routines): Add atomic in csu.
	($(objpfx)tst-atomic, $(objpfx)tst-atomic-long): Depend on
	$(objpfx)atomic.o.
	(libpthread-routines): Add ptw-atomic.
	(librt-routines): Add rt-atomic.
	(nscd-modules): Add nscd-atomic.
	(CFLAGS-nscd-atomic.S): Add -DSHARED.
	* sysdeps/i386/bits/atomic.h: New file.
	* sysdeps/i386/atomic.S: New file.
	* sysdeps/i386/rt-atomic.S: New file.
	* sysdeps/i386/nscd-atomic.S: New file.
	* sysdeps/i386/i486/bits/atomic.h: New file.
	* sysdeps/i386/i486/atomic.S: New file.
	* sysdeps/i386/i586/bits/atomic.h: New file.
	* sysdeps/i386/i586/atomic.S: New file.
	* sysdeps/i386/i686/bits/atomic.h: New file.
	* sysdeps/i386/i686/atomic.S: New file.
	* sysdeps/i386/tls.h (INIT_CMPXCHG): Define if not yet defined.
	(TLS_INIT_TP): Include INIT_CMPXCHG.
	(THREAD_ATOMIC_CMPXCHG_VAL, THREAD_ATOMIC_BIT_SET): Move to...
	* sysdeps/i386/i486/tls.h: ...this new file.
	* sysdeps/i386/i586/tls.h: New file.
	* sysdeps/i386/i686/tls.h: Include ../i486/tls.h instead of
	../tls.h.
	* sysdeps/i386/pthread_spin_trylock.c: New file.
	* sysdeps/i386/pthread_spin_lock.c: New file.  Old content moved to
	...
	* sysdeps/i386/i486/pthread_spin_lock.c: ... here.  New file.
	* sysdeps/i386/i586/pthread_spin_lock.c: New file.
	* sysdeps/i386/i686/pthread_spin_lock.c: New file.
	* sysdeps/unix/sysv/linux/i386/sysconf.c: New file.
	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: New file.  Old
	content moved to ...
	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.h: ... here.
	New file.
	* sysdeps/unix/sysv/linux/i386/i586/lowlevellock.h: New file.
	* sysdeps/unix/sysv/linux/i386/i686/lowlevellock.h: New file.
	* sysdeps/unix/sysv/linux/i386/pthread_once.c: New file.
	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Moved to...
	* sysdeps/unix/sysv/linux/i386/i486/pthread_once.S: ... here.
	* sysdeps/unix/sysv/linux/i386/i586/pthread_once.S: New file.
	* sysdeps/unix/sysv/linux/i386/i686/pthread_once.S: New file.
	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h
	(_POSIX_THREAD_PROCESS_SHARED): Define to 0.
	* sysdeps/unix/sysv/linux/i386/i686/bits/posix_opt.h: New file.
	* sysdeps/unix/sysv/linux/i386/i586/bits/posix_opt.h: New file.
	* sysdeps/unix/sysv/linux/i386/i486/bits/posix_opt.h: New file.
	* pthread_mutexattr_setpshared.c: Include unistd.h.
	(pthread_mutexattr_setpshared): Return ENOSYS if TSH not supported
	and pshared == PTHREAD_PROCESS_SHARED.
	* pthread_barrierattr_setpshared.c: Include unistd.h.
	(pthread_barrierattr_setpshared): Return ENOSYS if TSH not supported
	and pshared == PTHREAD_PROCESS_SHARED.
	* pthread_condattr_setpshared.c: Include unistd.h.
	(pthread_condattr_setpshared): Return ENOSYS if TSH not supported
	and pshared == PTHREAD_PROCESS_SHARED.
	* pthread_rwlockattr_setpshared.c: Include unistd.h.
	(pthread_rwlockattr_setpshared): Return ENOSYS if TSH not supported
	and pshared == PTHREAD_PROCESS_SHARED.
	* sem_init.c: Include unistd.h.
	(__new_sem_init): Return -1/ENOSYS if TSH not supported and pshared
	non-zero.
	* tst-signal2.c (do_test): Exit with 0 status if
	_POSIX_THREAD_PROCESS_SHARED not supported.
	* tst-cancel16.c (do_test): Likewise.
	* tst-cond12.c (do_test): Likewise.

--- libc/nptl/pthread_mutexattr_setpshared.c.jj	2002-11-26 23:49:22.000000000 +0100
+++ libc/nptl/pthread_mutexattr_setpshared.c	2004-05-10 10:35:26.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <pthreadP.h>
+#include <unistd.h>
 
 
 int
@@ -32,6 +33,12 @@ pthread_mutexattr_setpshared (attr, psha
       && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0))
     return EINVAL;
 
+#if !_POSIX_THREAD_PROCESS_SHARED
+  if (__builtin_expect (pshared == PTHREAD_PROCESS_SHARED, 0)
+      && sysconf (_SC_THREAD_PROCESS_SHARED) == -1)
+    return ENOSYS;
+#endif
+
   iattr = (struct pthread_mutexattr *) attr;
 
   /* We use bit 31 to single whether the mutex is going to be
--- libc/nptl/pthread_barrierattr_setpshared.c.jj	2002-11-26 23:49:51.000000000 +0100
+++ libc/nptl/pthread_barrierattr_setpshared.c	2004-05-10 10:36:29.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include "pthreadP.h"
+#include <unistd.h>
 
 
 int
@@ -32,6 +33,12 @@ pthread_barrierattr_setpshared (attr, ps
       && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0))
     return EINVAL;
 
+#if !_POSIX_THREAD_PROCESS_SHARED
+  if (__builtin_expect (pshared == PTHREAD_PROCESS_SHARED, 0)
+      && sysconf (_SC_THREAD_PROCESS_SHARED) == -1)
+    return ENOSYS;
+#endif
+
   iattr = (struct pthread_barrierattr *) attr;
 
   iattr->pshared = pshared;
--- libc/nptl/sysdeps/unix/sysv/linux/i386/sysconf.c.jj	2004-05-10 10:23:22.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/sysconf.c	2004-05-10 10:32:50.000000000 +0200
@@ -0,0 +1,57 @@
+/* Get file-specific information about a file.  Linux/i386 NPTL version.
+   Copyright (C) 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 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 <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#if !_POSIX_THREAD_PROCESS_SHARED
+
+static long int linux_i386_sysconf (int name);
+
+
+/* Get the value of the system variable NAME.  */
+long int
+__sysconf (int name)
+{
+  if (name == _SC_THREAD_PROCESS_SHARED)
+    {
+      /* The i386 glibc never uses compare and exchange instructions
+	 for shared libraries (on i486+ i386 NPTL shared libraries should
+	 be never used) and in libpthread.a only if running on i486+
+	 CPU.  */
+# ifdef SHARED
+      return -1;
+# else
+      extern int __atomic_has_cmpxchg attribute_hidden;
+      return __atomic_has_cmpxchg ? 1 : -1;
+# endif
+    }
+
+  return linux_i386_sysconf (name);
+}
+
+/* Now the generic i386 Linux version.  */
+# undef __sysconf
+# define __sysconf static linux_i386_sysconf
+
+#endif
+
+#include <sysdeps/unix/sysv/linux/i386/sysconf.c>
--- libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h.jj	2004-03-24 12:16:59.000000000 +0100
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h	2004-05-09 20:25:47.000000000 +0200
@@ -1,6 +1,6 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 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
@@ -9,11 +9,11 @@
 
    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
+   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
+   License along with the GNU C Libr	\ary; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
@@ -23,343 +23,192 @@
 #include <time.h>
 #include <sys/param.h>
 #include <bits/pthreadtypes.h>
+#include <atomic.h>
 
-#ifndef LOCK_INSTR
-# ifdef UP
-#  define LOCK_INSTR	/* nothing */
-# else
-#  define LOCK_INSTR "lock;"
-# endif
-#endif
 
-#define SYS_futex		240
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
+#define FUTEX_REQUEUE		3
 
+/* Initializer for compatibility lock.	*/
+#define LLL_MUTEX_LOCK_INITIALIZER (0)
 
-/* 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
-# define LLL_EBX_LOAD	"xchgl %2, %%ebx\n"
-# define LLL_EBX_REG	"D"
-#else
-# define LLL_EBX_LOAD
-# define LLL_EBX_REG	"b"
-#endif
-
-#ifdef I386_USE_SYSENTER
-# ifdef SHARED
-#  define LLL_ENTER_KERNEL	"call *%%gs:%P6\n\t"
-# else
-#  define LLL_ENTER_KERNEL	"call *_dl_sysinfo\n\t"
-# endif
-#else
-# 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 {									      \
-    int __ignore;							      \
-    register __typeof (val) _val asm ("edx") = (val);			      \
-    __asm __volatile (LLL_EBX_LOAD					      \
-		      LLL_ENTER_KERNEL					      \
-		      LLL_EBX_LOAD					      \
-		      : "=a" (__ignore)					      \
-		      : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0),	      \
-			"c" (FUTEX_WAIT), "d" (_val),			      \
-			"i" (offsetof (tcbhead_t, sysinfo)));		      \
-  } while (0)
-
-
-#define lll_futex_wake(futex, nr) \
-  do {									      \
-    int __ignore;							      \
-    register __typeof (nr) _nr asm ("edx") = (nr);			      \
-    __asm __volatile (LLL_EBX_LOAD					      \
-		      LLL_ENTER_KERNEL					      \
-		      LLL_EBX_LOAD					      \
-		      : "=a" (__ignore)					      \
-		      : "0" (SYS_futex), LLL_EBX_REG (futex),		      \
-			"c" (FUTEX_WAKE), "d" (_nr),			      \
-			"i" (0) /* phony, to align next arg's number */,      \
-			"i" (offsetof (tcbhead_t, sysinfo)));		      \
-  } while (0)
-
-
-/* Does not preserve %eax and %ecx.  */
-extern int __lll_mutex_lock_wait (int val, int *__futex)
-     __attribute ((regparm (2))) attribute_hidden;
-/* Does not preserve %eax, %ecx, and %edx.  */
-extern int __lll_mutex_timedlock_wait (int val, int *__futex,
-				       const struct timespec *abstime)
-     __attribute ((regparm (3))) attribute_hidden;
-/* Preserves all registers but %eax.  */
-extern int __lll_mutex_unlock_wake (int *__futex)
-     __attribute ((regparm (1))) 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) \
-  ({ 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)		      \
-		       : "memory");					      \
-     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"		      \
-			      "jnz _L_mutex_lock_%=\n\t"		      \
-			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_lock_%=,@function\n"	      \
-			      "_L_mutex_lock_%=:\n\t"			      \
-			      "leal %2, %%ecx\n\t"			      \
-			      "call __lll_mutex_lock_wait\n\t"		      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \
-			      ".previous\n"				      \
-			      "1:"					      \
-			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
-			      : "0" (0), "1" (1), "m" (futex)		      \
-			      : "memory"); })
-
-
-/* Special version of lll_mutex_lock which causes the unlock function to
-   always wakeup waiters.  */
-#define lll_mutex_cond_lock(futex) \
-  (void) ({ int ignore1, ignore2;					      \
-	    __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"		      \
-			      "jnz _L_mutex_cond_lock_%=\n\t"		      \
-			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_cond_lock_%=,@function\n"	      \
-			      "_L_mutex_cond_lock_%=:\n\t"		      \
-			      "leal %2, %%ecx\n\t"			      \
-			      "call __lll_mutex_lock_wait\n\t"		      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"   \
-			      ".previous\n"				      \
-			      "1:"					      \
-			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
-			      : "0" (0), "1" (2), "m" (futex)		      \
-			      : "memory"); })
-
-
-#define lll_mutex_timedlock(futex, timeout) \
-  ({ int result, ignore1, ignore2;					      \
-     __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"			      \
-		       "jnz _L_mutex_timedlock_%=\n\t"			      \
-		       ".subsection 1\n\t"				      \
-		       ".type _L_mutex_timedlock_%=,@function\n"	      \
-		       "_L_mutex_timedlock_%=:\n\t"			      \
-		       "leal %3, %%ecx\n\t"				      \
-		       "movl %7, %%edx\n\t"				      \
-		       "call __lll_mutex_timedlock_wait\n\t"		      \
-		       "jmp 1f\n\t"					      \
-		       ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\
-		       ".previous\n"					      \
-		       "1:"						      \
-		       : "=a" (result), "=c" (ignore1), "=&d" (ignore2),      \
-			 "=m" (futex)					      \
-		       : "0" (0), "1" (1), "m" (futex), "m" (timeout)	      \
-		       : "memory");					      \
-     result; })
-
-
-#define lll_mutex_unlock(futex) \
-  (void) ({ int ignore;							      \
-            __asm __volatile (LOCK_INSTR "subl $1,%0\n\t"		      \
-			      "jne _L_mutex_unlock_%=\n\t"		      \
-			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_unlock_%=,@function\n"	      \
-			      "_L_mutex_unlock_%=:\n\t"			      \
-			      "leal %0, %%eax\n\t"			      \
-			      "call __lll_mutex_unlock_wake\n\t"	      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
-			      ".previous\n"				      \
-			      "1:"					      \
-			      : "=m" (futex), "=&a" (ignore)		      \
-			      : "m" (futex)				      \
-			      : "memory"); })
+#define lll_futex_wait(futexp, val) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \
+			      (futexp), FUTEX_WAIT, (val), 0);		      \
+    __ret;								      \
+  })
+
+#define lll_futex_timed_wait(futexp, val, timespec) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \
+			      (futexp), FUTEX_WAIT, (val), (timespec));	      \
+    __ret;								      \
+  })
+
+#define lll_futex_wake(futexp, nr) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \
+			      (futexp), FUTEX_WAKE, (nr), 0);		      \
+    __ret;								      \
+  })
 
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+									      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 5,				      \
+			      (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move),  \
+			      (mutex));					      \
+    __ret;								      \
+  })
+
+static inline int
+__attribute__ ((always_inline))
+__lll_mutex_trylock (int *futex)
+{
+  return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0;
+}
+#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;
+
+
+static inline void
+__attribute__ ((always_inline))
+__lll_mutex_lock (int *futex)
+{
+  int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
+
+  if (__builtin_expect (val != 0, 0))
+    __lll_lock_wait (futex);
+}
+#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
+
+
+static inline void
+__attribute__ ((always_inline))
+__lll_mutex_cond_lock (int *futex)
+{
+  int val = atomic_compare_and_exchange_val_acq (futex, 2, 0);
+
+  if (__builtin_expect (val != 0, 0))
+    __lll_lock_wait (futex);
+}
+#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *)
+     attribute_hidden;
+
+
+static inline int
+__attribute__ ((always_inline))
+__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;
+}
+#define lll_mutex_timedlock(futex, abstime) \
+  __lll_mutex_timedlock (&(futex), abstime)
+
+#define lll_mutex_unlock(lock) \
+  ((void) ({								      \
+    int *__futex = &(lock);						      \
+    int __val = atomic_exchange_rel (__futex, 0);			      \
+    if (__builtin_expect (__val > 1, 0))				      \
+      lll_futex_wake (__futex, 1);					      \
+  }))
+
+#define lll_mutex_unlock_force(lock) \
+  ((void) ({								      \
+    int *__futex = &(lock);						      \
+    (void) atomic_exchange_rel (__futex, 0);				      \
+    lll_futex_wake (__futex, 1);					      \
+  }))
 
 #define lll_mutex_islocked(futex) \
   (futex != 0)
 
 
 /* We have a separate internal lock implementation which is not tied
-   to binary compatibility.  */
+   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)
 
-
-extern int __lll_lock_wait (int val, int *__futex)
-     __attribute ((regparm (2))) attribute_hidden;
-extern int __lll_unlock_wake (int *__futex)
-     __attribute ((regparm (1))) attribute_hidden;
-extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
-
-
-/* The states of a lock are:
-    0  -  untaken
-    1  -  taken by one user
-    2  -  taken by more users */
-
-
-#if defined NOT_IN_libc || defined UP
-# define lll_trylock(futex) lll_mutex_trylock (futex)
-# define lll_lock(futex) lll_mutex_lock (futex)
-# define lll_unlock(futex) lll_mutex_unlock (futex)
-#else
-/* Special versions of the macros for use in libc itself.  They avoid
-   the lock prefix when the thread library is not used.
-
-   XXX In future we might even want to avoid it on UP machines.  */
-# include <tls.h>
-
-# define lll_trylock(futex) \
-  ({ unsigned char ret;							      \
-     __asm __volatile ("cmpl $0, %%gs:%P5\n\t"				      \
-		       "je,pt 0f\n\t"					      \
-		       "lock\n"						      \
-		       "0:\tcmpxchgl %2, %1; setne %0"			      \
-		       : "=a" (ret), "=m" (futex)			      \
-		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\
-			 "0" (LLL_MUTEX_LOCK_INITIALIZER),		      \
-		         "i" (offsetof (tcbhead_t, multiple_threads))	      \
-		       : "memory");					      \
-     ret; })
-
-
-# define lll_lock(futex) \
-  (void) ({ int ignore1, ignore2;					      \
-	    __asm __volatile ("cmpl $0, %%gs:%P6\n\t"			      \
-			      "je,pt 0f\n\t"				      \
-			      "lock\n"					      \
-			      "0:\tcmpxchgl %1, %2\n\t"			      \
-			      "jnz _L_mutex_lock_%=\n\t"		      \
-			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_lock_%=,@function\n"	      \
-			      "_L_mutex_lock_%=:\n\t"			      \
-			      "leal %2, %%ecx\n\t"			      \
-			      "call __lll_mutex_lock_wait\n\t"		      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \
-			      ".previous\n"				      \
-			      "1:"					      \
-			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
-			      : "0" (0), "1" (1), "m" (futex),		      \
-		                "i" (offsetof (tcbhead_t, multiple_threads))  \
-			      : "memory"); })
-
-
-# define lll_unlock(futex) \
-  (void) ({ int ignore;							      \
-            __asm __volatile ("cmpl $0, %%gs:%P3\n\t"			      \
-			      "je,pt 0f\n\t"				      \
-			      "lock\n"					      \
-			      "0:\tsubl $1,%0\n\t"		      \
-			      "jne _L_mutex_unlock_%=\n\t"		      \
-			      ".subsection 1\n\t"			      \
-			      ".type _L_mutex_unlock_%=,@function\n"	      \
-			      "_L_mutex_unlock_%=:\n\t"			      \
-			      "leal %0, %%eax\n\t"			      \
-			      "call __lll_mutex_unlock_wake\n\t"	      \
-			      "jmp 1f\n\t"				      \
-			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
-			      ".previous\n"				      \
-			      "1:"					      \
-			      : "=m" (futex), "=&a" (ignore)		      \
-			      : "m" (futex),				      \
-				"i" (offsetof (tcbhead_t, multiple_threads))  \
-			      : "memory"); })
-#endif
-
-
-#define lll_islocked(futex) \
-  (futex != LLL_LOCK_INITIALIZER)
+#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.
-
-   The macro parameter must not have any side effect.  */
+   afterwards.	*/
 #define lll_wait_tid(tid) \
-  do {									      \
-    int __ignore;							      \
-    register __typeof (tid) _tid asm ("edx") = (tid);			      \
-    if (_tid != 0)							      \
-      __asm __volatile (LLL_EBX_LOAD					      \
-			"1:\tmovl %1, %%eax\n\t"			      \
-			LLL_ENTER_KERNEL				      \
-			"cmpl $0, (%%ebx)\n\t"				      \
-			"jne,pn 1b\n\t"					      \
-			LLL_EBX_LOAD					      \
-			: "=&a" (__ignore)				      \
-			: "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),	      \
-			  "c" (FUTEX_WAIT), "d" (_tid),			      \
-			  "i" (offsetof (tcbhead_t, sysinfo)));		      \
-  } while (0)
+  do						\
+    {						\
+      __typeof (tid) __tid;			\
+      while ((__tid = (tid)) != 0)		\
+	lll_futex_wait (&(tid), __tid);		\
+    }						\
+  while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+     attribute_hidden;
 
-extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
-     __attribute__ ((regparm (2))) attribute_hidden;
 #define lll_timedwait_tid(tid, abstime) \
-  ({									      \
-    int __result = 0;							      \
-    if (tid != 0)							      \
-      {									      \
-	if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)	      \
-	  __result = EINVAL;						      \
-	else								      \
-	  __result = __lll_timedwait_tid (&tid, abstime);		      \
-      }									      \
-    __result; })
+  ({							\
+    int __res = 0;					\
+    if ((tid) != 0)					\
+      __res = __lll_timedwait_tid (&(tid), (abstime));	\
+    __res;						\
+  })
 
 
 /* Conditional variable handling.  */
 
 extern void __lll_cond_wait (pthread_cond_t *cond)
-     __attribute ((regparm (1))) attribute_hidden;
+     attribute_hidden;
 extern int __lll_cond_timedwait (pthread_cond_t *cond,
 				 const struct timespec *abstime)
-     __attribute ((regparm (2))) attribute_hidden;
+     attribute_hidden;
 extern void __lll_cond_wake (pthread_cond_t *cond)
-     __attribute ((regparm (1))) attribute_hidden;
+     attribute_hidden;
 extern void __lll_cond_broadcast (pthread_cond_t *cond)
-     __attribute ((regparm (1))) attribute_hidden;
-
+     attribute_hidden;
 
 #define lll_cond_wait(cond) \
   __lll_cond_wait (cond)
@@ -370,5 +219,4 @@ extern void __lll_cond_broadcast (pthrea
 #define lll_cond_broadcast(cond) \
   __lll_cond_broadcast (cond)
 
-
 #endif	/* lowlevellock.h */
--- libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.c.jj	2004-05-09 20:29:17.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.c	2004-05-09 20:29:12.000000000 +0200
@@ -0,0 +1 @@
+#include "../sparc/pthread_once.c"
--- libc/nptl/sysdeps/unix/sysv/linux/i386/bits/posix_opt.h.jj	2004-04-13 10:42:53.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/bits/posix_opt.h	2004-05-10 10:20:18.000000000 +0200
@@ -135,8 +135,9 @@
 /* POSIX message queues are available.  */
 #define	_POSIX_MESSAGE_PASSING	200112L
 
-/* Thread process-shared synchronization is supported.  */
-#define _POSIX_THREAD_PROCESS_SHARED	200112L
+/* Thread process-shared synchronization is supported
+   in libpthread.a only and only if the CPU is i486+.  */
+#define _POSIX_THREAD_PROCESS_SHARED	0
 
 /* The monotonic clock might be available.  */
 #define _POSIX_MONOTONIC_CLOCK	0
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.h.jj	2004-05-09 20:21:22.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.h	2004-05-09 20:21:18.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/lowlevellock.h"
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i686/bits/posix_opt.h.jj	2004-05-10 10:19:24.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i686/bits/posix_opt.h	2004-04-13 10:42:53.000000000 +0200
@@ -0,0 +1,147 @@
+/* Define POSIX options for Linux.
+   Copyright (C) 1996-2001, 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
+   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.  */
+
+#ifndef	_POSIX_OPT_H
+#define	_POSIX_OPT_H	1
+
+/* Job control is supported.  */
+#define	_POSIX_JOB_CONTROL	1
+
+/* Processes have a saved set-user-ID and a saved set-group-ID.  */
+#define	_POSIX_SAVED_IDS	1
+
+/* Priority scheduling is supported.  */
+#define	_POSIX_PRIORITY_SCHEDULING	200112L
+
+/* Synchronizing file data is supported.  */
+#define	_POSIX_SYNCHRONIZED_IO	200112L
+
+/* The fsync function is present.  */
+#define	_POSIX_FSYNC	200112L
+
+/* Mapping of files to memory is supported.  */
+#define	_POSIX_MAPPED_FILES	200112L
+
+/* Locking of all memory is supported.  */
+#define	_POSIX_MEMLOCK	200112L
+
+/* Locking of ranges of memory is supported.  */
+#define	_POSIX_MEMLOCK_RANGE	200112L
+
+/* Setting of memory protections is supported.  */
+#define	_POSIX_MEMORY_PROTECTION	200112L
+
+/* Only root can change owner of file.  */
+#define	_POSIX_CHOWN_RESTRICTED	1
+
+/* `c_cc' member of 'struct termios' structure can be disabled by
+   using the value _POSIX_VDISABLE.  */
+#define	_POSIX_VDISABLE	'\0'
+
+/* Filenames are not silently truncated.  */
+#define	_POSIX_NO_TRUNC	1
+
+/* X/Open realtime support is available.  */
+#define _XOPEN_REALTIME	1
+
+/* XPG4.2 shared memory is supported.  */
+#define	_XOPEN_SHM	1
+
+/* Tell we have POSIX threads.  */
+#define _POSIX_THREADS	200112L
+
+/* We have the reentrant functions described in POSIX.  */
+#define _POSIX_REENTRANT_FUNCTIONS      1
+#define _POSIX_THREAD_SAFE_FUNCTIONS	200112L
+
+/* We provide priority scheduling for threads.  */
+#define _POSIX_THREAD_PRIORITY_SCHEDULING	200112L
+
+/* We support user-defined stack sizes.  */
+#define _POSIX_THREAD_ATTR_STACKSIZE	200112L
+
+/* We support user-defined stacks.  */
+#define _POSIX_THREAD_ATTR_STACKADDR	200112L
+
+/* We support POSIX.1b semaphores.  */
+#define _POSIX_SEMAPHORES	200112L
+
+/* Real-time signals are supported.  */
+#define _POSIX_REALTIME_SIGNALS	200112L
+
+/* We support asynchronous I/O.  */
+#define _POSIX_ASYNCHRONOUS_IO	200112L
+#define _POSIX_ASYNC_IO		1
+/* Alternative name for Unix98.  */
+#define _LFS_ASYNCHRONOUS_IO	1
+
+/* The LFS support in asynchronous I/O is also available.  */
+#define _LFS64_ASYNCHRONOUS_IO	1
+
+/* The rest of the LFS is also available.  */
+#define _LFS_LARGEFILE		1
+#define _LFS64_LARGEFILE	1
+#define _LFS64_STDIO		1
+
+/* POSIX shared memory objects are implemented.  */
+#define _POSIX_SHARED_MEMORY_OBJECTS	200112L
+
+/* CPU-time clocks supported.  */
+#define _POSIX_CPUTIME 200112L
+
+/* We support the clock also in threads.  */
+#define _POSIX_THREAD_CPUTIME  200112L
+
+/* GNU libc provides regular expression handling.  */
+#define _POSIX_REGEXP	1
+
+/* Reader/Writer locks are available.  */
+#define _POSIX_READER_WRITER_LOCKS	200112L
+
+/* We have a POSIX shell.  */
+#define _POSIX_SHELL	1
+
+/* We support the Timeouts option.  */
+#define _POSIX_TIMEOUTS	200112L
+
+/* We support spinlocks.  */
+#define _POSIX_SPIN_LOCKS	200112L
+
+/* The `spawn' function family is supported.  */
+#define _POSIX_SPAWN	200112L
+
+/* We have POSIX timers.  */
+#define _POSIX_TIMERS	200112L
+
+/* The barrier functions are available.  */
+#define _POSIX_BARRIERS	200112L
+
+/* POSIX message queues are available.  */
+#define	_POSIX_MESSAGE_PASSING	200112L
+
+/* Thread process-shared synchronization is supported.  */
+#define _POSIX_THREAD_PROCESS_SHARED	200112L
+
+/* The monotonic clock might be available.  */
+#define _POSIX_MONOTONIC_CLOCK	0
+
+/* The clock selection interfaces are available.  */
+#define _POSIX_CLOCK_SELECTION	200112L
+
+#endif /* posix_opt.h */
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_once.S.jj	2004-05-09 20:28:21.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_once.S	2004-05-09 20:28:16.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/pthread_once.S"
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.h.jj	2004-05-09 20:21:22.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.h	2004-05-09 20:21:18.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/lowlevellock.h"
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i586/bits/posix_opt.h.jj	2004-05-10 10:19:24.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i586/bits/posix_opt.h	2004-04-13 10:42:53.000000000 +0200
@@ -0,0 +1,147 @@
+/* Define POSIX options for Linux.
+   Copyright (C) 1996-2001, 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
+   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.  */
+
+#ifndef	_POSIX_OPT_H
+#define	_POSIX_OPT_H	1
+
+/* Job control is supported.  */
+#define	_POSIX_JOB_CONTROL	1
+
+/* Processes have a saved set-user-ID and a saved set-group-ID.  */
+#define	_POSIX_SAVED_IDS	1
+
+/* Priority scheduling is supported.  */
+#define	_POSIX_PRIORITY_SCHEDULING	200112L
+
+/* Synchronizing file data is supported.  */
+#define	_POSIX_SYNCHRONIZED_IO	200112L
+
+/* The fsync function is present.  */
+#define	_POSIX_FSYNC	200112L
+
+/* Mapping of files to memory is supported.  */
+#define	_POSIX_MAPPED_FILES	200112L
+
+/* Locking of all memory is supported.  */
+#define	_POSIX_MEMLOCK	200112L
+
+/* Locking of ranges of memory is supported.  */
+#define	_POSIX_MEMLOCK_RANGE	200112L
+
+/* Setting of memory protections is supported.  */
+#define	_POSIX_MEMORY_PROTECTION	200112L
+
+/* Only root can change owner of file.  */
+#define	_POSIX_CHOWN_RESTRICTED	1
+
+/* `c_cc' member of 'struct termios' structure can be disabled by
+   using the value _POSIX_VDISABLE.  */
+#define	_POSIX_VDISABLE	'\0'
+
+/* Filenames are not silently truncated.  */
+#define	_POSIX_NO_TRUNC	1
+
+/* X/Open realtime support is available.  */
+#define _XOPEN_REALTIME	1
+
+/* XPG4.2 shared memory is supported.  */
+#define	_XOPEN_SHM	1
+
+/* Tell we have POSIX threads.  */
+#define _POSIX_THREADS	200112L
+
+/* We have the reentrant functions described in POSIX.  */
+#define _POSIX_REENTRANT_FUNCTIONS      1
+#define _POSIX_THREAD_SAFE_FUNCTIONS	200112L
+
+/* We provide priority scheduling for threads.  */
+#define _POSIX_THREAD_PRIORITY_SCHEDULING	200112L
+
+/* We support user-defined stack sizes.  */
+#define _POSIX_THREAD_ATTR_STACKSIZE	200112L
+
+/* We support user-defined stacks.  */
+#define _POSIX_THREAD_ATTR_STACKADDR	200112L
+
+/* We support POSIX.1b semaphores.  */
+#define _POSIX_SEMAPHORES	200112L
+
+/* Real-time signals are supported.  */
+#define _POSIX_REALTIME_SIGNALS	200112L
+
+/* We support asynchronous I/O.  */
+#define _POSIX_ASYNCHRONOUS_IO	200112L
+#define _POSIX_ASYNC_IO		1
+/* Alternative name for Unix98.  */
+#define _LFS_ASYNCHRONOUS_IO	1
+
+/* The LFS support in asynchronous I/O is also available.  */
+#define _LFS64_ASYNCHRONOUS_IO	1
+
+/* The rest of the LFS is also available.  */
+#define _LFS_LARGEFILE		1
+#define _LFS64_LARGEFILE	1
+#define _LFS64_STDIO		1
+
+/* POSIX shared memory objects are implemented.  */
+#define _POSIX_SHARED_MEMORY_OBJECTS	200112L
+
+/* CPU-time clocks supported.  */
+#define _POSIX_CPUTIME 200112L
+
+/* We support the clock also in threads.  */
+#define _POSIX_THREAD_CPUTIME  200112L
+
+/* GNU libc provides regular expression handling.  */
+#define _POSIX_REGEXP	1
+
+/* Reader/Writer locks are available.  */
+#define _POSIX_READER_WRITER_LOCKS	200112L
+
+/* We have a POSIX shell.  */
+#define _POSIX_SHELL	1
+
+/* We support the Timeouts option.  */
+#define _POSIX_TIMEOUTS	200112L
+
+/* We support spinlocks.  */
+#define _POSIX_SPIN_LOCKS	200112L
+
+/* The `spawn' function family is supported.  */
+#define _POSIX_SPAWN	200112L
+
+/* We have POSIX timers.  */
+#define _POSIX_TIMERS	200112L
+
+/* The barrier functions are available.  */
+#define _POSIX_BARRIERS	200112L
+
+/* POSIX message queues are available.  */
+#define	_POSIX_MESSAGE_PASSING	200112L
+
+/* Thread process-shared synchronization is supported.  */
+#define _POSIX_THREAD_PROCESS_SHARED	200112L
+
+/* The monotonic clock might be available.  */
+#define _POSIX_MONOTONIC_CLOCK	0
+
+/* The clock selection interfaces are available.  */
+#define _POSIX_CLOCK_SELECTION	200112L
+
+#endif /* posix_opt.h */
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_once.S.jj	2004-05-09 20:28:21.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_once.S	2004-05-09 20:28:16.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/pthread_once.S"
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.h.jj	2004-05-09 20:20:59.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.h	2004-03-24 12:16:59.000000000 +0100
@@ -0,0 +1,374 @@
+/* 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.
+
+   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>
+
+#ifndef LOCK_INSTR
+# ifdef UP
+#  define LOCK_INSTR	/* nothing */
+# else
+#  define LOCK_INSTR "lock;"
+# endif
+#endif
+
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+
+/* 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
+# define LLL_EBX_LOAD	"xchgl %2, %%ebx\n"
+# define LLL_EBX_REG	"D"
+#else
+# define LLL_EBX_LOAD
+# define LLL_EBX_REG	"b"
+#endif
+
+#ifdef I386_USE_SYSENTER
+# ifdef SHARED
+#  define LLL_ENTER_KERNEL	"call *%%gs:%P6\n\t"
+# else
+#  define LLL_ENTER_KERNEL	"call *_dl_sysinfo\n\t"
+# endif
+#else
+# 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 {									      \
+    int __ignore;							      \
+    register __typeof (val) _val asm ("edx") = (val);			      \
+    __asm __volatile (LLL_EBX_LOAD					      \
+		      LLL_ENTER_KERNEL					      \
+		      LLL_EBX_LOAD					      \
+		      : "=a" (__ignore)					      \
+		      : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0),	      \
+			"c" (FUTEX_WAIT), "d" (_val),			      \
+			"i" (offsetof (tcbhead_t, sysinfo)));		      \
+  } while (0)
+
+
+#define lll_futex_wake(futex, nr) \
+  do {									      \
+    int __ignore;							      \
+    register __typeof (nr) _nr asm ("edx") = (nr);			      \
+    __asm __volatile (LLL_EBX_LOAD					      \
+		      LLL_ENTER_KERNEL					      \
+		      LLL_EBX_LOAD					      \
+		      : "=a" (__ignore)					      \
+		      : "0" (SYS_futex), LLL_EBX_REG (futex),		      \
+			"c" (FUTEX_WAKE), "d" (_nr),			      \
+			"i" (0) /* phony, to align next arg's number */,      \
+			"i" (offsetof (tcbhead_t, sysinfo)));		      \
+  } while (0)
+
+
+/* Does not preserve %eax and %ecx.  */
+extern int __lll_mutex_lock_wait (int val, int *__futex)
+     __attribute ((regparm (2))) attribute_hidden;
+/* Does not preserve %eax, %ecx, and %edx.  */
+extern int __lll_mutex_timedlock_wait (int val, int *__futex,
+				       const struct timespec *abstime)
+     __attribute ((regparm (3))) attribute_hidden;
+/* Preserves all registers but %eax.  */
+extern int __lll_mutex_unlock_wake (int *__futex)
+     __attribute ((regparm (1))) 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) \
+  ({ 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)		      \
+		       : "memory");					      \
+     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"		      \
+			      "jnz _L_mutex_lock_%=\n\t"		      \
+			      ".subsection 1\n\t"			      \
+			      ".type _L_mutex_lock_%=,@function\n"	      \
+			      "_L_mutex_lock_%=:\n\t"			      \
+			      "leal %2, %%ecx\n\t"			      \
+			      "call __lll_mutex_lock_wait\n\t"		      \
+			      "jmp 1f\n\t"				      \
+			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \
+			      ".previous\n"				      \
+			      "1:"					      \
+			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
+			      : "0" (0), "1" (1), "m" (futex)		      \
+			      : "memory"); })
+
+
+/* Special version of lll_mutex_lock which causes the unlock function to
+   always wakeup waiters.  */
+#define lll_mutex_cond_lock(futex) \
+  (void) ({ int ignore1, ignore2;					      \
+	    __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"		      \
+			      "jnz _L_mutex_cond_lock_%=\n\t"		      \
+			      ".subsection 1\n\t"			      \
+			      ".type _L_mutex_cond_lock_%=,@function\n"	      \
+			      "_L_mutex_cond_lock_%=:\n\t"		      \
+			      "leal %2, %%ecx\n\t"			      \
+			      "call __lll_mutex_lock_wait\n\t"		      \
+			      "jmp 1f\n\t"				      \
+			      ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"   \
+			      ".previous\n"				      \
+			      "1:"					      \
+			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
+			      : "0" (0), "1" (2), "m" (futex)		      \
+			      : "memory"); })
+
+
+#define lll_mutex_timedlock(futex, timeout) \
+  ({ int result, ignore1, ignore2;					      \
+     __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"			      \
+		       "jnz _L_mutex_timedlock_%=\n\t"			      \
+		       ".subsection 1\n\t"				      \
+		       ".type _L_mutex_timedlock_%=,@function\n"	      \
+		       "_L_mutex_timedlock_%=:\n\t"			      \
+		       "leal %3, %%ecx\n\t"				      \
+		       "movl %7, %%edx\n\t"				      \
+		       "call __lll_mutex_timedlock_wait\n\t"		      \
+		       "jmp 1f\n\t"					      \
+		       ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\
+		       ".previous\n"					      \
+		       "1:"						      \
+		       : "=a" (result), "=c" (ignore1), "=&d" (ignore2),      \
+			 "=m" (futex)					      \
+		       : "0" (0), "1" (1), "m" (futex), "m" (timeout)	      \
+		       : "memory");					      \
+     result; })
+
+
+#define lll_mutex_unlock(futex) \
+  (void) ({ int ignore;							      \
+            __asm __volatile (LOCK_INSTR "subl $1,%0\n\t"		      \
+			      "jne _L_mutex_unlock_%=\n\t"		      \
+			      ".subsection 1\n\t"			      \
+			      ".type _L_mutex_unlock_%=,@function\n"	      \
+			      "_L_mutex_unlock_%=:\n\t"			      \
+			      "leal %0, %%eax\n\t"			      \
+			      "call __lll_mutex_unlock_wake\n\t"	      \
+			      "jmp 1f\n\t"				      \
+			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
+			      ".previous\n"				      \
+			      "1:"					      \
+			      : "=m" (futex), "=&a" (ignore)		      \
+			      : "m" (futex)				      \
+			      : "memory"); })
+
+
+#define lll_mutex_islocked(futex) \
+  (futex != 0)
+
+
+/* We have a separate internal lock implementation which is not tied
+   to binary compatibility.  */
+
+/* Type for lock object.  */
+typedef int lll_lock_t;
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER		(0)
+#define LLL_LOCK_INITIALIZER_LOCKED	(1)
+
+
+extern int __lll_lock_wait (int val, int *__futex)
+     __attribute ((regparm (2))) attribute_hidden;
+extern int __lll_unlock_wake (int *__futex)
+     __attribute ((regparm (1))) attribute_hidden;
+extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
+
+
+/* The states of a lock are:
+    0  -  untaken
+    1  -  taken by one user
+    2  -  taken by more users */
+
+
+#if defined NOT_IN_libc || defined UP
+# define lll_trylock(futex) lll_mutex_trylock (futex)
+# define lll_lock(futex) lll_mutex_lock (futex)
+# define lll_unlock(futex) lll_mutex_unlock (futex)
+#else
+/* Special versions of the macros for use in libc itself.  They avoid
+   the lock prefix when the thread library is not used.
+
+   XXX In future we might even want to avoid it on UP machines.  */
+# include <tls.h>
+
+# define lll_trylock(futex) \
+  ({ unsigned char ret;							      \
+     __asm __volatile ("cmpl $0, %%gs:%P5\n\t"				      \
+		       "je,pt 0f\n\t"					      \
+		       "lock\n"						      \
+		       "0:\tcmpxchgl %2, %1; setne %0"			      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\
+			 "0" (LLL_MUTEX_LOCK_INITIALIZER),		      \
+		         "i" (offsetof (tcbhead_t, multiple_threads))	      \
+		       : "memory");					      \
+     ret; })
+
+
+# define lll_lock(futex) \
+  (void) ({ int ignore1, ignore2;					      \
+	    __asm __volatile ("cmpl $0, %%gs:%P6\n\t"			      \
+			      "je,pt 0f\n\t"				      \
+			      "lock\n"					      \
+			      "0:\tcmpxchgl %1, %2\n\t"			      \
+			      "jnz _L_mutex_lock_%=\n\t"		      \
+			      ".subsection 1\n\t"			      \
+			      ".type _L_mutex_lock_%=,@function\n"	      \
+			      "_L_mutex_lock_%=:\n\t"			      \
+			      "leal %2, %%ecx\n\t"			      \
+			      "call __lll_mutex_lock_wait\n\t"		      \
+			      "jmp 1f\n\t"				      \
+			      ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n"   \
+			      ".previous\n"				      \
+			      "1:"					      \
+			      : "=a" (ignore1), "=c" (ignore2), "=m" (futex)  \
+			      : "0" (0), "1" (1), "m" (futex),		      \
+		                "i" (offsetof (tcbhead_t, multiple_threads))  \
+			      : "memory"); })
+
+
+# define lll_unlock(futex) \
+  (void) ({ int ignore;							      \
+            __asm __volatile ("cmpl $0, %%gs:%P3\n\t"			      \
+			      "je,pt 0f\n\t"				      \
+			      "lock\n"					      \
+			      "0:\tsubl $1,%0\n\t"		      \
+			      "jne _L_mutex_unlock_%=\n\t"		      \
+			      ".subsection 1\n\t"			      \
+			      ".type _L_mutex_unlock_%=,@function\n"	      \
+			      "_L_mutex_unlock_%=:\n\t"			      \
+			      "leal %0, %%eax\n\t"			      \
+			      "call __lll_mutex_unlock_wake\n\t"	      \
+			      "jmp 1f\n\t"				      \
+			      ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
+			      ".previous\n"				      \
+			      "1:"					      \
+			      : "=m" (futex), "=&a" (ignore)		      \
+			      : "m" (futex),				      \
+				"i" (offsetof (tcbhead_t, multiple_threads))  \
+			      : "memory"); })
+#endif
+
+
+#define lll_islocked(futex) \
+  (futex != LLL_LOCK_INITIALIZER)
+
+
+/* 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.
+
+   The macro parameter must not have any side effect.  */
+#define lll_wait_tid(tid) \
+  do {									      \
+    int __ignore;							      \
+    register __typeof (tid) _tid asm ("edx") = (tid);			      \
+    if (_tid != 0)							      \
+      __asm __volatile (LLL_EBX_LOAD					      \
+			"1:\tmovl %1, %%eax\n\t"			      \
+			LLL_ENTER_KERNEL				      \
+			"cmpl $0, (%%ebx)\n\t"				      \
+			"jne,pn 1b\n\t"					      \
+			LLL_EBX_LOAD					      \
+			: "=&a" (__ignore)				      \
+			: "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),	      \
+			  "c" (FUTEX_WAIT), "d" (_tid),			      \
+			  "i" (offsetof (tcbhead_t, sysinfo)));		      \
+  } while (0)
+
+extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
+     __attribute__ ((regparm (2))) attribute_hidden;
+#define lll_timedwait_tid(tid, abstime) \
+  ({									      \
+    int __result = 0;							      \
+    if (tid != 0)							      \
+      {									      \
+	if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)	      \
+	  __result = EINVAL;						      \
+	else								      \
+	  __result = __lll_timedwait_tid (&tid, abstime);		      \
+      }									      \
+    __result; })
+
+
+/* Conditional variable handling.  */
+
+extern void __lll_cond_wait (pthread_cond_t *cond)
+     __attribute ((regparm (1))) attribute_hidden;
+extern int __lll_cond_timedwait (pthread_cond_t *cond,
+				 const struct timespec *abstime)
+     __attribute ((regparm (2))) attribute_hidden;
+extern void __lll_cond_wake (pthread_cond_t *cond)
+     __attribute ((regparm (1))) attribute_hidden;
+extern void __lll_cond_broadcast (pthread_cond_t *cond)
+     __attribute ((regparm (1))) 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 */
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/bits/posix_opt.h.jj	2004-05-10 10:19:24.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/bits/posix_opt.h	2004-04-13 10:42:53.000000000 +0200
@@ -0,0 +1,147 @@
+/* Define POSIX options for Linux.
+   Copyright (C) 1996-2001, 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
+   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.  */
+
+#ifndef	_POSIX_OPT_H
+#define	_POSIX_OPT_H	1
+
+/* Job control is supported.  */
+#define	_POSIX_JOB_CONTROL	1
+
+/* Processes have a saved set-user-ID and a saved set-group-ID.  */
+#define	_POSIX_SAVED_IDS	1
+
+/* Priority scheduling is supported.  */
+#define	_POSIX_PRIORITY_SCHEDULING	200112L
+
+/* Synchronizing file data is supported.  */
+#define	_POSIX_SYNCHRONIZED_IO	200112L
+
+/* The fsync function is present.  */
+#define	_POSIX_FSYNC	200112L
+
+/* Mapping of files to memory is supported.  */
+#define	_POSIX_MAPPED_FILES	200112L
+
+/* Locking of all memory is supported.  */
+#define	_POSIX_MEMLOCK	200112L
+
+/* Locking of ranges of memory is supported.  */
+#define	_POSIX_MEMLOCK_RANGE	200112L
+
+/* Setting of memory protections is supported.  */
+#define	_POSIX_MEMORY_PROTECTION	200112L
+
+/* Only root can change owner of file.  */
+#define	_POSIX_CHOWN_RESTRICTED	1
+
+/* `c_cc' member of 'struct termios' structure can be disabled by
+   using the value _POSIX_VDISABLE.  */
+#define	_POSIX_VDISABLE	'\0'
+
+/* Filenames are not silently truncated.  */
+#define	_POSIX_NO_TRUNC	1
+
+/* X/Open realtime support is available.  */
+#define _XOPEN_REALTIME	1
+
+/* XPG4.2 shared memory is supported.  */
+#define	_XOPEN_SHM	1
+
+/* Tell we have POSIX threads.  */
+#define _POSIX_THREADS	200112L
+
+/* We have the reentrant functions described in POSIX.  */
+#define _POSIX_REENTRANT_FUNCTIONS      1
+#define _POSIX_THREAD_SAFE_FUNCTIONS	200112L
+
+/* We provide priority scheduling for threads.  */
+#define _POSIX_THREAD_PRIORITY_SCHEDULING	200112L
+
+/* We support user-defined stack sizes.  */
+#define _POSIX_THREAD_ATTR_STACKSIZE	200112L
+
+/* We support user-defined stacks.  */
+#define _POSIX_THREAD_ATTR_STACKADDR	200112L
+
+/* We support POSIX.1b semaphores.  */
+#define _POSIX_SEMAPHORES	200112L
+
+/* Real-time signals are supported.  */
+#define _POSIX_REALTIME_SIGNALS	200112L
+
+/* We support asynchronous I/O.  */
+#define _POSIX_ASYNCHRONOUS_IO	200112L
+#define _POSIX_ASYNC_IO		1
+/* Alternative name for Unix98.  */
+#define _LFS_ASYNCHRONOUS_IO	1
+
+/* The LFS support in asynchronous I/O is also available.  */
+#define _LFS64_ASYNCHRONOUS_IO	1
+
+/* The rest of the LFS is also available.  */
+#define _LFS_LARGEFILE		1
+#define _LFS64_LARGEFILE	1
+#define _LFS64_STDIO		1
+
+/* POSIX shared memory objects are implemented.  */
+#define _POSIX_SHARED_MEMORY_OBJECTS	200112L
+
+/* CPU-time clocks supported.  */
+#define _POSIX_CPUTIME 200112L
+
+/* We support the clock also in threads.  */
+#define _POSIX_THREAD_CPUTIME  200112L
+
+/* GNU libc provides regular expression handling.  */
+#define _POSIX_REGEXP	1
+
+/* Reader/Writer locks are available.  */
+#define _POSIX_READER_WRITER_LOCKS	200112L
+
+/* We have a POSIX shell.  */
+#define _POSIX_SHELL	1
+
+/* We support the Timeouts option.  */
+#define _POSIX_TIMEOUTS	200112L
+
+/* We support spinlocks.  */
+#define _POSIX_SPIN_LOCKS	200112L
+
+/* The `spawn' function family is supported.  */
+#define _POSIX_SPAWN	200112L
+
+/* We have POSIX timers.  */
+#define _POSIX_TIMERS	200112L
+
+/* The barrier functions are available.  */
+#define _POSIX_BARRIERS	200112L
+
+/* POSIX message queues are available.  */
+#define	_POSIX_MESSAGE_PASSING	200112L
+
+/* Thread process-shared synchronization is supported.  */
+#define _POSIX_THREAD_PROCESS_SHARED	200112L
+
+/* The monotonic clock might be available.  */
+#define _POSIX_MONOTONIC_CLOCK	0
+
+/* The clock selection interfaces are available.  */
+#define _POSIX_CLOCK_SELECTION	200112L
+
+#endif /* posix_opt.h */
--- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_once.S.jj	2004-05-09 20:28:01.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_once.S	2003-10-03 21:49:23.000000000 +0200
@@ -0,0 +1,182 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 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.  */
+
+#include <unwindbuf.h>
+#include <sysdep.h>
+
+#ifndef UP
+# define LOCK lock
+#else
+# define LOCK
+#endif
+
+#define SYS_futex	240
+#define FUTEX_WAKE	1
+
+	.comm	__fork_generation, 4, 4
+
+	.text
+
+
+	.globl	__pthread_once
+	.type	__pthread_once,@function
+	.align	16
+	cfi_startproc
+__pthread_once:
+	movl	4(%esp), %ecx
+	testl	$2, (%ecx)
+	jz	1f
+	xorl	%eax, %eax
+	ret
+
+1:	pushl	%ebx
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (3, 0)
+	pushl	%esi
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (6, 0)
+	movl	%ecx, %ebx
+	xorl	%esi, %esi
+
+	/* Not yet initialized or initialization in progress.
+	   Get the fork generation counter now.  */
+6:	movl	(%ebx), %eax
+#ifdef PIC
+	call	__i686.get_pc_thunk.cx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
+#endif
+
+5:	movl	%eax, %edx
+
+	testl	$2, %eax
+	jnz	4f
+
+	andl	$3, %edx
+#ifdef PIC
+	orl	__fork_generation@GOTOFF(%ecx), %edx
+#else
+	orl	__fork_generation, %edx
+#endif
+	orl	$1, %edx
+
+	LOCK
+	cmpxchgl %edx, (%ebx)
+	jnz	5b
+
+	/* Check whether another thread already runs the initializer.  */
+	testl	$1, %eax
+	jz	3f	/* No -> do it.  */
+
+	/* Check whether the initializer execution was interrupted
+	   by a fork.  */
+	xorl	%edx, %eax
+	testl	$0xfffffffc, %eax
+	jnz	3f	/* Different for generation -> run initializer.  */
+
+	/* Somebody else got here first.  Wait.  */
+	movl	%esi, %ecx		/* movl $FUTEX_WAIT, %ecx */
+	movl	$SYS_futex, %eax
+	ENTER_KERNEL
+	jmp	6b
+
+3:	/* Call the initializer function after setting up the
+	   cancellation handler.  Note that it is not possible here
+	   to use the unwind-based cleanup handling.  This would require
+	   that the user-provided function and all the code it calls
+	   is compiled with exceptions.  Unfortunately this cannot be
+	   guaranteed.  */
+	subl	$UNWINDBUFSIZE+8, %esp
+	cfi_adjust_cfa_offset (UNWINDBUFSIZE+8)
+	movl	%ecx, %ebx		/* PIC register value.  */
+
+	leal	8+UWJMPBUF(%esp), %eax
+	movl	$0, 4(%esp)
+	movl	%eax, (%esp)
+	call	__sigsetjmp@PLT
+	testl	%eax, %eax
+	jne	7f
+
+	leal	8(%esp), %eax
+	call	HIDDEN_JUMPTARGET(__pthread_register_cancel)
+
+	/* Call the user-provided initialization function.  */
+	call	*24+UNWINDBUFSIZE(%esp)
+
+	/* Pop the cleanup handler.  */
+	leal	8(%esp), %eax
+	call	HIDDEN_JUMPTARGET(__pthread_unregister_cancel)
+	addl	$UNWINDBUFSIZE+8, %esp
+	cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8)
+
+	/* Sucessful run of the initializer.  Signal that we are done.  */
+	movl	12(%esp), %ebx
+	LOCK
+	addl	$1, (%ebx)
+
+	/* Wake up all other threads.  */
+	movl	$0x7fffffff, %edx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	ENTER_KERNEL
+
+4:	popl	%esi
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (6)
+	popl	%ebx
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (3)
+	xorl	%eax, %eax
+	ret
+
+7:	/* __sigsetjmp returned for the second time.  */
+	movl	20+UNWINDBUFSIZE(%esp), %ebx
+	cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
+	cfi_offset (3, -8)
+	cfi_offset (6, -12)
+	movl	$0, (%ebx)
+
+	movl	$0x7fffffff, %edx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	ENTER_KERNEL
+
+	leal	8(%esp), %eax
+	call	HIDDEN_JUMPTARGET (__pthread_unwind_next)
+	/* NOTREACHED */
+	hlt
+	cfi_endproc
+	.size	__pthread_once,.-__pthread_once
+
+	.globl	__pthread_once_internal
+__pthread_once_internal = __pthread_once
+
+	.globl	pthread_once
+pthread_once = __pthread_once
+
+
+#ifdef PIC
+	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
+	.globl	__i686.get_pc_thunk.cx
+	.hidden	__i686.get_pc_thunk.cx
+	.type	__i686.get_pc_thunk.cx,@function
+__i686.get_pc_thunk.cx:
+	movl (%esp), %ecx;
+	ret
+	.size	__i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
+#endif
--- libc/nptl/sysdeps/i386/rt-atomic.S.jj	2004-05-10 09:01:17.000000000 +0200
+++ libc/nptl/sysdeps/i386/rt-atomic.S	2004-05-10 09:01:12.000000000 +0200
@@ -0,0 +1 @@
+#include <atomic.S>
--- libc/nptl/sysdeps/i386/pthread_spin_trylock.c.jj	2004-05-09 19:42:23.000000000 +0200
+++ libc/nptl/sysdeps/i386/pthread_spin_trylock.c	2004-05-10 12:01:42.000000000 +0200
@@ -0,0 +1,46 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
+
+   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 "pthreadP.h"
+#include <errno.h>
+
+#ifndef LOCK_PREFIX
+# ifdef UP
+#  define LOCK_PREFIX	/* nothing */
+# else
+#  define LOCK_PREFIX	"lock;"
+# endif
+#endif
+
+
+int
+pthread_spin_trylock (lock)
+     pthread_spinlock_t *lock;
+{
+  int ret = EBUSY;
+  asm ("\n"
+       LOCK_PREFIX "btrl $0, %0\n\t"
+       "jnc 1f\n\t"
+       "xorl %1, %1\n\t"
+       "1:"
+       : "=m" (*lock), "=r" (ret)
+       : "m" (*lock), "1" (ret));
+
+  return ret;
+}
--- libc/nptl/sysdeps/i386/bits/atomic.h.jj	2004-05-07 16:09:51.000000000 +0200
+++ libc/nptl/sysdeps/i386/bits/atomic.h	2004-05-10 14:25:58.000000000 +0200
@@ -0,0 +1,192 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
+
+   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 <stdint.h>
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int16_t atomic16_t;
+typedef uint16_t uatomic16_t;
+typedef int_fast16_t atomic_fast16_t;
+typedef uint_fast16_t uatomic_fast16_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+
+#ifndef LOCK_PREFIX
+# ifdef UP
+#  define LOCK_PREFIX	/* nothing */
+# else
+#  define LOCK_PREFIX "lock;"
+# endif
+#endif
+
+#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
+  ({ __typeof (*mem) ret;						      \
+     __asm __volatile ("call __atomic_cmpxchgb"				      \
+		       : "=a" (ret), "=m" (*mem)			      \
+		       : "c" (newval), "d" (mem), "m" (*mem), "0" (oldval));  \
+     ret; })
+
+#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
+  ({ __typeof (*mem) ret;						      \
+     __asm __volatile ("call __atomic_cmpxchgw"				      \
+		       : "=a" (ret), "=m" (*mem)			      \
+		       : "c" (newval), "d" (mem), "m" (*mem), "0" (oldval));  \
+     ret; })
+
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+  ({ __typeof (*mem) ret;						      \
+     __asm __volatile ("call __atomic_cmpxchgl"				      \
+		       : "=a" (ret), "=m" (*mem)			      \
+		       : "c" (newval), "d" (mem), "m" (*mem), "0" (oldval));  \
+     ret; })
+
+#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
+  ({ __typeof (*mem) ret = *(mem); abort (); ret = (newval); ret = (oldval); })
+
+/* Note that we need no lock prefix.  */
+#define atomic_exchange_acq(mem, newvalue) \
+  ({ __typeof (*mem) result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile ("call __atomic_xchgb"				      \
+			 : "=a" (result), "=m" (*mem)			      \
+			 : "0" (newvalue), "d" (mem), "m" (*mem));	      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile ("call __atomic_xchgw"				      \
+			 : "=a" (result), "=m" (*mem)			      \
+			 : "0" (newvalue), "d" (mem), "m" (*mem));	      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile ("call __atomic_xchgl"				      \
+			 : "=a" (result), "=m" (*mem)			      \
+			 : "0" (newvalue), "d" (mem), "m" (*mem));	      \
+     else								      \
+       {								      \
+	 result = 0;							      \
+	 abort ();							      \
+       }								      \
+     result; })
+
+
+#define atomic_exchange_and_add(mem, value) \
+  ({ __typeof (*mem) result;						      \
+     __typeof (value) addval = (value);					      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile ("call __atomic_xaddb"				      \
+			 : "=a" (result), "=m" (*mem)			      \
+			 : "0" (addval), "d" (mem), "m" (*mem)		      \
+			 : "ecx");					      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile ("call __atomic_xaddw"				      \
+			 : "=a" (result), "=m" (*mem)			      \
+			 : "0" (addval), "d" (mem), "m" (*mem)		      \
+			 : "ecx");					      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile ("call __atomic_xaddl"				      \
+			 : "=a" (result), "=m" (*mem)			      \
+			 : "0" (addval), "d" (mem), "m" (*mem)		      \
+			 : "ecx");					      \
+     else								      \
+       {								      \
+	 __typeof (mem) memp = (mem);					      \
+	 do								      \
+	   result = *memp;						      \
+	 while (__arch_compare_and_exchange_val_64_acq (memp,		      \
+							result + addval,      \
+							result) == result);   \
+       }								      \
+     result; })
+
+
+#define atomic_increment(mem) \
+  (void) atomic_increment_and_test(mem)
+
+#define atomic_increment_and_test(mem) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile ("call __atomic_incb_sete"			      \
+			 : "=m" (*mem), "=a" (__result)			      \
+			 : "d" (mem), "m" (*mem));			      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile ("call __atomic_incw_sete"			      \
+			 : "=m" (*mem), "=a" (__result)			      \
+			 : "d" (mem), "m" (*mem));			      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile ("call __atomic_incl_sete"			      \
+			 : "=m" (*mem), "=a" (__result)			      \
+			 : "d" (mem), "m" (*mem));			      \
+     else								      \
+       abort ();							      \
+     __result; })
+
+
+#define atomic_decrement(mem) \
+  (void) atomic_decrement_and_test(mem)
+
+#define atomic_decrement_and_test(mem) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 1)						      \
+       __asm __volatile ("call __atomic_decb_sete"			      \
+			 : "=m" (*mem), "=a" (__result)			      \
+			 : "d" (mem), "m" (*mem));			      \
+     else if (sizeof (*mem) == 2)					      \
+       __asm __volatile ("call __atomic_decw_sete"			      \
+			 : "=m" (*mem), "=a" (__result)			      \
+			 : "d" (mem), "m" (*mem));			      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile ("call __atomic_decl_sete"			      \
+			 : "=m" (*mem), "=a" (__result)			      \
+			 : "d" (mem), "m" (*mem));			      \
+     else								      \
+       abort ();							      \
+     __result; })
+
+
+#define atomic_bit_set(mem, bit) \
+  (void) atomic_bit_test_set(mem, bit)
+
+#define atomic_bit_test_set(mem, bit) \
+  ({ unsigned char __result;						      \
+     if (sizeof (*mem) == 2)						      \
+       __asm __volatile ("call __atomic_btsw_setc"			      \
+			 : "=a" (__result), "=m" (*mem)			      \
+			 : "d" (mem), "m" (*mem), "a" (bit));		      \
+     else if (sizeof (*mem) == 4)					      \
+       __asm __volatile ("call __atomic_btsl_setc"			      \
+			 : "=a" (__result), "=m" (*mem)			      \
+			 : "d" (mem), "m" (*mem), "a" (bit));		      \
+     else							      	      \
+       abort ();							      \
+     __result; })
--- libc/nptl/sysdeps/i386/atomic.S.jj	2004-05-07 16:26:23.000000000 +0200
+++ libc/nptl/sysdeps/i386/atomic.S	2004-05-10 14:24:19.000000000 +0200
@@ -0,0 +1,291 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
+
+   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 LOCK_PREFIX
+# ifdef UP
+#  define LOCK_PREFIX /* nothing */
+# else
+#  define LOCK_PREFIX lock;
+# endif
+#endif
+
+#ifndef SHARED
+# define ATOMIC_FN(name)			\
+	.globl	__atomic_##name;		\
+	.hidden	__atomic_##name;		\
+	.type	__atomic_##name, @function;	\
+	.align	16;				\
+__atomic_##name:				\
+	cmpl	$0, __atomic_has_cmpxchg;	\
+	jz	__lock_##name;
+# define ATOMIC_LOCK(name)			\
+__lock_##name:					\
+	pushl	%ebx;				\
+	xorl	%ebx, %ebx;			\
+	movb	%dl, %bl;			\
+	xorb	%dh, %bl;			\
+	shrl	$2, %ebx;			\
+1:	LOCK_PREFIX				\
+	btsl	$0, __atomic_locks(%ebx);	\
+	jc	1b;
+# define ATOMIC_UNLOCK(name)			\
+	movb	$0, __atomic_locks(%ebx);	\
+	popl	%ebx;				\
+	ret;					\
+.size __atomic_##name, .-__atomic_##name;
+#else
+# define ATOMIC_FN(name)			\
+	.globl	__atomic_##name;		\
+	.hidden	__atomic_##name;		\
+	.type	__atomic_##name, @function;	\
+	.align	16;				\
+__atomic_##name:				\
+	.if	0
+# define ATOMIC_LOCK(name)			\
+	.endif;					\
+	pushl	%ebx;				\
+	call	0f;				\
+0:	xorl	%ebx, %ebx;			\
+	xorl	%ebx, %ebx;			\
+	movb	%dl, %bl;			\
+	xorb	%dh, %bl;			\
+	shrl	$2, %ebx;			\
+	addl	(%esp), %ebx;			\
+1:	LOCK_PREFIX				\
+	btsl	$0, __atomic_locks-0b(%ebx);	\
+	jc	1b;
+# define ATOMIC_UNLOCK(name)			\
+	movb	$0, __atomic_locks-0b(%ebx);	\
+	popl	%ebx;				\
+	popl	%ebx;				\
+	ret;					\
+.size __atomic_##name, .-__atomic_##name;
+#endif
+
+	.data
+	.align	4
+__atomic_locks:
+	.skip	64
+#ifndef SHARED
+	.globl	__atomic_has_cmpxchg
+	.hidden	__atomic_has_cmpxchg
+	.type	__atomic_has_cmpxchg, @object
+	.size	__atomic_has_cmpxchg, 4
+	.align	4
+__atomic_has_cmpxchg:
+	.long	0
+	.text
+	.globl	__atomic_i386_init
+	.hidden	__atomic_i386_init
+	.type	__atomic_i386_init, @function
+	.align	16
+__atomic_i386_init:
+	pushfl
+	pushfl
+	popl	%eax
+	movl	%eax, %edx
+	btcl	$18, %eax
+	pushl	%eax
+	popfl
+	pushfl
+	popl	%eax
+	popfl
+	xorl	%eax, %edx
+	btl	$18, %edx
+	jnc	1f
+	movl	$1, __atomic_has_cmpxchg
+1:	ret
+.size __atomic_i386_init, .-__atomic_i386_init
+#endif
+
+	/* All functions here are internal_function calling convention.
+	   First arg %eax, second %edx, third %ecx.  */
+	.text
+	/* __atomic_cmpxchgb (oldval, mem, newval) */
+ATOMIC_FN (cmpxchgb)
+	LOCK_PREFIX cmpxchgb %cl, (%edx)
+	ret
+ATOMIC_LOCK (cmpxchgb)
+	cmpb	%al, (%edx)
+	jne	2f
+	movb	%cl, (%edx)
+	jmp	3f
+2:	movb	(%edx), %al
+3:
+ATOMIC_UNLOCK (cmpxchgb)
+
+	/* __atomic_cmpxchgw (oldval, mem, newval) */
+ATOMIC_FN (cmpxchgw)
+	LOCK_PREFIX cmpxchgw %cx, (%edx)
+	ret
+ATOMIC_LOCK (cmpxchgw)
+	cmpw	%ax, (%edx)
+	jne	2f
+	movw	%cx, (%edx)
+	jmp	3f
+2:	movw	(%edx), %ax
+3:
+ATOMIC_UNLOCK (cmpxchgw)
+
+	/* __atomic_cmpxchgl (oldval, mem, newval) */
+ATOMIC_FN (cmpxchgl)
+	LOCK_PREFIX cmpxchgl %ecx, (%edx)
+	ret
+ATOMIC_LOCK (cmpxchgl)
+	cmpl	%eax, (%edx)
+	jne	2f
+	movl	%ecx, (%edx)
+	jmp	3f
+2:	movl	(%edx), %eax
+3:
+ATOMIC_UNLOCK (cmpxchgl)
+
+	/* __atomic_xchgb (newval, mem) */
+ATOMIC_FN (xchgb)
+	xchgb	%al, (%edx)
+	ret
+ATOMIC_LOCK (xchgb)
+	xchgb	%al, (%edx)
+ATOMIC_UNLOCK (xchgb)
+
+	/* __atomic_xchgw (newval, mem) */
+ATOMIC_FN (xchgw)
+	xchgw	%ax, (%edx)
+	ret
+ATOMIC_LOCK (xchgw)
+	xchgw	%ax, (%edx)
+ATOMIC_UNLOCK (xchgw)
+
+	/* __atomic_xchgl (newval, mem) */
+ATOMIC_FN (xchgl)
+	xchgl	%eax, (%edx)
+	ret
+ATOMIC_LOCK (xchgl)
+	xchgl	%eax, (%edx)
+ATOMIC_UNLOCK (xchgl)
+
+	/* __atomic_xaddb (addval, mem) */
+ATOMIC_FN (xaddb)
+	LOCK_PREFIX xaddb %al, (%edx)
+	ret
+ATOMIC_LOCK (xaddb)
+	movb	(%edx), %cl
+	addb	%al, (%edx)
+	movl	%ecx, %eax
+ATOMIC_UNLOCK (xaddb)
+
+	/* __atomic_xaddw (addval, mem) */
+ATOMIC_FN (xaddw)
+	LOCK_PREFIX xaddw %ax, (%edx)
+	ret
+ATOMIC_LOCK (xaddw)
+	movw	(%edx), %cx
+	addw	%ax, (%edx)
+	movl	%ecx, %eax
+ATOMIC_UNLOCK (xaddw)
+
+	/* __atomic_xaddl (addval, mem) */
+ATOMIC_FN (xaddl)
+	LOCK_PREFIX xaddl %eax, (%edx)
+	ret
+ATOMIC_LOCK (xaddl)
+	movl	(%edx), %ecx
+	addl	%eax, (%edx)
+	movl	%ecx, %eax
+ATOMIC_UNLOCK (xaddl)
+
+	/* __atomic_incb_sete (0, mem) */
+ATOMIC_FN (incb_sete)
+	LOCK_PREFIX incb (%edx)
+	sete	%al
+	ret
+ATOMIC_LOCK (incb_sete)
+	incb	(%edx)
+	sete	%al
+ATOMIC_UNLOCK (incb_sete)
+
+	/* __atomic_incw_sete (0, mem) */
+ATOMIC_FN (incw_sete)
+	LOCK_PREFIX incw (%edx)
+	sete	%al
+	ret
+ATOMIC_LOCK (incw_sete)
+	incw	(%edx)
+	sete	%al
+ATOMIC_UNLOCK (incw_sete)
+
+	/* __atomic_incl_sete (0, mem) */
+ATOMIC_FN (incl_sete)
+	LOCK_PREFIX incl (%edx)
+	sete	%al
+	ret
+ATOMIC_LOCK (incl_sete)
+	incl	(%edx)
+	sete	%al
+ATOMIC_UNLOCK (incl_sete)
+
+	/* __atomic_decb_sete (0, mem) */
+ATOMIC_FN (decb_sete)
+	LOCK_PREFIX decb (%edx)
+	sete	%al
+	ret
+ATOMIC_LOCK (decb_sete)
+	decb	(%edx)
+	sete	%al
+ATOMIC_UNLOCK (decb_sete)
+
+	/* __atomic_decw_sete (0, mem) */
+ATOMIC_FN (decw_sete)
+	LOCK_PREFIX decw (%edx)
+	sete	%al
+	ret
+ATOMIC_LOCK (decw_sete)
+	decw	(%edx)
+	sete	%al
+ATOMIC_UNLOCK (decw_sete)
+
+	/* __atomic_decl_sete (0, mem) */
+ATOMIC_FN (decl_sete)
+	LOCK_PREFIX decl (%edx)
+	sete	%al
+	ret
+ATOMIC_LOCK (decl_sete)
+	decl	(%edx)
+	sete	%al
+ATOMIC_UNLOCK (decl_sete)
+
+	/* __atomic_btsw_setc (bit, mem) */
+ATOMIC_FN (btsw_setc)
+	LOCK_PREFIX btsw %ax, (%edx)
+	setc	%al
+	ret
+ATOMIC_LOCK (btsw_setc)
+	btsw	%ax, (%edx)
+	setc	%al
+ATOMIC_UNLOCK (btsw_setc)
+
+	/* __atomic_btsl_setc (bit, mem) */
+ATOMIC_FN (btsl_setc)
+	LOCK_PREFIX btsl %eax, (%edx)
+	setc	%al
+	ret
+ATOMIC_LOCK (btsl_setc)
+	btsl	%eax, (%edx)
+	setc	%al
+ATOMIC_UNLOCK (btsl_setc)
--- libc/nptl/sysdeps/i386/i686/bits/atomic.h.jj	2004-05-07 16:11:02.000000000 +0200
+++ libc/nptl/sysdeps/i386/i686/bits/atomic.h	2004-05-10 15:59:47.492939545 +0200
@@ -0,0 +1 @@
+#include "../../../../../sysdeps/i386/i486/bits/atomic.h"
--- libc/nptl/sysdeps/i386/i686/atomic.S.jj	2004-05-10 08:59:55.000000000 +0200
+++ libc/nptl/sysdeps/i386/i686/atomic.S	2004-05-10 08:59:51.000000000 +0200
@@ -0,0 +1 @@
+/* Nothing needed.  */
--- libc/nptl/sysdeps/i386/i686/tls.h.jj	2002-11-26 23:50:15.000000000 +0100
+++ libc/nptl/sysdeps/i386/i686/tls.h	2004-05-07 15:14:50.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -31,6 +31,6 @@
 
 
 /* Get the full set of definitions.  */
-#include "../tls.h"
+#include "../i486/tls.h"
 
 #endif	/* tls.h */
--- libc/nptl/sysdeps/i386/i686/pthread_spin_lock.c.jj	2004-05-09 19:09:43.000000000 +0200
+++ libc/nptl/sysdeps/i386/i686/pthread_spin_lock.c	2004-05-09 19:09:56.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/pthread_spin_lock.c"
--- libc/nptl/sysdeps/i386/nscd-atomic.S.jj	2004-05-10 09:01:17.000000000 +0200
+++ libc/nptl/sysdeps/i386/nscd-atomic.S	2004-05-10 09:01:12.000000000 +0200
@@ -0,0 +1 @@
+#include <atomic.S>
--- libc/nptl/sysdeps/i386/i586/bits/atomic.h.jj	2004-05-07 16:11:02.000000000 +0200
+++ libc/nptl/sysdeps/i386/i586/bits/atomic.h	2004-05-10 15:59:29.440174835 +0200
@@ -0,0 +1 @@
+#include "../../../../../sysdeps/i386/i486/bits/atomic.h"
--- libc/nptl/sysdeps/i386/i586/atomic.S.jj	2004-05-10 08:59:55.000000000 +0200
+++ libc/nptl/sysdeps/i386/i586/atomic.S	2004-05-10 08:59:51.000000000 +0200
@@ -0,0 +1 @@
+/* Nothing needed.  */
--- libc/nptl/sysdeps/i386/i586/tls.h.jj	2004-05-07 15:14:31.000000000 +0200
+++ libc/nptl/sysdeps/i386/i586/tls.h	2004-05-08 01:10:14.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/tls.h"
--- libc/nptl/sysdeps/i386/i586/pthread_spin_lock.c.jj	2004-05-09 19:09:43.000000000 +0200
+++ libc/nptl/sysdeps/i386/i586/pthread_spin_lock.c	2004-05-09 19:09:56.000000000 +0200
@@ -0,0 +1 @@
+#include "../i486/pthread_spin_lock.c"
--- libc/nptl/sysdeps/i386/tls.h.jj	2004-03-05 12:13:00.000000000 +0100
+++ libc/nptl/sysdeps/i386/tls.h	2004-05-10 10:58:45.000000000 +0200
@@ -179,6 +179,16 @@ union user_desc_init
 # endif
 #endif
 
+#ifndef INIT_CMPXCHG
+# ifndef SHARED
+extern void __atomic_i386_init (void) attribute_hidden;
+#  define INIT_CMPXCHG \
+  __atomic_i386_init ()
+# else
+#  define INIT_CMPXCHG
+# endif
+#endif
+
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
@@ -193,6 +203,7 @@ union user_desc_init
      _head->self = _thrdescr;						      \
      /* New syscall handling support.  */				      \
      INIT_SYSINFO;							      \
+     INIT_CMPXCHG;							      \
 									      \
      /* The 'entry_number' field.  Let the kernel pick a value.  */	      \
      if (secondcall)							      \
@@ -367,32 +378,6 @@ union user_desc_init
        }})
 
 
-/* Atomic compare and exchange on TLS, returning old value.  */
-#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \
-  ({ __typeof (descr->member) __ret;					      \
-     __typeof (oldval) __old = (oldval);				      \
-     if (sizeof (descr->member) == 4)					      \
-       asm volatile (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3"		      \
-		     : "=a" (__ret)					      \
-		     : "0" (__old), "r" (newval),			      \
-		       "i" (offsetof (struct pthread, member)));	      \
-     else								      \
-       /* Not necessary for other sizes in the moment.  */		      \
-       abort ();							      \
-     __ret; })
-
-
-/* Atomic set bit.  */
-#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
-  (void) ({ if (sizeof ((descr)->member) == 4)				      \
-	      asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0"		      \
-			    :: "i" (offsetof (struct pthread, member)),	      \
-			       "ir" (1 << (bit)));			      \
-	    else							      \
-	      /* Not necessary for other sizes in the moment.  */	      \
-	      abort (); })
-
-
 /* Call the user-provided thread function.  */
 #define CALL_THREAD_FCT(descr) \
   ({ void *__res;							      \
--- libc/nptl/sysdeps/i386/Makefile.jj	2003-09-17 11:34:55.000000000 +0200
+++ libc/nptl/sysdeps/i386/Makefile	2004-05-10 11:04:20.000000000 +0200
@@ -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
@@ -18,8 +18,22 @@
 
 ifeq ($(subdir),csu)
 gen-as-const-headers += tcb-offsets.sym
+routines += atomic
+$(objpfx)tst-atomic: $(objpfx)atomic.o
+$(objpfx)tst-atomic-long: $(objpfx)atomic.o
 endif
 
 ifeq ($(subdir),nptl)
 CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4
+
+libpthread-routines += ptw-atomic
+endif
+
+ifeq ($(subdir),rt)
+librt-routines += rt-atomic
+endif
+
+ifeq ($(subdir),nscd)
+nscd-modules += nscd-atomic
+CFLAGS-nscd-atomic.S += -DSHARED
 endif
--- libc/nptl/sysdeps/i386/pthread_spin_lock.c.jj	2004-04-13 10:42:53.000000000 +0200
+++ libc/nptl/sysdeps/i386/pthread_spin_lock.c	2004-05-10 12:01:35.000000000 +0200
@@ -1,6 +1,6 @@
-/* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -33,13 +33,13 @@ pthread_spin_lock (lock)
      pthread_spinlock_t *lock;
 {
   asm ("\n"
-       "1:\t" LOCK_PREFIX "decl %0\n\t"
-       "jne 2f\n\t"
+       "1:\t" LOCK_PREFIX "btrl $0, %0\n\t"
+       "jnc 2f\n\t"
        ".subsection 1\n\t"
        ".align 16\n"
        "2:\trep; nop\n\t"
        "cmpl $0, %0\n\t"
-       "jg 1b\n\t"
+       "jne 1b\n\t"
        "jmp 2b\n\t"
        ".previous"
        : "=m" (*lock)
--- libc/nptl/sysdeps/i386/i486/bits/atomic.h.jj	2004-05-07 16:11:02.000000000 +0200
+++ libc/nptl/sysdeps/i386/i486/bits/atomic.h	2004-05-10 15:59:13.037114477 +0200
@@ -0,0 +1 @@
+#include "../../../../../sysdeps/i386/i486/bits/atomic.h"
--- libc/nptl/sysdeps/i386/i486/atomic.S.jj	2004-05-10 08:59:55.000000000 +0200
+++ libc/nptl/sysdeps/i386/i486/atomic.S	2004-05-10 08:59:51.000000000 +0200
@@ -0,0 +1 @@
+/* Nothing needed.  */
--- libc/nptl/sysdeps/i386/i486/tls.h.jj	2004-05-07 15:12:52.000000000 +0200
+++ libc/nptl/sysdeps/i386/i486/tls.h	2004-05-10 10:58:22.000000000 +0200
@@ -0,0 +1,54 @@
+/* Copyright (C) 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 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 _TLS_H
+
+/* We can always assume cmpxchg and xadd, no need to check for it.  */
+#define INIT_CMPXCHG
+
+/* Get the full set of definitions.  */
+#include "../tls.h"
+
+/* Additional definitions for <tls.h> on i486 and up.  */
+
+/* Atomic compare and exchange on TLS, returning old value.  */
+#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \
+  ({ __typeof (descr->member) __ret;					      \
+     __typeof (oldval) __old = (oldval);				      \
+     if (sizeof (descr->member) == 4)					      \
+       asm volatile (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3"		      \
+		     : "=a" (__ret)					      \
+		     : "0" (__old), "r" (newval),			      \
+		       "i" (offsetof (struct pthread, member)));	      \
+     else								      \
+       /* Not necessary for other sizes in the moment.  */		      \
+       abort ();							      \
+     __ret; })
+
+
+/* Atomic set bit.  */
+#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
+  (void) ({ if (sizeof ((descr)->member) == 4)				      \
+	      asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0"		      \
+			    :: "i" (offsetof (struct pthread, member)),	      \
+			       "ir" (1 << (bit)));			      \
+	    else							      \
+	      /* Not necessary for other sizes in the moment.  */	      \
+	      abort (); })
+
+#endif	/* tls.h */
--- libc/nptl/sysdeps/i386/i486/pthread_spin_lock.c.jj	2004-05-09 19:09:26.000000000 +0200
+++ libc/nptl/sysdeps/i386/i486/pthread_spin_lock.c	2004-04-13 10:42:53.000000000 +0200
@@ -0,0 +1,49 @@
+/* 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.
+
+   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 "pthreadP.h"
+
+#ifndef LOCK_PREFIX
+# ifdef UP
+#  define LOCK_PREFIX	/* nothing */
+# else
+#  define LOCK_PREFIX	"lock;"
+# endif
+#endif
+
+
+int
+pthread_spin_lock (lock)
+     pthread_spinlock_t *lock;
+{
+  asm ("\n"
+       "1:\t" LOCK_PREFIX "decl %0\n\t"
+       "jne 2f\n\t"
+       ".subsection 1\n\t"
+       ".align 16\n"
+       "2:\trep; nop\n\t"
+       "cmpl $0, %0\n\t"
+       "jg 1b\n\t"
+       "jmp 2b\n\t"
+       ".previous"
+       : "=m" (*lock)
+       : "m" (*lock));
+
+  return 0;
+}
--- libc/nptl/tst-signal2.c.jj	2003-03-17 03:48:28.000000000 +0100
+++ libc/nptl/tst-signal2.c	2004-05-10 12:25:15.000000000 +0200
@@ -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.
 
@@ -100,6 +100,16 @@ receiver (void)
 static int
 do_test (void)
 {
+#if _POSIX_THREAD_PROCESS_SHARED <= 0
+# if !_POSIX_THREAD_PROCESS_SHARED
+  if (sysconf (_SC_THREAD_PROCESS_SHARED) < 0)
+# endif
+    {
+      puts ("_POSIX_THREAD_PROCESS_SHARED not supported, test skipped");
+      return 0;
+    }
+#endif
+
   char tmp[] = "/tmp/tst-signal1-XXXXXX";
 
   int fd = mkstemp (tmp);
--- libc/nptl/tst-cancel16.c.jj	2003-06-16 09:07:53.000000000 +0200
+++ libc/nptl/tst-cancel16.c	2004-05-10 12:24:33.000000000 +0200
@@ -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 Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -63,6 +63,16 @@ tf (void *arg)
 static int
 do_test (void)
 {
+#if _POSIX_THREAD_PROCESS_SHARED <= 0
+# if !_POSIX_THREAD_PROCESS_SHARED
+  if (sysconf (_SC_THREAD_PROCESS_SHARED) < 0)
+# endif
+    {
+      puts ("_POSIX_THREAD_PROCESS_SHARED not supported, test skipped");
+      return 0;
+    }
+#endif
+
   char fname[] = "/tmp/cancel16XXXXXX";
   fd = mkstemp (fname);
   if (fd == -1)
--- libc/nptl/pthread_condattr_setpshared.c.jj	2003-09-03 04:57:24.000000000 +0200
+++ libc/nptl/pthread_condattr_setpshared.c	2004-05-10 11:22:48.000000000 +0200
@@ -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.
 
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <pthreadP.h>
+#include <unistd.h>
 
 int
 pthread_condattr_setpshared (attr, pshared)
@@ -29,6 +30,12 @@ pthread_condattr_setpshared (attr, pshar
       && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0))
     return EINVAL;
 
+#if !_POSIX_THREAD_PROCESS_SHARED
+  if (__builtin_expect (pshared == PTHREAD_PROCESS_SHARED, 0)
+      && sysconf (_SC_THREAD_PROCESS_SHARED) == -1)
+    return ENOSYS;
+#endif
+
   int *valuep = &((struct pthread_condattr *) attr)->value;
 
   *valuep = (*valuep & ~1) | (pshared != PTHREAD_PROCESS_PRIVATE);
--- libc/nptl/sem_init.c.jj	2002-12-16 23:56:03.000000000 +0100
+++ libc/nptl/sem_init.c	2004-05-10 15:09:33.462093115 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -22,6 +22,7 @@
 #include <lowlevellock.h>
 #include <shlib-compat.h>
 #include "semaphoreP.h"
+#include <unistd.h>
 
 
 int
@@ -37,6 +38,15 @@ __new_sem_init (sem, pshared, value)
       return -1;
     }
 
+#if !_POSIX_THREAD_PROCESS_SHARED
+  if (__builtin_expect (pshared != 0, 0)
+      && sysconf (_SC_THREAD_PROCESS_SHARED) == -1)
+    {
+      __set_errno (ENOSYS);
+      return -1;
+    }
+#endif
+
   /* Map to the internal type.  */
   struct sem *isem = (struct sem *) sem;
 
--- libc/nptl/tst-cond12.c.jj	2003-11-21 23:48:57.000000000 +0100
+++ libc/nptl/tst-cond12.c	2004-05-10 12:22:30.000000000 +0200
@@ -61,6 +61,16 @@ prepare (void)
 static int
 do_test (void)
 {
+#if _POSIX_THREAD_PROCESS_SHARED <= 0
+# if !_POSIX_THREAD_PROCESS_SHARED
+  if (sysconf (_SC_THREAD_PROCESS_SHARED) < 0)
+# endif
+    {
+      puts ("_POSIX_THREAD_PROCESS_SHARED not supported, test skipped");
+      return 0;
+    }
+#endif
+
   struct
   {
     pthread_mutex_t m;
--- libc/nptl/pthread_rwlockattr_setpshared.c.jj	2002-11-26 23:49:44.000000000 +0100
+++ libc/nptl/pthread_rwlockattr_setpshared.c	2004-05-10 10:36:00.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include "pthreadP.h"
+#include <unistd.h>
 
 
 int
@@ -32,6 +33,12 @@ pthread_rwlockattr_setpshared (attr, psh
       && __builtin_expect (pshared != PTHREAD_PROCESS_PRIVATE, 0))
     return EINVAL;
 
+#if !_POSIX_THREAD_PROCESS_SHARED
+  if (__builtin_expect (pshared == PTHREAD_PROCESS_SHARED, 0)
+      && sysconf (_SC_THREAD_PROCESS_SHARED) == -1)
+    return ENOSYS;
+#endif
+
   iattr = (struct pthread_rwlockattr *) attr;
 
   iattr->pshared = pshared;
--- libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S.jj	2003-10-03 21:49:23.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S	2004-05-09 20:27:55.000000000 +0200
@@ -1,182 +0,0 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@redhat.com>, 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.  */
-
-#include <unwindbuf.h>
-#include <sysdep.h>
-
-#ifndef UP
-# define LOCK lock
-#else
-# define LOCK
-#endif
-
-#define SYS_futex	240
-#define FUTEX_WAKE	1
-
-	.comm	__fork_generation, 4, 4
-
-	.text
-
-
-	.globl	__pthread_once
-	.type	__pthread_once,@function
-	.align	16
-	cfi_startproc
-__pthread_once:
-	movl	4(%esp), %ecx
-	testl	$2, (%ecx)
-	jz	1f
-	xorl	%eax, %eax
-	ret
-
-1:	pushl	%ebx
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (3, 0)
-	pushl	%esi
-	cfi_adjust_cfa_offset (4)
-	cfi_rel_offset (6, 0)
-	movl	%ecx, %ebx
-	xorl	%esi, %esi
-
-	/* Not yet initialized or initialization in progress.
-	   Get the fork generation counter now.  */
-6:	movl	(%ebx), %eax
-#ifdef PIC
-	call	__i686.get_pc_thunk.cx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
-#endif
-
-5:	movl	%eax, %edx
-
-	testl	$2, %eax
-	jnz	4f
-
-	andl	$3, %edx
-#ifdef PIC
-	orl	__fork_generation@GOTOFF(%ecx), %edx
-#else
-	orl	__fork_generation, %edx
-#endif
-	orl	$1, %edx
-
-	LOCK
-	cmpxchgl %edx, (%ebx)
-	jnz	5b
-
-	/* Check whether another thread already runs the initializer.  */
-	testl	$1, %eax
-	jz	3f	/* No -> do it.  */
-
-	/* Check whether the initializer execution was interrupted
-	   by a fork.  */
-	xorl	%edx, %eax
-	testl	$0xfffffffc, %eax
-	jnz	3f	/* Different for generation -> run initializer.  */
-
-	/* Somebody else got here first.  Wait.  */
-	movl	%esi, %ecx		/* movl $FUTEX_WAIT, %ecx */
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-	jmp	6b
-
-3:	/* Call the initializer function after setting up the
-	   cancellation handler.  Note that it is not possible here
-	   to use the unwind-based cleanup handling.  This would require
-	   that the user-provided function and all the code it calls
-	   is compiled with exceptions.  Unfortunately this cannot be
-	   guaranteed.  */
-	subl	$UNWINDBUFSIZE+8, %esp
-	cfi_adjust_cfa_offset (UNWINDBUFSIZE+8)
-	movl	%ecx, %ebx		/* PIC register value.  */
-
-	leal	8+UWJMPBUF(%esp), %eax
-	movl	$0, 4(%esp)
-	movl	%eax, (%esp)
-	call	__sigsetjmp@PLT
-	testl	%eax, %eax
-	jne	7f
-
-	leal	8(%esp), %eax
-	call	HIDDEN_JUMPTARGET(__pthread_register_cancel)
-
-	/* Call the user-provided initialization function.  */
-	call	*24+UNWINDBUFSIZE(%esp)
-
-	/* Pop the cleanup handler.  */
-	leal	8(%esp), %eax
-	call	HIDDEN_JUMPTARGET(__pthread_unregister_cancel)
-	addl	$UNWINDBUFSIZE+8, %esp
-	cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8)
-
-	/* Sucessful run of the initializer.  Signal that we are done.  */
-	movl	12(%esp), %ebx
-	LOCK
-	addl	$1, (%ebx)
-
-	/* Wake up all other threads.  */
-	movl	$0x7fffffff, %edx
-	movl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-
-4:	popl	%esi
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (6)
-	popl	%ebx
-	cfi_adjust_cfa_offset (-4)
-	cfi_restore (3)
-	xorl	%eax, %eax
-	ret
-
-7:	/* __sigsetjmp returned for the second time.  */
-	movl	20+UNWINDBUFSIZE(%esp), %ebx
-	cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
-	cfi_offset (3, -8)
-	cfi_offset (6, -12)
-	movl	$0, (%ebx)
-
-	movl	$0x7fffffff, %edx
-	movl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	ENTER_KERNEL
-
-	leal	8(%esp), %eax
-	call	HIDDEN_JUMPTARGET (__pthread_unwind_next)
-	/* NOTREACHED */
-	hlt
-	cfi_endproc
-	.size	__pthread_once,.-__pthread_once
-
-	.globl	__pthread_once_internal
-__pthread_once_internal = __pthread_once
-
-	.globl	pthread_once
-pthread_once = __pthread_once
-
-
-#ifdef PIC
-	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
-	.globl	__i686.get_pc_thunk.cx
-	.hidden	__i686.get_pc_thunk.cx
-	.type	__i686.get_pc_thunk.cx,@function
-__i686.get_pc_thunk.cx:
-	movl (%esp), %ecx;
-	ret
-	.size	__i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
-#endif

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]