summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Implies1
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Makefile24
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Versions12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/allocrtsig.c54
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/local_lim.h80
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h144
-rw-r--r--nptl/sysdeps/unix/sysv/linux/configure3
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork-gen.c37
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.c124
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.h60
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h150
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h39
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/createthread.c146
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/fork.c31
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S279
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S180
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S176
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S566
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S311
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S122
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h257
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h101
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S49
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S171
-rw-r--r--nptl/sysdeps/unix/sysv/linux/internaltypes.h130
-rw-r--r--nptl/sysdeps/unix/sysv/linux/jmp-unwind.c33
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pt-fork.c28
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pt-raise.c31
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_kill.c36
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_yield.c30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/raise.c39
-rw-r--r--nptl/sysdeps/unix/sysv/linux/register-atfork.c87
-rw-r--r--nptl/sysdeps/unix/sysv/linux/unregister-atfork.c49
45 files changed, 3820 insertions, 0 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/Implies b/nptl/sysdeps/unix/sysv/linux/Implies
new file mode 100644
index 0000000000..f1b3e8939c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/Implies
@@ -0,0 +1 @@
+pthread
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
new file mode 100644
index 0000000000..efe4ba4e9d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/Makefile
@@ -0,0 +1,24 @@
+# Copyright (C) 2002 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. */
+
+ifeq ($(subdir),nptl)
+sysdep_routines += register-atfork unregister-atfork fork-gen lowlevellock
+
+libpthread-sysdep_routines += pt-fork
+endif
diff --git a/nptl/sysdeps/unix/sysv/linux/Versions b/nptl/sysdeps/unix/sysv/linux/Versions
new file mode 100644
index 0000000000..117598c95f
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/Versions
@@ -0,0 +1,12 @@
+libc {
+ GLIBC_PRIVATE {
+ __register_atfork; __register_pthread_fork_handler;
+ __libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
+ __libc_allocate_rtsig_private;
+ }
+}
+libpthread {
+ GLIBC_2.0 {
+ fork; __fork;
+ }
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
new file mode 100644
index 0000000000..5badaea9ec
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2002 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 <signal.h>
+
+
+static int current_rtmin = __SIGRTMIN + 1;
+static int current_rtmax = __SIGRTMAX;
+
+
+/* We reserve __SIGRTMIN for use as the cancelation signal. This
+ signal is used internally. */
+int
+__libc_current_sigrtmin (void)
+{
+ return current_rtmin;
+}
+strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private)
+
+
+int
+__libc_current_sigrtmax (void)
+{
+ return current_rtmax;
+}
+strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private)
+
+
+int
+__libc_allocate_rtsig (int high)
+{
+ if (current_rtmin == -1 || current_rtmin > current_rtmax)
+ /* We don't have anymore signal available. */
+ return -1;
+
+ return high ? current_rtmin++ : current_rtmax--;
+}
+strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private)
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
new file mode 100644
index 0000000000..63de09a1b0
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h
@@ -0,0 +1,80 @@
+/* Minimum guaranteed maximum values for system limits. Linux version.
+ Copyright (C) 1993,94,95,96,97,98,2000,2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* The kernel header pollutes the namespace with the NR_OPEN symbol
+ and defines LINK_MAX although filesystems have different maxima. A
+ similar thing is true for OPEN_MAX: the limit can be changed at
+ runtime and therefore the macro must not be defined. Remove this
+ after including the header if necessary. */
+#ifndef NR_OPEN
+# define __undef_NR_OPEN
+#endif
+#ifndef LINK_MAX
+# define __undef_LINK_MAX
+#endif
+#ifndef OPEN_MAX
+# define __undef_OPEN_MAX
+#endif
+
+/* The kernel sources contain a file with all the needed information. */
+#include <linux/limits.h>
+
+/* Have to remove NR_OPEN? */
+#ifdef __undef_NR_OPEN
+# undef NR_OPEN
+# undef __undef_NR_OPEN
+#endif
+/* Have to remove LINK_MAX? */
+#ifdef __undef_LINK_MAX
+# undef LINK_MAX
+# undef __undef_LINK_MAX
+#endif
+/* Have to remove OPEN_MAX? */
+#ifdef __undef_OPEN_MAX
+# undef OPEN_MAX
+# undef __undef_OPEN_MAX
+#endif
+
+/* The number of data keys per process. */
+#define _POSIX_THREAD_KEYS_MAX 128
+/* This is the value this implementation supports. */
+#define PTHREAD_KEYS_MAX 1024
+
+/* Controlling the iterations of destructors for thread-specific data. */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+/* Number of iterations this implementation does. */
+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+/* The number of threads per process. */
+#define _POSIX_THREAD_THREADS_MAX 64
+/* This is the value this implementation supports. */
+#define PTHREAD_THREADS_MAX 1024
+
+/* Maximum amount by which a process can descrease its asynchronous I/O
+ priority level. */
+#define AIO_PRIO_DELTA_MAX 20
+
+/* Minimum size for a thread. We are free to choose a reasonable value. */
+#define PTHREAD_STACK_MIN 16384
+
+/* Maximum number of POSIX timers available. */
+#define TIMER_MAX 256
+
+/* Maximum number of timer expiration overruns. */
+#define DELAYTIMER_MAX 2147483647
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
new file mode 100644
index 0000000000..8274f516be
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
@@ -0,0 +1,144 @@
+/* Define POSIX options for Linux.
+ Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#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
+
+/* Implementation supports `poll' function. */
+#define _POSIX_POLL 1
+
+/* Implementation supports `select' and `pselect' functions. */
+#define _POSIX_SELECT 1
+
+/* 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
+
+/* X/Open realtime thread support is available. */
+#define _XOPEN_REALTIME_THREADS 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, but only the non-shared form for now. */
+#define _POSIX_SEMAPHORES 1
+
+/* Real-time signals are supported. */
+#define _POSIX_REALTIME_SIGNALS 1
+
+/* We support asynchronous I/O. */
+#define _POSIX_ASYNCHRONOUS_IO 1
+#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
+
+/* 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 1
+
+/* The barrier functions are available. */
+#define _POSIX_BARRIERS 200112L
+
+/* POSIX message queues are not yet supported. */
+#undef _POSIX_MESSAGE_PASSING
+
+/* Thread process-shared synchronization is supported. */
+#define _POSIX_THREAD_PROCESS_SHARED 200112L
+
+#endif /* posix_opt.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/configure b/nptl/sysdeps/unix/sysv/linux/configure
new file mode 100644
index 0000000000..229414dd74
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/configure
@@ -0,0 +1,3 @@
+# Local configure fragment for sysdeps/unix/sysv/linux.
+
+DEFINES="$DEFINES -D_LIBC_REENTRANT"
diff --git a/nptl/sysdeps/unix/sysv/linux/fork-gen.c b/nptl/sysdeps/unix/sysv/linux/fork-gen.c
new file mode 100644
index 0000000000..ff00261404
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/fork-gen.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002 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 <list.h>
+#include "fork.h"
+
+
+static struct fork_handler pthread_child_handler;
+
+
+void
+__register_pthread_fork_handler (ptr, reclaim)
+ unsigned long int *ptr;
+ void (*reclaim) (void);
+{
+ __fork_generation_pointer = ptr;
+
+ pthread_child_handler.handler = reclaim;
+
+ list_add_tail (&pthread_child_handler.list, &__fork_child_list);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c
new file mode 100644
index 0000000000..c1aa23c5c5
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/fork.c
@@ -0,0 +1,124 @@
+/* Copyright (C) 2002 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sysdep.h>
+#include <libio/libioP.h>
+#include <tls.h>
+#include "fork.h"
+
+
+unsigned long int *__fork_generation_pointer;
+
+
+lll_lock_t __fork_lock = LLL_LOCK_INITIALIZER;
+LIST_HEAD (__fork_prepare_list);
+LIST_HEAD (__fork_parent_list);
+LIST_HEAD (__fork_child_list);
+
+
+static void
+fresetlockfiles (void)
+{
+ _IO_ITER i;
+
+ for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
+ *((pthread_mutex_t *) _IO_iter_file(i)->_lock)
+ = (pthread_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+}
+
+
+pid_t
+__libc_fork (void)
+{
+ pid_t pid;
+ list_t *runp;
+
+ /* Get the lock so that the set of registered handlers is not
+ inconsistent or changes beneath us. */
+ lll_lock (__fork_lock);
+
+ /* Run all the registered preparation handlers. In reverse order. */
+ list_for_each_prev (runp, &__fork_prepare_list)
+ {
+ struct fork_handler *curp;
+
+ curp = list_entry (runp, struct fork_handler, list);
+
+ curp->handler ();
+ }
+
+ _IO_list_lock ();
+
+#ifdef ARCH_FORK
+ pid = ARCH_FORK ();
+#else
+# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used"
+ pid = INLINE_SYSCALL (fork, 0);
+#endif
+
+ if (pid == 0)
+ {
+ if (__fork_generation_pointer != NULL)
+ *__fork_generation_pointer += 4;
+
+ /* Reset the file list. These are recursive mutexes. */
+ fresetlockfiles ();
+
+ /* We execute this even if the 'fork' call failed. */
+ _IO_list_resetlock ();
+
+ /* Run the handlers registered for the child. */
+ list_for_each (runp, &__fork_child_list)
+ {
+ struct fork_handler *curp;
+
+ curp = list_entry (runp, struct fork_handler, list);
+
+ curp->handler ();
+ }
+
+ /* Initialize the fork lock. */
+ __fork_lock = (lll_lock_t) LLL_LOCK_INITIALIZER;
+ }
+ else
+ {
+ /* We execute this even if the 'fork' call failed. */
+ _IO_list_unlock ();
+
+ /* Run the handlers registered for the parent. */
+ list_for_each (runp, &__fork_parent_list)
+ {
+ struct fork_handler *curp;
+
+ curp = list_entry (runp, struct fork_handler, list);
+
+ curp->handler ();
+ }
+
+ /* Release the for lock. */
+ lll_unlock (__fork_lock);
+ }
+
+ return pid;
+}
+weak_alias (__libc_fork, __fork)
+weak_alias (__libc_fork, fork)
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.h b/nptl/sysdeps/unix/sysv/linux/fork.h
new file mode 100644
index 0000000000..85722a59eb
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/fork.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2002 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 <list.h>
+#include <lowlevellock.h>
+
+/* The fork generation counter, defined in libpthread. */
+extern unsigned long int __fork_generation attribute_hidden;
+
+/* Pointer to the fork generation counter in the thread library. */
+extern unsigned long int *__fork_generation_pointer attribute_hidden;
+
+/* Lock to protect handling of fork handlers. */
+extern lll_lock_t __fork_lock attribute_hidden;
+
+/* Lists of registered fork handlers. */
+extern list_t __fork_prepare_list attribute_hidden;
+extern list_t __fork_parent_list attribute_hidden;
+extern list_t __fork_child_list attribute_hidden;
+
+
+/* Elements of the fork handler lists. */
+struct fork_handler
+{
+ list_t list;
+ void (*handler) (void);
+ void *dso_handle;
+};
+
+
+/* Function to call to unregister fork handlers. */
+extern void __unregister_atfork (void *dso_handle) attribute_hidden;
+#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle)
+
+
+/* C library side function to register new fork handlers. */
+extern int __register_atfork (void (*__prepare) (void),
+ void (*__parent) (void),
+ void (*__child) (void),
+ void *dso_handle);
+
+/* Register the generation counter in the libpthread with the libc. */
+extern void __register_pthread_fork_handler (unsigned long int *__ptr,
+ void (*reclaim) (void));
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
new file mode 100644
index 0000000000..2167bbb988
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h
@@ -0,0 +1,150 @@
+/* Copyright (C) 2002 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 _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H 1
+
+#define __SIZEOF_PTHREAD_ATTR_T 36
+#define __SIZEOF_PTHREAD_MUTEX_T 24
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 12
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCK_T 32
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 20
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+
+/* Thread identifiers. The structure of the attribute type is not
+ exposed on purpose. */
+typedef unsigned long int pthread_t;
+
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_ATTR_T];
+ long int __align;
+} pthread_attr_t;
+
+
+/* Data structures for mutex handling. The structure of the attribute
+ type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __count;
+ struct pthread *__owner;
+ /* KIND must stay at this position in the structure to maintain
+ binary compatibility. */
+ int __kind;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
+ long int __align;
+} pthread_mutex_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+ long int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling. The structure of
+ the attribute type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __nr_wakers;
+ unsigned int __nr_sleepers;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_COND_T];
+ long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+ long int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#ifdef __USE_UNIX98
+/* Data structure for read-write lock variable handling. The
+ structure of the attribute type is not exposed on purpose. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __nr_readers;
+ unsigned int __readers_wakeup;
+ unsigned int __writer_wakeup;
+ unsigned int __nr_readers_queued;
+ unsigned int __nr_writers_queued;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned int __flags;
+ pthread_t __writer;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+ long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+ long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type. */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type. The structure of the type is
+ deliberately not exposed. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIER_T];
+ long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+ int __align;
+} pthread_barrierattr_t;
+#endif
+
+
+#endif /* bits/pthreadtypes.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h
new file mode 100644
index 0000000000..ab46ac099b
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002 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 _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+
+#define __SIZEOF_SEM_T 16
+
+
+/* Value returned if `sem_open' failed. */
+#define SEM_FAILED ((sem_t *) 0)
+
+/* Maximum value the semaphore can have. */
+#define SEM_VALUE_MAX ((int) ((~0u) >> 1))
+
+
+typedef union
+{
+ char __size[__SIZEOF_SEM_T];
+ long int __align;
+} sem_t;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/createthread.c b/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
new file mode 100644
index 0000000000..3196a8c754
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
@@ -0,0 +1,146 @@
+/* Copyright (C) 2002 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 <sched.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <atomic.h>
+#include <ldsodefs.h>
+#include <tls.h>
+
+
+#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
+
+
+static int
+create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
+{
+ union user_desc_init desc;
+
+ /* Describe the thread-local storage segment. */
+
+ /* The 'entry_number' field. The first three bits of the segment
+ register value select the GDT, ignore them. We get the index
+ from the value of the %gs register in the current thread. */
+ desc.vals[0] = TLS_GET_GS () >> 3;
+ /* The 'base_addr' field. Pointer to the TCB. */
+ desc.vals[1] = (unsigned long int) pd;
+ /* The 'limit' field. We use 4GB which is 0xfffff pages. */
+ desc.vals[2] = 0xfffff;
+ /* Collapsed value of the bitfield:
+ .seg_32bit = 1
+ .contents = 0
+ .read_exec_only = 0
+ .limit_in_pages = 1
+ .seg_not_present = 0
+ .useable = 1 */
+ desc.vals[3] = 0x51;
+
+
+ assert (pd->header.data.tcb != NULL);
+
+
+ if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
+ {
+ /* The parent thread is supposed to report events. Check whether
+ the TD_CREATE event is needed, too. */
+ const int _idx = __td_eventword (TD_CREATE);
+ const uint32_t _mask = __td_eventmask (TD_CREATE);
+
+ if ((_mask & (__nptl_threads_events.event_bits[_idx]
+ | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
+ {
+ /* We have to report the new thread. Make sure the thread
+ does not run far by forcing it to get a lock. We lock it
+ here too so that the new thread cannot continue until we
+ tell it to. */
+ lll_lock (pd->lock);
+
+ /* Create the thread. */
+ if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+ CLONE_SETTLS | CLONE_PARENT_SETTID |
+ CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
+ pd, &pd->tid, &desc.desc, &pd->tid) == -1)
+ /* Failed. */
+ return errno;
+
+ /* Now fill in the information about the new thread in
+ the newly created thread's data structure. We cannot let
+ the new thread do this since we don't know whether it was
+ already scheduled when we send the event. */
+ pd->eventbuf.eventnum = TD_CREATE;
+ pd->eventbuf.eventdata = pd;
+
+ /* Enqueue the descriptor. */
+ do
+ pd->nextevent = __nptl_last_event;
+ while (atomic_compare_and_exchange_acq (__nptl_last_event, pd,
+ pd->nextevent) != 0);
+
+ /* Now call the function which signals the event. */
+ __nptl_create_event ();
+
+ /* And finally restart the new thread. */
+ lll_unlock (pd->lock);
+
+ return 0;
+ }
+ }
+
+ /* We rely heavily on various flags the CLONE function understands:
+
+ CLONE_VM, CLONE_FS, CLONE_FILES
+ These flags select semantics with shared address space and
+ file descriptors according to what POSIX requires.
+
+ CLONE_SIGNAL
+ This flag selects the POSIX signal semantics.
+
+ CLONE_SETTLS
+ The sixth parameter to CLONE determines the TLS area for the
+ new thread.
+
+ CLONE_PARENT_SETTID
+ The kernels writes the thread ID of the newly created thread
+ into the location pointed to by the fifth parameters to CLONE.
+
+ Note that it would be semantically equivalent to use
+ CLONE_CHILD_SETTID but it is be more expensive in the kernel.
+
+ CLONE_CHILD_CLEARTID
+ The kernels clears the thread ID of a thread that has called
+ sys_exit() - using the same parameter as CLONE_SETTID.
+
+ CLONE_DETACHED
+ No signal is generated if the thread exists and it is
+ automatically reaped.
+
+ The termination signal is chosen to be zero which means no signal
+ is sent. */
+ if (__clone (start_thread, STACK_VARIABLES_ARGS,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+ CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+ CLONE_DETACHED | 0, pd, &pd->tid, &desc.desc, &pd->tid) == -1)
+ /* Failed. */
+ return errno;
+
+ return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/fork.c b/nptl/sysdeps/unix/sysv/linux/i386/fork.c
new file mode 100644
index 0000000000..813e5299a6
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/fork.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2002 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 <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK() \
+ INLINE_SYSCALL (clone, 5, \
+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \
+ NULL, NULL, &THREAD_SELF->tid)
+
+#include "../fork.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S
new file mode 100644
index 0000000000..9e2b9fec8d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S
@@ -0,0 +1,279 @@
+/* Copyright (C) 2002 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 <sysdep.h>
+
+ .text
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK lock
+#endif
+
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_futex 240
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#define EWOULDBLOCK 11
+#define EINVAL 22
+#define ETIMEDOUT 110
+
+#define cond_lock 0
+#define cond_nr_wakers 4
+#define cond_nr_sleepers 8
+
+
+ .global __lll_cond_wait
+ .type __lll_cond_wait,@function
+ .hidden __lll_cond_wait
+ .align 16
+__lll_cond_wait:
+ pushl %esi
+ pushl %ebx
+
+ xorl %esi, %esi
+
+ leal cond_nr_wakers(%eax), %ebx
+
+4: movl (%ebx), %edx
+ testl %edx, %edx
+ jne 1f
+
+ LOCK
+ decl cond_lock-cond_nr_wakers(%ebx)
+ jne 2f
+
+3: xorl %ecx, %ecx
+ movl $SYS_futex, %eax
+ int $0x80
+
+ movl $1, %eax
+ LOCK
+ xaddl %eax, cond_lock-cond_nr_wakers(%ebx)
+ testl %eax, %eax
+ je 4b
+
+ leal cond_lock-cond_nr_wakers(%ebx), %ecx
+ /* Preserves %ebx, %edx, %edi, %esi. */
+ call __lll_mutex_lock_wait
+ jmp 4b
+
+1: decl (%ebx)
+
+ popl %ebx
+ popl %esi
+ ret
+
+2: leal cond_lock-cond_nr_wakers(%ebx), %eax
+ /* Preserves %ebx, %ecx, %edx, %edi, %esi. */
+ call __lll_mutex_unlock_wake
+ jmp 3b
+ .size __lll_cond_wait,.-__lll_cond_wait
+
+
+ .global __lll_cond_timedwait
+ .type __lll_cond_timedwait,@function
+ .hidden __lll_cond_timedwait
+ .align 16
+__lll_cond_timedwait:
+ /* Check for a valid timeout value. */
+ cmpl $1000000000, 4(%edx)
+ jae 1f
+
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ /* Stack frame for the timespec and timeval structs. */
+ subl $8, %esp
+
+ leal cond_nr_wakers(%eax), %ebp /* cond */
+ movl %edx, %edi /* timeout */
+
+9: movl (%ebp), %esi
+ testl %esi, %esi
+ jne 5f
+
+ LOCK
+ decl cond_lock-cond_nr_wakers(%ebp)
+ jne 6f
+
+ /* Get current time. */
+7: movl %esp, %ebx
+ xorl %ecx, %ecx
+ movl $SYS_gettimeofday, %eax
+ int $0x80
+
+ /* Compute relative timeout. */
+ movl 4(%esp), %eax
+ movl $1000, %edx
+ mul %edx /* Milli seconds to nano seconds. */
+ movl (%edi), %ecx
+ movl 4(%edi), %edx
+ subl (%esp), %ecx
+ subl %eax, %edx
+ jns 3f
+ addl $1000000000, %edx
+ decl %ecx
+3: testl %ecx, %ecx
+ js 4f /* Time is already up. */
+
+ movl %ecx, (%esp) /* Store relative timeout. */
+ movl %edx, 4(%esp)
+ movl %esi, %edx
+ movl %esp, %esi
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl %ebp, %ebx
+ movl $SYS_futex, %eax
+ int $0x80
+
+ movl %eax, %edx
+
+ movl $1, %eax
+ LOCK
+ xaddl %eax, cond_lock-cond_nr_wakers(%ebp)
+ testl %eax, %eax
+ jne 8f
+
+ cmpl $-ETIMEDOUT, %edx
+ jne 9b
+
+4: movl $ETIMEDOUT, %eax
+ jmp 2f
+
+5: decl (%ebp)
+ xorl %eax, %eax
+
+2: addl $8, %esp
+ popl %ebx
+ popl %esi
+ popl %edi
+ popl %ebp
+ ret
+
+6: leal cond_lock-cond_nr_wakers(%ebp), %eax
+ /* Preserves %ebx, %ecx, %edx, %edi, %esi. */
+ call __lll_mutex_unlock_wake
+ jmp 7b
+
+8: leal cond_lock-cond_nr_wakers(%ebp), %ecx
+ /* Preserves %ebx, %edx, %edi, %esi. */
+ call __lll_mutex_lock_wait
+ jmp 5b
+
+1: movl $EINVAL, %eax
+ ret
+ .size __lll_cond_timedwait,.-__lll_cond_timedwait
+
+
+ .global __lll_cond_wake
+ .type __lll_cond_wake,@function
+ .hidden __lll_cond_wake
+ .align 16
+__lll_cond_wake:
+ pushl %esi
+ pushl %ebx
+
+ movl %eax, %ebx
+
+ movl $1, %eax
+ LOCK
+ xaddl %eax, (%ebx)
+ testl %eax, %eax
+ jne 1f
+
+2: leal cond_nr_wakers(%ebx), %ebx
+ cmpl $0, cond_nr_sleepers-cond_nr_wakers(%ebx)
+ je 3f
+
+ incl (%ebx)
+ jz 5f
+
+6: movl $FUTEX_WAKE, %ecx
+ xorl %esi, %esi
+ movl %ecx, %edx /* movl $1, %edx */
+ movl $SYS_futex, %eax
+ int $0x80
+
+3: LOCK
+ decl cond_lock-cond_nr_wakers(%ebx)
+ je,pt 4f
+
+ leal cond_lock-cond_nr_wakers(%ebx), %eax
+ call __lll_mutex_unlock_wake
+
+4: popl %ebx
+ popl %esi
+ ret
+
+1: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+
+5: movl $0x80000000, (%ebx)
+ jmp 6b
+ .size __lll_cond_wake,.-__lll_cond_wake
+
+
+ .global __lll_cond_broadcast
+ .type __lll_cond_broadcast,@function
+ .hidden __lll_cond_broadcast
+ .align 16
+__lll_cond_broadcast:
+ pushl %esi
+ pushl %ebx
+
+ movl %eax, %ebx
+ movl $0x8000000, %edx
+
+ movl $1, %eax
+ LOCK
+ xaddl %eax, (%ebx)
+ testl %eax, %eax
+ jne 1f
+
+2: leal cond_nr_wakers(%ebx), %ebx
+ cmpl $0, cond_nr_sleepers-cond_nr_wakers(%ebx)
+ je 3f
+
+ orl %edx, (%ebx)
+
+6: movl $FUTEX_WAKE, %ecx
+ xorl %esi, %esi
+ movl $SYS_futex, %eax
+ int $0x80
+
+3: LOCK
+ decl cond_lock-cond_nr_wakers(%ebx)
+ je,pt 4f
+
+ leal cond_lock-cond_nr_wakers(%ebx), %eax
+ call __lll_mutex_unlock_wake
+
+4: popl %ebx
+ popl %esi
+ ret
+
+1: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+ .size __lll_cond_broadcast,.-__lll_cond_broadcast
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
new file mode 100644
index 0000000000..400413d7c2
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
@@ -0,0 +1,180 @@
+/* Copyright (C) 2002 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 <sysdep.h>
+
+ .text
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK lock
+#endif
+
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_futex 240
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#define ETIMEDOUT 110
+
+
+ .globl __lll_lock_wait
+ .type __lll_lock_wait,@function
+ .hidden __lll_lock_wait
+ .align 16
+__lll_lock_wait:
+ pushl %esi
+ pushl %ebx
+ pushl %edx
+
+ movl %ecx, %ebx
+ xorl %esi, %esi /* No timeout. */
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+1:
+ leal -1(%eax), %edx /* account for the preceeded xadd. */
+ movl $SYS_futex, %eax
+ int $0x80
+
+ orl $-1, %eax /* Load -1. */
+ LOCK
+ xaddl %eax, (%ebx)
+ jne 1b
+
+ movl $-1, (%ebx)
+
+ popl %edx
+ popl %ebx
+ popl %esi
+ ret
+ .size __lll_lock_wait,.-__lll_lock_wait
+
+
+ .globl lll_unlock_wake_cb
+ .type lll_unlock_wake_cb,@function
+ .hidden lll_unlock_wake_cb
+ .align 16
+lll_unlock_wake_cb:
+ pushl %esi
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+
+ movl 20(%esp), %ebx
+ LOCK
+ incl (%ebx)
+ jng 1f
+
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %esi
+ ret
+ .size lll_unlock_wake_cb,.-lll_unlock_wake_cb
+
+
+ .globl __lll_unlock_wake
+ .type __lll_unlock_wake,@function
+ .hidden __lll_unlock_wake
+__lll_unlock_wake:
+ pushl %esi
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+
+ movl %eax, %ebx
+1: movl $FUTEX_WAKE, %ecx
+ movl $1, %edx /* Wake one thread. */
+ xorl %esi, %esi
+ movl %edx, (%ebx) /* Stores '$1'. */
+ movl $SYS_futex, %eax
+ int $0x80
+
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %esi
+ ret
+ .size __lll_unlock_wake,.-__lll_unlock_wake
+
+
+ .globl __lll_timedwait_tid
+ .type __lll_timedwait_tid,@function
+ .hidden __lll_timedwait_tid
+__lll_timedwait_tid:
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ movl %eax, %ebp
+ movl %edx, %edi
+ subl $8, %esp
+
+ /* Get current time. */
+2: movl %esp, %ebx
+ xorl %ecx, %ecx
+ movl $SYS_gettimeofday, %eax
+ int $0x80
+
+ /* Compute relative timeout. */
+ movl 4(%esp), %eax
+ movl $1000, %edx
+ mul %edx /* Milli seconds to nano seconds. */
+ movl (%edi), %ecx
+ movl 4(%edi), %edx
+ subl (%esp), %ecx
+ subl %eax, %edx
+ jns 5f
+ addl $1000000000, %edx
+ decl %ecx
+5: testl %ecx, %ecx
+ js 6f /* Time is already up. */
+
+ movl %ecx, (%esp) /* Store relative timeout. */
+ movl %edx, 4(%esp)
+
+ movl (%ebp), %edx
+ testl %edx, %edx
+ jz 4f
+
+ movl %esp, %esi
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl %ebp, %ebx
+ movl $SYS_futex, %eax
+ int $0x80
+
+ movl %eax, %edx
+
+ cmpl $0, (%ebx)
+ jne 1f
+4: xorl %eax, %eax
+
+3: addl $8, %esp
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+1: cmpl $-ETIMEDOUT, %edx
+ jne 2b
+6: movl $ETIMEDOUT, %eax
+ jmp 3b
+ .size __lll_timedwait_tid,.-__lll_timedwait_tid
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S
new file mode 100644
index 0000000000..a48cd88fa8
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S
@@ -0,0 +1,176 @@
+/* Copyright (C) 2002 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 <sysdep.h>
+
+ .text
+
+#ifdef UP
+# define LOCK
+#else
+# define LOCK lock
+#endif
+
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_futex 240
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#define EWOULDBLOCK 11
+#define EINVAL 22
+#define ETIMEDOUT 110
+
+
+ .globl __lll_mutex_lock_wait
+ .type __lll_mutex_lock_wait,@function
+ .hidden __lll_mutex_lock_wait
+ .align 16
+__lll_mutex_lock_wait:
+ pushl %esi
+ pushl %ebx
+ pushl %edx
+
+ movl %ecx, %ebx
+ xorl %esi, %esi /* No timeout. */
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+1:
+ leal 1(%eax), %edx /* account for the preceeded xadd. */
+ movl $SYS_futex, %eax
+ int $0x80
+
+ movl $1, %eax
+ LOCK
+ xaddl %eax, (%ebx)
+ testl %eax, %eax
+ jne 1b
+
+ movl $2, (%ebx)
+
+ popl %edx
+ popl %ebx
+ popl %esi
+ ret
+ .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
+
+
+ .globl __lll_mutex_timedlock_wait
+ .type __lll_mutex_timedlock_wait,@function
+ .hidden __lll_mutex_timedlock_wait
+ .align 16
+__lll_mutex_timedlock_wait:
+ /* Check for a valid timeout value. */
+ cmpl $1000000000, 4(%edx)
+ jae 3f
+
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ /* Stack frame for the timespec and timeval structs. */
+ subl $8, %esp
+
+ movl %ecx, %ebp
+ movl %edx, %edi
+ leal 1(%eax), %esi
+
+ /* Get current time. */
+1:
+ movl %esp, %ebx
+ xorl %ecx, %ecx
+ movl $SYS_gettimeofday, %eax
+ int $0x80
+
+ /* Compute relative timeout. */
+ movl 4(%esp), %eax
+ movl $1000, %edx
+ mul %edx /* Milli seconds to nano seconds. */
+ movl (%edi), %ecx
+ movl 4(%edi), %edx
+ subl (%esp), %ecx
+ subl %eax, %edx
+ jns 4f
+ addl $1000000000, %edx
+ decl %ecx
+4: testl %ecx, %ecx
+ js 5f /* Time is already up. */
+
+ /* Futex call. */
+ movl %ecx, (%esp) /* Store relative timeout. */
+ movl %edx, 4(%esp)
+ movl %esi, %edx
+ movl %esp, %esi
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl %ebp, %ebx
+ movl $SYS_futex, %eax
+ int $0x80
+
+ movl $1, %esi
+ LOCK
+ xaddl %esi, (%ebx)
+ testl %esi, %esi
+ jne 7f
+
+ movl $2, (%ebx)
+ xorl %eax, %eax
+
+6: addl $8, %esp
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+ /* Check whether the time expired. */
+7: cmpl $-ETIMEDOUT, %eax
+ je 5f
+ jmp 1b
+
+3: movl $EINVAL, %eax
+ ret
+
+5: movl $ETIMEDOUT, %eax
+ jmp 6b
+ .size __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
+
+
+ .globl __lll_mutex_unlock_wake
+ .type __lll_mutex_unlock_wake,@function
+ .hidden __lll_mutex_unlock_wake
+ .align 16
+__lll_mutex_unlock_wake:
+ pushl %esi
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+
+ movl $FUTEX_WAKE, %ecx
+ movl %eax, %ebx
+ xorl %esi, %esi
+ movl $0, (%ebx)
+ movl $1, %edx /* Wake one thread. */
+ movl $SYS_futex, %eax
+ int $0x80
+
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %esi
+ ret
+ .size __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S
new file mode 100644
index 0000000000..2dde246d1f
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S
@@ -0,0 +1,566 @@
+/* Copyright (C) 2002 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 <sysdep.h>
+
+ .text
+
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_futex 240
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#define EAGAIN 11
+#define EDEADLK 35
+#define ETIMEDOUT 110
+
+/* Offsets in the pthread_rwlock_t structure. */
+#define MUTEX 0
+#define NR_READERS 4
+#define READERS_WAKEUP 8
+#define WRITERS_WAKEUP 12
+#define READERS_QUEUED 16
+#define WRITERS_QUEUED 20
+#define FLAGS 24
+#define WRITER 28
+
+#ifndef UP
+# define LOCK lock
+#else
+# define LOCK
+#endif
+
+
+ .globl __pthread_rwlock_rdlock
+ .type __pthread_rwlock_rdlock,@function
+ .align 16
+__pthread_rwlock_rdlock:
+ pushl %esi
+ pushl %ebx
+
+ xorl %esi, %esi
+ xorl %edx, %edx
+ movl 12(%esp), %ebx
+
+ /* Get the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebx)
+ testl %eax, %eax
+ jne 1f
+
+2: movl WRITER(%ebx), %eax
+ testl %eax, %eax
+ jne 14f
+ cmp $0, WRITERS_QUEUED(%ebx)
+ je 5f
+ cmpl $0, FLAGS(%ebx)
+ je 5f
+
+3: incl READERS_QUEUED(%ebx)
+ je 4f
+
+ LOCK
+ decl MUTEX(%ebx)
+ jne 10f
+
+11: addl $READERS_WAKEUP-MUTEX, %ebx
+ movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl $SYS_futex, %eax
+ int $0x80
+
+ subl $READERS_WAKEUP-MUTEX, %ebx
+
+ /* Reget the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebx)
+ testl %eax, %eax
+ jne 12f
+
+13: decl READERS_QUEUED(%ebx)
+ jne 2b
+ movl $0, READERS_WAKEUP(%ebx)
+ jmp 2b
+
+5: xorl %ecx, %ecx
+ incl NR_READERS(%ebx)
+ je 8f
+9: LOCK
+ decl MUTEX(%ebx)
+ jne 6f
+7:
+
+ movl %ecx, %eax
+ popl %ebx
+ popl %esi
+ ret
+
+1: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+
+14: cmpl %gs:8, %eax
+ jne 3b
+ /* Deadlock detected. */
+ movl $EDEADLK, %ecx
+ jmp 9b
+
+6: movl %ebx, %eax
+ call __lll_mutex_unlock_wake
+ jmp 7b
+
+ /* Overflow. */
+8: decl NR_READERS(%ebx)
+ movl $EAGAIN, %ecx
+ jmp 9b
+
+ /* Overflow. */
+4: decl READERS_QUEUED(%ebx)
+ movl $EAGAIN, %ecx
+ jmp 9b
+
+10: movl %ebx, %eax
+ call __lll_mutex_unlock_wake
+ jmp 11b
+
+12: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 13b
+ .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
+
+ .globl pthread_rwlock_rdlock
+pthread_rwlock_rdlock = __pthread_rwlock_rdlock
+
+
+ .globl pthread_rwlock_timedrdlock
+ .type pthread_rwlock_timedrdlock,@function
+ .align 16
+pthread_rwlock_timedrdlock:
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ pushl %ebp
+ subl $8, %esp
+
+ movl 28(%esp), %ebp
+ movl 32(%esp), %edi
+
+ /* Get the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebp)
+ testl %eax, %eax
+ jne 1f
+
+2: movl WRITER(%ebp), %eax
+ testl %eax, %eax
+ jne 14f
+ cmp $0, WRITERS_QUEUED(%ebp)
+ je 5f
+ cmpl $0, FLAGS(%ebp)
+ je 5f
+
+3: incl READERS_QUEUED(%ebp)
+ je 4f
+
+ LOCK
+ decl MUTEX(%ebp)
+ jne 10f
+
+ /* Get current time. */
+ movl %esp, %ebx
+ xorl %ecx, %ecx
+ movl $SYS_gettimeofday, %eax
+ int $0x80
+
+ /* Compute relative timeout. */
+ movl 4(%esp), %eax
+ movl $1000, %edx
+ mul %edx /* Milli seconds to nano seconds. */
+ movl (%edi), %ecx
+ movl 4(%edi), %edx
+ subl (%esp), %ecx
+ subl %eax, %edx
+ jns 15f
+ addl $1000000000, %edx
+ decl %ecx
+15: testl %ecx, %ecx
+ js 16f /* Time is already up. */
+
+ /* Futex call. */
+ movl %ecx, (%esp) /* Store relative timeout. */
+ movl %edx, 4(%esp)
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl %esp, %esi
+ movl %ecx, %edx
+ leal READERS_WAKEUP(%ebp), %ebx
+ movl $SYS_futex, %eax
+ int $0x80
+ movl %eax, %edx
+17:
+
+ /* Reget the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebp)
+ testl %eax, %eax
+ jne 12f
+
+13: cmpl $-ETIMEDOUT, %ecx
+ je 18f
+ decl READERS_QUEUED(%ebp)
+ jne 2b
+ movl $0, READERS_WAKEUP(%ebp)
+ jmp 2b
+
+
+5: xorl %ecx, %ecx
+ incl NR_READERS(%ebp)
+ je 8f
+9: LOCK
+ decl MUTEX(%ebp)
+ jne 6f
+
+7: movl %ecx, %eax
+
+ addl $8, %esp
+ popl %ebp
+ popl %ebx
+ popl %edi
+ popl %esi
+ ret
+
+1: movl %ebp, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+
+14: cmpl %gs:8, %eax
+ jne 3b
+ movl $EDEADLK, %ecx
+ jmp 9b
+
+6: movl %ebp, %eax
+ call __lll_mutex_unlock_wake
+ jmp 7b
+
+ /* Overflow. */
+8: decl NR_READERS(%ebp)
+ movl $EAGAIN, %ecx
+ jmp 9b
+
+ /* Overflow. */
+4: decl READERS_QUEUED(%ebp)
+ movl $EAGAIN, %ecx
+ jmp 9b
+
+10: movl %ebp, %eax
+ call __lll_mutex_unlock_wake
+ jmp 11b
+
+12: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 13b
+
+16: movl $-ETIMEDOUT, %ecx
+ jmp 17b
+
+18: movl $ETIMEDOUT, %ecx
+ jmp 9b
+ .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock
+
+
+ .globl __pthread_rwlock_wrlock
+ .type __pthread_rwlock_wrlock,@function
+ .align 16
+__pthread_rwlock_wrlock:
+ pushl %esi
+ pushl %ebx
+
+ xorl %esi, %esi
+ xorl %edx, %edx
+ movl 12(%esp), %ebx
+
+ /* Get the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebx)
+ testl %eax, %eax
+ jne 1f
+
+2: movl WRITER(%ebx), %eax
+ testl %eax, %eax
+ jne 14f
+ cmp $0, NR_READERS(%ebx)
+ je 5f
+
+3: incl WRITERS_QUEUED(%ebx)
+ je 4f
+
+ LOCK
+ decl MUTEX(%ebx)
+ jne 10f
+
+11: addl $WRITERS_WAKEUP-MUTEX, %ebx
+ movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl $SYS_futex, %eax
+ int $0x80
+
+ subl $WRITERS_WAKEUP-MUTEX, %ebx
+
+ /* Reget the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebx)
+ testl %eax, %eax
+ jne 12f
+
+13: decl WRITERS_QUEUED(%ebx)
+ movl $0, WRITERS_WAKEUP(%ebx)
+ jmp 2b
+
+5: xorl %ecx, %ecx
+ movl %gs:8, %eax
+ movl %eax, WRITER(%ebx)
+9: LOCK
+ decl MUTEX(%ebx)
+ jne 6f
+7:
+
+ movl %ecx, %eax
+ popl %ebx
+ popl %esi
+ ret
+
+1: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+
+14: cmpl %gs:8, %eax
+ jne 3b
+ movl $EDEADLK, %ecx
+ jmp 9b
+
+6: movl %ebx, %eax
+ call __lll_mutex_unlock_wake
+ jmp 7b
+
+4: decl WRITERS_QUEUED(%ebx)
+ movl $EAGAIN, %ecx
+ jmp 9b
+
+10: movl %ebx, %eax
+ call __lll_mutex_unlock_wake
+ jmp 11b
+
+12: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 13b
+ .size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
+
+ .globl pthread_rwlock_wrlock
+pthread_rwlock_wrlock = __pthread_rwlock_wrlock
+
+
+ .globl pthread_rwlock_timedwrlock
+ .type pthread_rwlock_timedwrlock,@function
+ .align 16
+pthread_rwlock_timedwrlock:
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ pushl %ebp
+ subl $8, %esp
+
+ movl 28(%esp), %ebp
+ movl 32(%esp), %edi
+
+ /* Get the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebp)
+ testl %eax, %eax
+ jne 1f
+
+2: movl WRITER(%ebp), %eax
+ testl %eax, %eax
+ jne 14f
+ cmp $0, NR_READERS(%ebp)
+ je 5f
+
+3: incl WRITERS_QUEUED(%ebp)
+ je 4f
+
+ LOCK
+ decl MUTEX(%ebp)
+ jne 10f
+
+ /* Get current time. */
+ movl %esp, %ebx
+ xorl %ecx, %ecx
+ movl $SYS_gettimeofday, %eax
+ int $0x80
+
+ /* Compute relative timeout. */
+ movl 4(%esp), %eax
+ movl $1000, %edx
+ mul %edx /* Milli seconds to nano seconds. */
+ movl (%edi), %ecx
+ movl 4(%edi), %edx
+ subl (%esp), %ecx
+ subl %eax, %edx
+ jns 15f
+ addl $1000000000, %edx
+ decl %ecx
+15: testl %ecx, %ecx
+ js 16f /* Time is already up. */
+
+ /* Futex call. */
+ movl %ecx, (%esp) /* Store relative timeout. */
+ movl %edx, 4(%esp)
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl %esp, %esi
+ movl %ecx, %edx
+ leal WRITERS_WAKEUP(%ebp), %ebx
+ movl $SYS_futex, %eax
+ int $0x80
+ movl %eax, %edx
+17:
+
+ /* Reget the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebp)
+ testl %eax, %eax
+ jne 12f
+
+13: cmpl $-ETIMEDOUT, %ecx
+ je 18f
+ decl WRITERS_QUEUED(%ebp)
+ movl $0, WRITERS_WAKEUP(%ebp)
+ jmp 2b
+
+
+5: xorl %ecx, %ecx
+ movl %gs:8, %eax
+ movl %eax, WRITER(%ebp)
+9: LOCK
+ decl MUTEX(%ebp)
+ jne 6f
+
+7: movl %ecx, %eax
+
+ addl $8, %esp
+ popl %ebp
+ popl %ebx
+ popl %edi
+ popl %esi
+ ret
+
+1: movl %ebp, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+
+14: cmpl %gs:8, %eax
+ jne 3b
+ movl $EDEADLK, %ecx
+ jmp 9b
+
+6: movl %ebp, %eax
+ call __lll_mutex_unlock_wake
+ jmp 7b
+
+ /* Overflow. */
+4: decl WRITERS_QUEUED(%ebp)
+ movl $EAGAIN, %ecx
+ jmp 9b
+
+10: movl %ebp, %eax
+ call __lll_mutex_unlock_wake
+ jmp 11b
+
+12: movl %ebx, %ecx
+ call __lll_mutex_lock_wait
+ jmp 13b
+
+16: movl $-ETIMEDOUT, %ecx
+ jmp 17b
+
+18: movl $ETIMEDOUT, %ecx
+ jmp 9b
+ .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock
+
+ .globl __pthread_rwlock_unlock
+ .type __pthread_rwlock_unlock,@function
+ .align 16
+__pthread_rwlock_unlock:
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ xorl %esi, %esi
+ xorl %edx, %edx
+ movl 16(%esp), %edi
+
+ /* Get the lock. */
+ movl $1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%edi)
+ testl %eax, %eax
+ jne 1f
+
+2: cmpl $0, WRITER(%edi)
+ jne 5f
+ decl NR_READERS(%edi)
+ jnz 6f
+
+5: movl $0, WRITER(%edi)
+
+ movl $0x7fffffff, %edx
+ leal READERS_WAKEUP(%edi), %ebx
+ movl $1, %ecx
+ leal WRITERS_WAKEUP(%edi), %eax
+ cmpl $0, WRITERS_QUEUED(%edi)
+ cmovne %ecx, %edx
+ cmovne %eax, %ebx
+ movl $SYS_futex, %eax
+ int $0x80
+
+6: LOCK
+ decl MUTEX(%edi)
+ jne 3f
+
+4: xorl %eax, %eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ ret
+
+1: movl %edi, %ecx
+ call __lll_mutex_lock_wait
+ jmp 2b
+
+3: movl %edi, %eax
+ call __lll_mutex_unlock_wake
+ jmp 4b
+
+ .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock
+
+ .globl pthread_rwlock_unlock
+pthread_rwlock_unlock = __pthread_rwlock_unlock
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S
new file mode 100644
index 0000000000..18fb16f6f6
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S
@@ -0,0 +1,311 @@
+/* Copyright (C) 2002 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 <sysdep.h>
+#include <shlib-compat.h>
+
+ .text
+
+#ifndef UP
+# define LOCK lock
+#else
+# define
+#endif
+
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_futex 240
+#define FUTEX_WAKE 1
+
+#define EINTR 4
+#define EAGAIN 11
+#define EWOULDBLOCK EAGAIN
+#define EINVAL 22
+#define ETIMEDOUT 110
+
+
+ .globl __new_sem_wait
+ .type __new_sem_wait,@function
+ .align 16
+__new_sem_wait:
+ pushl %ebx
+ pushl %esi
+
+ movl 12(%esp), %ebx
+
+3: movl (%ebx), %eax
+2: testl %eax, %eax
+ je,pn 1f
+
+ leal -1(%eax), %edx
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ jne,pn 2b
+ xorl %eax, %eax
+
+ popl %esi
+ popl %ebx
+ ret
+
+1: xorl %esi, %esi
+ movl $SYS_futex, %eax
+ movl %esi, %ecx
+ movl %esi, %edx
+ int $0x80
+
+ testl %eax, %eax
+ je 3b
+ cmpl $-EWOULDBLOCK, %eax
+ je 3b
+ negl %eax
+#ifdef PIC
+ call __i686.get_pc_thunk.bx
+#else
+ movl $4f, %ebx
+4:
+#endif
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl %gs:0, %edx
+ subl errno@gottpoff(%ebx), %edx
+ movl %eax, (%edx)
+ orl $-1, %eax
+ popl %esi
+ popl %ebx
+ ret
+ .size __new_sem_wait,.-__new_sem_wait
+ .symver __new_sem_wait, sem_wait@@GLIBC_2.1
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+ .global __old_sem_wait
+__old_sem_wait = __new_sem_wait
+ .symver __old_sem_wait, sem_wait@GLIBC_2.0
+#endif
+
+
+ .globl __new_sem_trywait
+ .type __new_sem_trywait,@function
+ .align 16
+__new_sem_trywait:
+ movl 4(%esp), %ecx
+
+ movl (%ecx), %eax
+2: testl %eax, %eax
+ jz 1f
+
+ leal -1(%eax), %edx
+ LOCK
+ cmpxchgl %edx, (%ecx)
+ jne,pn 2b
+ xorl %eax, %eax
+ ret
+
+1:
+#ifdef PIC
+ call __i686.get_pc_thunk.cx
+#else
+ movl $3f, %ecx
+3:
+#endif
+ addl $_GLOBAL_OFFSET_TABLE_, %ecx
+ movl %gs:0, %edx
+ subl errno@gottpoff(%ecx), %edx
+ movl $EAGAIN, (%edx)
+ orl $-1, %eax
+ ret
+ .size __new_sem_trywait,.-__new_sem_trywait
+ .symver __new_sem_trywait, sem_trywait@@GLIBC_2.1
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+ .global __old_sem_trywait
+__old_sem_trywait = __new_sem_trywait
+ .symver __old_sem_trywait, sem_trywait@GLIBC_2.0
+#endif
+
+
+ .globl sem_timedwait
+ .type sem_timedwait,@function
+ .align 16
+sem_timedwait:
+ movl 4(%esp), %ecx
+
+ movl (%ecx), %eax
+2: testl %eax, %eax
+ je,pn 1f
+
+ leal -1(%eax), %edx
+ LOCK
+ cmpxchgl %edx, (%ecx)
+ jne,pn 2b
+
+ xorl %eax, %eax
+ ret
+
+ /* Check whether the timeout value is valid. */
+1: pushl %esi
+ pushl %edi
+ pushl %ebx
+ subl $8, %esp
+
+ movl %esp, %esi
+ movl 28(%esp), %edi
+
+ /* Check for invalid nanosecond field. */
+ cmpl $1000000000, 4(%edi)
+ movl $EINVAL, %eax
+ jae 6f
+
+7: xorl %ecx, %ecx
+ movl %esp, %ebx
+ movl %ecx, %edx
+ movl $SYS_gettimeofday, %eax
+ int $0x80
+
+ /* Compute relative timeout. */
+ movl 4(%esp), %eax
+ movl $1000, %edx
+ mul %edx /* Milli seconds to nano seconds. */
+ movl (%edi), %ecx
+ movl 4(%edi), %edx
+ subl (%esp), %ecx
+ subl %eax, %edx
+ jns 5f
+ addl $1000000000, %edx
+ decl %ecx
+5: testl %ecx, %ecx
+ movl $ETIMEDOUT, %eax
+ js 6f /* Time is already up. */
+
+ movl %ecx, (%esp) /* Store relative timeout. */
+ movl %edx, 4(%esp)
+ movl 24(%esp), %ebx
+ xorl %ecx, %ecx
+ movl $SYS_futex, %eax
+ xorl %edx, %edx
+ int $0x80
+
+ testl %eax, %eax
+ je,pt 9f
+ cmpl $-EWOULDBLOCK, %eax
+ jne 3f
+
+9: movl (%ebx), %eax
+8: testl %eax, %eax
+ je 7b
+
+ leal -1(%eax), %ecx
+ LOCK
+ cmpxchgl %ecx, (%ebx)
+ jne,pn 8b
+
+ addl $8, %esp
+ xorl %eax, %eax
+ popl %ebx
+ popl %edi
+ popl %esi
+ ret
+
+3: negl %eax
+6:
+#ifdef PIC
+ call __i686.get_pc_thunk.bx
+#else
+ movl $4f, %ebx
+4:
+#endif
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl %gs:0, %edx
+ subl errno@gottpoff(%ebx), %edx
+ movl %eax, (%edx)
+
+ addl $8, %esp
+ orl $-1, %eax
+ popl %ebx
+ popl %edi
+ popl %esi
+ ret
+ .size sem_timedwait,.-sem_timedwait
+
+
+ .globl __new_sem_post
+ .type __new_sem_post,@function
+ .align 16
+__new_sem_post:
+ pushl %esi
+ pushl %ebx
+
+ movl 12(%esp), %ebx
+ movl $1, %edx
+ LOCK
+ xaddl %edx, (%ebx)
+
+ xorl %esi, %esi
+ movl $SYS_futex, %eax
+ movl $FUTEX_WAKE, %ecx
+ incl %edx
+ int $0x80
+
+ testl %eax, %eax
+ js 1f
+
+ popl %ebx
+ popl %esi
+ ret
+
+1:
+#ifdef PIC
+ call __i686.get_pc_thunk.bx
+#else
+ movl $4f, %ebx
+4:
+#endif
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl %gs:0, %edx
+ subl errno@gottpoff(%ebx), %edx
+ movl $EINVAL, (%edx)
+
+ orl $-1, %eax
+ popl %ebx
+ popl %esi
+ ret
+ .size __new_sem_post,.-__new_sem_post
+ .symver __new_sem_post, sem_post@@GLIBC_2.1
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+ .global __old_sem_post
+__old_sem_post = __new_sem_post
+ .symver __old_sem_post, sem_post@GLIBC_2.0
+#endif
+
+
+#ifdef PIC
+ .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
+ .globl __i686.get_pc_thunk.bx
+ .hidden __i686.get_pc_thunk.bx
+ .type __i686.get_pc_thunk.bx,@function
+__i686.get_pc_thunk.bx:
+ movl (%esp), %ebx;
+ ret
+ .size __i686.get_pc_thunk.bx,.-__i686.get_pc_thunk.bx
+
+
+ .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
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S
new file mode 100644
index 0000000000..a385adc5f9
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S
@@ -0,0 +1,122 @@
+/* Copyright (C) 2002 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 <sysdep.h>
+
+#define SYS_futex 240
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#ifndef UP
+# define LOCK lock
+#else
+# define LOCK
+#endif
+
+#define CURR_EVENT 0
+#define MUTEX 4
+#define LEFT 8
+#define INIT_COUNT 12
+
+
+ .text
+
+ .globl pthread_barrier_wait
+ .type pthread_barrier_wait,@function
+ .align 16
+pthread_barrier_wait:
+ pushl %esi
+ pushl %ebx
+
+ movl 12(%esp), %ebx
+ xorl %esi, %esi
+
+ /* Get the mutex. */
+ orl $-1, %eax
+ LOCK
+ xaddl %eax, MUTEX(%ebx)
+ jne 1f
+
+ /* One less waiter. If this was the last one needed wake
+ everybody. */
+2: decl LEFT(%ebx)
+ je 3f
+
+ /* There are more threads to come. */
+ movl CURR_EVENT(%ebx), %edx
+
+ /* Release the mutex. */
+ LOCK
+ incl MUTEX(%ebx)
+ jng 6f
+
+ /* Wait for the remaining threads. The call will return immediately
+ if the CURR_EVENT memory has meanwhile been changed. */
+7: movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
+8: movl $SYS_futex, %eax
+ int $0x80
+
+ /* Don't return on spurious wakeups. The syscall does not change
+ any register except %eax so there is no need to reload any of
+ them. */
+ cmpl %edx, CURR_EVENT(%ebx)
+ je,pn 8b
+
+ /* Note: %esi is still zero. */
+ movl %esi, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */
+
+ popl %ebx
+ popl %esi
+ ret
+
+ /* The necessary number of threads arrived. */
+3: movl INIT_COUNT(%ebx), %eax
+ movl %eax, LEFT(%ebx)
+ incl CURR_EVENT(%ebx)
+
+ /* Wake up all waiters. The count is a signed number in the kernel
+ so 0x7fffffff is the highest value. */
+ movl $0x7fffffff, %edx
+ movl $FUTEX_WAKE, %ecx
+ movl $SYS_futex, %eax
+ int $0x80
+
+ /* Release the mutex. */
+ LOCK
+ incl MUTEX(%ebx)
+ jng 4f
+
+5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */
+
+ popl %ebx
+ popl %esi
+ ret
+
+1: leal MUTEX(%ebx), %ecx
+ call __lll_lock_wait
+ jmp 2b
+
+4: leal MUTEX(%ebx), %eax
+ call __lll_unlock_wake
+ jmp 5b
+
+6: leal MUTEX(%ebx), %eax
+ call __lll_unlock_wake
+ jmp 7b
+ .size pthread_barrier_wait,.-pthread_barrier_wait
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S
new file mode 100644
index 0000000000..3dc8403a29
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelcond.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S
new file mode 100644
index 0000000000..e60dea89ef
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevellock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S
new file mode 100644
index 0000000000..50481991ff
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelmutex.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S
new file mode 100644
index 0000000000..6f4a8305ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelrwlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S
new file mode 100644
index 0000000000..cfaa36ac74
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelsem.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S
new file mode 100644
index 0000000000..6d20b9a95c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/pthread_barrier_wait.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S
new file mode 100644
index 0000000000..3dc8403a29
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelcond.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S
new file mode 100644
index 0000000000..e60dea89ef
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevellock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S
new file mode 100644
index 0000000000..50481991ff
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelmutex.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S
new file mode 100644
index 0000000000..6f4a8305ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelrwlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S
new file mode 100644
index 0000000000..cfaa36ac74
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/lowlevelsem.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S
new file mode 100644
index 0000000000..6d20b9a95c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002 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 "../i486/pthread_barrier_wait.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
new file mode 100644
index 0000000000..71babd5c93
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -0,0 +1,257 @@
+/* Copyright (C) 2002 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 <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)
+
+
+/* Does not preserve %eax and %ecx. */
+extern int __lll_mutex_lock_wait (int val, int *__futex)
+ __attribute ((regparm (2))) attribute_hidden;
+/* Does not preserver %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_wait (int *__futex)
+ __attribute ((regparm (1))) attribute_hidden;
+
+
+#define lll_mutex_trylock(futex) \
+ ({ unsigned char ret; \
+ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0" \
+ : "=a" (ret), "=m" (futex) \
+ : "r" (1), "1" (futex), "0" (0)); \
+ ret; })
+
+
+#define lll_mutex_lock(futex) \
+ (void) ({ int ignore1, ignore2; \
+ __asm (LOCK_INSTR "xaddl %0, %2\n\t" \
+ "testl %0, %0\n\t" \
+ "jne 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tleal %2, %%ecx\n\t" \
+ "call __lll_mutex_lock_wait\n\t" \
+ "jmp 2f\n\t" \
+ ".previous\n" \
+ "2:" \
+ : "=a" (ignore1), "=&c" (ignore2), "=m" (futex) \
+ : "0" (1), "2" (futex)); })
+
+
+#define lll_mutex_timedlock(futex, timeout) \
+ ({ int result, ignore1, ignore2; \
+ __asm (LOCK_INSTR "xaddl %0, %3\n\t" \
+ "testl %0, %0\n\t" \
+ "jne 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tleal %3, %%ecx\n\t" \
+ "movl %6, %%edx\n\t" \
+ "call __lll_mutex_timedlock_wait\n\t" \
+ "jmp 2f\n\t" \
+ ".previous\n" \
+ "2:" \
+ : "=a" (result), "=&c" (ignore1), "=&d" (ignore2), "=m" (futex) \
+ : "0" (1), "3" (futex), "m" (timeout)); \
+ result; })
+
+
+#define lll_mutex_unlock(futex) \
+ (void) ({ int ignore; \
+ __asm (LOCK_INSTR "decl %0\n\t" \
+ "jne 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tleal %0, %%eax\n\t" \
+ "call __lll_mutex_unlock_wake\n\t" \
+ "jmp 2f\n\t" \
+ ".previous\n" \
+ "2:" \
+ : "=m" (futex), "=&a" (ignore) \
+ : "0" (futex)); })
+
+
+#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 (1)
+#define LLL_LOCK_INITIALIZER_LOCKED (0)
+
+
+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:
+ 1 - untaken
+ 0 - taken by one user
+ <0 - taken by more users */
+
+
+#define lll_trylock(futex) \
+ ({ unsigned char ret; \
+ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0" \
+ : "=a" (ret), "=m" (futex) \
+ : "r" (0), "1" (futex), "0" (1)); \
+ ret; })
+
+
+#define lll_lock(futex) \
+ (void) ({ int ignore1, ignore2; \
+ __asm (LOCK_INSTR "xaddl %0, %2\n\t" \
+ "jne 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tleal %2, %%ecx\n\t" \
+ "call __lll_lock_wait\n\t" \
+ "jmp 2f\n\t" \
+ ".previous\n" \
+ "2:" \
+ : "=a" (ignore1), "=&c" (ignore2), "=m" (futex) \
+ : "0" (-1), "2" (futex)); })
+
+
+#define lll_unlock(futex) \
+ (void) ({ int ignore; \
+ __asm (LOCK_INSTR "incl %0\n\t" \
+ "jng 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tleal %0, %%eax\n\t" \
+ "call __lll_unlock_wake\n\t" \
+ "jmp 2f\n\t" \
+ ".previous\n" \
+ "2:" \
+ : "=m" (futex), "=&a" (ignore) \
+ : "0" (futex)); })
+
+
+#define lll_islocked(futex) \
+ (futex != 0)
+
+
+/* The kernel notifies a process with uses CLONE_CLEARTID via futex
+ wakeup when the clone terminates. The memory location contains the
+ thread ID while the clone is running and is reset to zero
+ afterwards.
+
+ The macro parameter must not have any side effect. */
+#ifdef PIC
+# define LLL_TID_EBX_LOAD "xchgl %2, %%ebx\n"
+# define LLL_TID_EBX_REG "D"
+#else
+# define LLL_TID_EBX_LOAD
+# define LLL_TID_EBX_REG "b"
+#endif
+#define lll_wait_tid(tid) \
+ do { \
+ int __ignore; \
+ register __typeof (tid) _tid asm ("edx") = (tid); \
+ if (_tid != 0) \
+ __asm __volatile (LLL_TID_EBX_LOAD \
+ "1:\tmovl %1, %%eax\n\t" \
+ "int $0x80\n\t" \
+ "cmpl $0, (%%ebx)\n\t" \
+ "jne,pn 1b\n\t" \
+ LLL_TID_EBX_LOAD \
+ : "=&a" (__ignore) \
+ : "i" (SYS_futex), LLL_TID_EBX_REG (&tid), "S" (0), \
+ "c" (FUTEX_WAIT), "d" (_tid)); \
+ } 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 == NULL || abstime->tv_nsec >= 1000000000) \
+ __result = EINVAL; \
+ else \
+ __result = __lll_timedwait_tid (&tid, abstime); \
+ } \
+ __result; })
+
+
+#define lll_wake_tid(tid) \
+ do { \
+ int __ignore; \
+ (tid) = 0; \
+ __asm __volatile (LLL_TID_EBX_LOAD \
+ "\tint $0x80\n\t" \
+ LLL_TID_EBX_LOAD \
+ : "=a" (__ignore) \
+ : "0" (SYS_futex), LLL_TID_EBX_REG (&(tid)), "S" (0), \
+ "c" (FUTEX_WAKE), "d" (0x7fffffff)); \
+ } while (0)
+
+
+/* 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 */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h
new file mode 100644
index 0000000000..bd5f96402b
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevelsem.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 2002 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 _LOWLEVELSEM_H
+#define _LOWLEVELSEM_H 1
+
+#ifndef LOCK
+# ifdef UP
+# define LOCK /* nothing */
+# else
+# define LOCK "lock;"
+# endif
+#endif
+
+#define SYS_futex 240
+
+
+#define lll_sem_wait(sem) \
+ ({ int result, ignore1, ignore2; \
+ __asm __volatile ("1:\tincl 8(%4)\n\t" \
+ LOCK "incl (%4)\n\t" \
+ "jng 2f\n" \
+ ".subsection 1\n" \
+ "2:\tmovl %4, %%eax\n\t" \
+ "call __lll_unlock_wake\n\t" \
+ "jmp 3f\n\t" \
+ ".previous\n" \
+ "3:\tpushl %%ebx\n\t" \
+ "movl %%esi, %%ecx\n\t" \
+ "movl %%esi, %%edx\n\t" \
+ "leal 4(%4), %%ebx\n\t" \
+ "movl %5, %%eax\n\t" \
+ "int $0x80\n\t" \
+ "movl %%eax, %%edx\n\t" \
+ "popl %%ebx\n\t" \
+ "orl $-1, %%eax\n\t" \
+ LOCK "xaddl %%eax, (%4)\n\t" \
+ "jne 4f\n\t" \
+ ".subsection 1\n" \
+ "4:\tmovl %4, %%ecx\n\t" \
+ "call __lll_lock_wait\n\t" \
+ "jmp 5f\n\t" \
+ ".previous\n" \
+ "5:\tdecl 8(%4)\n\t" \
+ "xorl %0, %0\n\t" \
+ "cmpl $0, 4(%4)\n\t" \
+ "jne,pt 6f\n\t" \
+ "cmpl %7, %%edx\n\t" \
+ "jne,pn 1b\n\t" \
+ "addl %8, %0\n\t" /* Shorter than movl %7, %0 */ \
+ "6:" \
+ : "=a" (result), "=c" (ignore1), "=d" (ignore2), \
+ "=m" (*sem) \
+ : "D" (sem), "i" (SYS_futex), "S" (0), \
+ "i" (-EINTR), "i" (EINTR)); \
+ result; })
+
+
+extern int __lll_sem_timedwait (struct sem *sem, const struct timespec *ts)
+ __attribute__ ((regparm (2))) attribute_hidden;
+#define lll_sem_timedwait(sem, timeout) \
+ __lll_sem_timedwait (sem, timeout)
+
+
+#define lll_sem_post(sem) \
+ (void) ({ int ignore1, ignore2, ignore3; \
+ __asm __volatile ("movl $1, %%eax\n\t" \
+ LOCK \
+ "xaddl %%eax, (%4)\n\t" \
+ "pushl %%esi\n\t" \
+ "pushl %%ebx\n\t" \
+ "movl %4, %%ebx\n\t" \
+ "leal 1(%%eax), %%edx\n\t" \
+ "xorl %%esi, %%esi\n\t" \
+ "movl %5, %%eax\n\t" \
+ /* movl $FUTEX_WAKE, %ecx */ \
+ "movl $1, %%ecx\n\t" \
+ "int $0x80\n\t" \
+ "popl %%ebx\n\t" \
+ "popl %%esi" \
+ : "=&a" (ignore1), "=c" (ignore2), \
+ "=m" (*sem), "=d" (ignore3) \
+ : "r" (sem), "i" (SYS_futex)); })
+
+#endif /* lowlevelsem.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
new file mode 100644
index 0000000000..6994c0d7fa
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
@@ -0,0 +1,49 @@
+/* Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Schwab <schwab@gnu.org>.
+
+ 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 <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+#include <kernel-features.h>
+
+/* Clone the calling process, but without copying the whole address space.
+ The calling process is suspended until the new process exits or is
+ replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
+ and the process ID of the new process to the old process. */
+
+ENTRY (__vfork)
+ /* Pop the return PC value into ECX. */
+ popl %ecx
+
+ /* Stuff the syscall number in EAX and enter into the kernel. */
+ movl $SYS_ify (vfork), %eax
+ int $0x80
+
+ /* Jump to the return PC. Don't jump directly since this
+ disturbs the branch target cache. Instead push the return
+ address back on the stack. */
+ pushl %ecx
+
+ cmpl $-4095, %eax
+ jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */
+.Lpseudo_end:
+ ret
+PSEUDO_END (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S
new file mode 100644
index 0000000000..747c8ec2d2
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S
@@ -0,0 +1,171 @@
+/* Copyright (C) 2002 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 <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
+__pthread_once:
+ movl 4(%esp), %ecx
+ testl $2, (%ecx)
+ jz 1f
+ xorl %eax, %eax
+ ret
+
+1: pushl %ebx
+ pushl %esi
+ 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
+ int $0x80
+ jmp 6b
+
+3: /* Call the initializer function after setting up the
+ cancellation handler. */
+ subl $16, %esp
+
+ /* Push the cleanup handler. */
+#ifdef PIC
+ leal clear_once_control@GOTOFF(%ecx), %eax
+#else
+ leal clear_once_control, %eax
+#endif
+ movl %esp, %edx
+ pushl %ebx
+ pushl %eax
+ pushl %edx
+ call _GI_pthread_cleanup_push /* Note: no @PLT. */
+
+ movl 44(%esp), %eax
+ call *%eax
+
+ /* Pop the cleanup handler. This code depends on the once
+ handler and _pthread_cleanup_push not touch the content
+ of the stack. Otherwise the first parameter would have
+ to be reloaded. */
+ movl $0, 4(%esp)
+ call _GI_pthread_cleanup_pop /* Note: no @PLT. */
+
+ addl $28, %esp
+
+ /* Sucessful run of the initializer. Signal that we are done. */
+ LOCK
+ incl (%ebx)
+
+ /* Wake up all other threads. */
+ movl $0x7fffffff, %edx
+ movl $FUTEX_WAKE, %ecx
+ movl $SYS_futex, %eax
+ int $0x80
+
+4: popl %esi
+ popl %ebx
+ xorl %eax, %eax
+ ret
+
+ .size __pthread_once,.-__pthread_once
+
+ .globl pthread_once
+pthread_once = __pthread_once
+
+
+ .type clear_once_control,@function
+ .align 16
+clear_once_control:
+ pushl %esi
+ pushl %ebx
+
+ movl 4(%esp), %eax
+ movl $0, (%eax)
+
+ xorl %esi, %esi
+ movl $0x7fffffff, %edx
+ movl $FUTEX_WAKE, %ecx
+ movl $SYS_futex, %eax
+ int $0x80
+
+ popl %ebx
+ popl %esi
+ ret
+ .size clear_once_control,.-clear_once_control
+
+
+#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
diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
new file mode 100644
index 0000000000..24ead1b5ce
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 2002 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 _INTERNALTYPES_H
+#define _INTERNALTYPES_H 1
+
+
+struct pthread_attr
+{
+ /* Scheduler parameters and priority. */
+ struct sched_param schedparam;
+ int schedpolicy;
+ /* Various flags like detachstate, scope, etc. */
+ int flags;
+ /* Size of guard area. */
+ size_t guardsize;
+ /* Stack handling. */
+ void *stackaddr;
+ size_t stacksize;
+
+ /* Chain of all initialized attributes. Keep this last since it is
+ not always used. */
+ struct pthread_attr *next;
+};
+
+#define ATTR_FLAG_DETACHSTATE 0x0001
+#define ATTR_FLAG_NOTINHERITSCHED 0x0002
+#define ATTR_FLAG_SCOPEPROCESS 0x0004
+#define ATTR_FLAG_STACKADDR 0x0008
+
+
+/* Mutex attribute data structure. */
+struct pthread_mutexattr
+{
+ /* Identifier for the kind of mutex.
+
+ Bit 31 is set if the mutex is to be shared between processes.
+
+ Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify
+ the type of the mutex. */
+ int mutexkind;
+};
+
+
+/* Conditional variable attribute data structure. */
+struct pthread_condattr
+{
+ /* Flag whether coditional variable will be shareable between processes. */
+ int pshared;
+};
+
+
+/* Read-write lock variable attribute data structure. */
+struct pthread_rwlockattr
+{
+ int lockkind;
+ int pshared;
+};
+
+
+/* Barrier data structure. */
+struct pthread_barrier
+{
+ unsigned int curr_event;
+ int lock;
+ unsigned int left;
+ unsigned int init_count;
+};
+
+
+/* Barrier variable attribute data structure. */
+struct pthread_barrierattr
+{
+ int pshared;
+};
+
+
+/* Thread-local data handling. */
+struct pthread_key_struct
+{
+ /* Sequence numbers. Even numbers indicated vacant entries. Note
+ that zero is even. We use uintptr_t to not require padding on
+ 32- and 64-bit machines. On 64-bit machines it helps to avoid
+ wrapping, too. */
+ uintptr_t seq;
+
+ /* Destructor for the data. */
+ void (*destr) (void *);
+};
+
+/* Check whether an entry is unused. */
+#define KEY_UNUSED(p) (((p) & 1) == 0)
+/* Check whether a key is usable. We cannot reuse an allocated key if
+ the sequence counter would overflow after the next destroy call.
+ This would mean that we potentially free memory for a key with the
+ same sequence. This is *very* unlikely to happen, A program would
+ have to create and destroy a key 2^31 times (on 32-bit platforms,
+ on 64-bit platforms that would be 2^63). If it should happen we
+ simply don't use this specific key anymore. */
+#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2)))
+
+
+/* Handling of read-write lock data. */
+// XXX For now there is only one flag. Maybe more in future.
+#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0)
+
+
+/* Semaphore variable structure. */
+struct sem
+{
+ unsigned int count;
+};
+
+#endif /* internaltypes.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c
new file mode 100644
index 0000000000..0fd3c9aa58
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c
@@ -0,0 +1,33 @@
+/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. Linux version.
+ Copyright (C) 1995, 1997, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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 <setjmp.h>
+#include <stddef.h>
+
+
+extern void __pthread_cleanup_upto (jmp_buf env, char *targetframe);
+#pragma weak __pthread_cleanup_upto
+
+
+void
+_longjmp_unwind (jmp_buf env, int val)
+{
+ if (__pthread_cleanup_upto != NULL)
+ __pthread_cleanup_upto (env, __builtin_frame_address (0));
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/nptl/sysdeps/unix/sysv/linux/pt-fork.c
new file mode 100644
index 0000000000..a1e228ee29
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pt-fork.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002 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 <unistd.h>
+
+
+pid_t
+__fork (void)
+{
+ return __libc_fork ();
+}
+strong_alias (__fork, fork)
diff --git a/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/nptl/sysdeps/unix/sysv/linux/pt-raise.c
new file mode 100644
index 0000000000..0c68960e5d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pt-raise.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2002 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 <errno.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+int
+raise (sig)
+ int sig;
+{
+ return INLINE_SYSCALL (tkill, 2, THREAD_SELF->tid, sig);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
new file mode 100644
index 0000000000..f5c2377e7e
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002 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 <errno.h>
+#include <signal.h>
+#include <pthreadP.h>
+#include <tls.h>
+#include <sysdep.h>
+
+
+int
+pthread_kill (threadid, signo)
+ pthread_t threadid;
+ int signo;
+{
+ struct pthread *pd = (struct pthread *) threadid;
+
+ /* We have a special syscall to do the work. */
+ return INLINE_SYSCALL (tkill, 2, pd->tid, signo);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_yield.c b/nptl/sysdeps/unix/sysv/linux/pthread_yield.c
new file mode 100644
index 0000000000..5aecffcf0d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_yield.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2002 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 <pthread.h>
+#include <sched.h>
+
+
+/* With the 1-on-1 model we implement this function is equivalent to
+ the 'sched_yield' function. */
+int
+pthread_yield (void)
+{
+ return sched_yield ();
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/raise.c b/nptl/sysdeps/unix/sysv/linux/raise.c
new file mode 100644
index 0000000000..009f32ad30
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/raise.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002 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 <errno.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <nptl/pthreadP.h>
+
+
+int
+raise (sig)
+ int sig;
+{
+ struct pthread *pd = THREAD_SELF;
+ pid_t selftid = pd->tid;
+ if (selftid == 0)
+ {
+ selftid = INLINE_SYSCALL (gettid, 0);
+ THREAD_SETMEM (pd, tid, selftid);
+ }
+
+ return INLINE_SYSCALL (tkill, 2, selftid, sig);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
new file mode 100644
index 0000000000..ef70dde8a2
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/register-atfork.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2002 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 <errno.h>
+#include <stdlib.h>
+#include "fork.h"
+
+
+int
+__register_atfork (prepare, parent, child, dso_handle)
+ void (*prepare) (void);
+ void (*parent) (void);
+ void (*child) (void);
+ void *dso_handle;
+{
+ struct fork_handler *new_prepare = NULL;
+ struct fork_handler *new_parent = NULL;
+ struct fork_handler *new_child = NULL;
+
+ if (prepare != NULL)
+ {
+ new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare));
+ if (new_prepare == NULL)
+ goto out1;
+
+ new_prepare->handler = prepare;
+ new_prepare->dso_handle = dso_handle;
+ }
+
+ if (parent != NULL)
+ {
+ new_parent = (struct fork_handler *) malloc (sizeof (*new_parent));
+ if (new_parent == NULL)
+ goto out2;
+
+ new_parent->handler = parent;
+ new_parent->dso_handle = dso_handle;
+ }
+
+ if (child != NULL)
+ {
+ new_child = (struct fork_handler *) malloc (sizeof (*new_child));
+ if (new_child == NULL)
+ {
+ free (new_parent);
+ out2:
+ free (new_prepare);
+ out1:
+ return errno;
+ }
+
+ new_child->handler = child;
+ new_child->dso_handle = dso_handle;
+ }
+
+ /* Get the lock to not conflict with running forks. */
+ lll_lock (__fork_lock);
+
+ /* Now that we have all the handlers allocate enqueue them. */
+ if (new_prepare != NULL)
+ list_add_tail (&new_prepare->list, &__fork_prepare_list);
+ if (new_parent != NULL)
+ list_add_tail (&new_parent->list, &__fork_parent_list);
+ if (new_child != NULL)
+ list_add_tail (&new_child->list, &__fork_child_list);
+
+ /* Release the lock. */
+ lll_unlock (__fork_lock);
+
+ return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
new file mode 100644
index 0000000000..470f80d05c
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2002 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 <errno.h>
+#include <stdlib.h>
+#include "fork.h"
+
+
+void
+__unregister_atfork (dso_handle)
+ void *dso_handle;
+{
+ /* Get the lock to not conflict with running forks. */
+ lll_lock (__fork_lock);
+
+ list_t *runp;
+ list_t *prevp;
+
+ list_for_each_prev_safe (runp, prevp, &__fork_prepare_list)
+ if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+ list_del (runp);
+
+ list_for_each_prev_safe (runp, prevp, &__fork_parent_list)
+ if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+ list_del (runp);
+
+ list_for_each_prev_safe (runp, prevp, &__fork_child_list)
+ if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle)
+ list_del (runp);
+
+ /* Release the lock. */
+ lll_unlock (__fork_lock);
+}