diff options
author | Ulrich Drepper <drepper@redhat.com> | 2002-11-26 22:50:54 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2002-11-26 22:50:54 +0000 |
commit | 76a50749f7af5935ba3739e815aa6a16ae4440d1 (patch) | |
tree | c16eac47f220f03fea74d80ef0a4e774809e94b7 /nptl/sysdeps/unix/sysv | |
parent | 6938e63f714b15c377d8cbf8e97b6f15b0e1b692 (diff) | |
download | glibc-76a50749f7af5935ba3739e815aa6a16ae4440d1.tar.gz glibc-76a50749f7af5935ba3739e815aa6a16ae4440d1.tar.xz glibc-76a50749f7af5935ba3739e815aa6a16ae4440d1.zip |
Initial revision cvs/initial
2002-11-26 Ulrich Drepper <drepper@redhat.com> * allocatestack.c (queue_stack): Don't remove stack from list here. Do it in the caller. Correct condition to prematurely terminate loop to free stacks. (__deallocate_stack): Remove stack from list here. 2002-11-26 Ulrich Drepper <drepper@redhat.com> * Makefile (tests): Add tst-stack1. * tst-stack1.c: New file. * allocatestack.c (allocate_stack): Initialize the TCB on a user provided stack. * pthread_attr_getstack.c: Return bottom of the thread area. 2002-11-25 Ulrich Drepper <drepper@redhat.com> * Makefile (libpthread-routines): Add pt-allocrtsig and pthread_kill_other_threads. * pt-allocrtsig.c: New file. * pthread_kill_other_threads.c: New file. * sysdeps/unix/sysv/linux/allocrtsig.c: Add additional aliases for all three functions. * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove allocrtsig. * sysdeps/unix/sysv/linux/Versions (libc:GLIBC_PRIVATE): Export __libc_current_sigrtmin_private, __libc_current_sigrtmax_private, and __libc_allocate_rtsig_private. * Versions (libpthread): Export pthread_kill_other_threads_np, __libc_current_sigrtmin, and __libc_current_sigrtmax. 2002-11-24 Ulrich Drepper <drepper@redhat.com> * allocatestack.c (allocate_stack): stackaddr in attribute points to the end of the stack. Adjust computations. When mprotect call fails dequeue stack and free it. * pthread_attr_setstack.c: Store top of the stack in stackaddr attribute. * pthread_getattr_np.c: Likewise. * descr.h (IS_DETACHED): Add some more parenthesis to prevent surprises. 2002-11-23 Ulrich Drepper <drepper@redhat.com> * sysdeps/pthread/pthread.h (pthread_self): __THROW must come before attribute definitions. Patch by Luca Barbieri <ldb@ldb.ods.org>. 2002-11-22 Ulrich Drepper <drepper@redhat.com> * pthread_getspecific.c: Optimize access to first 2nd-level array. * pthread_setspecific.c: Likewise. 2002-11-21 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/i386/createthread.c: Remove CLONE_ flags definitions. Get them from the official place. * sysdeps/unix/sysv/linux/i386/fork.c: Likewise. * sysdeps/unix/sysv/linux/i386/createthread.c: Update CLONE_* flags. Use new CLONE_ flags in clone() calls. * sysdeps/unix/sysv/linux/fork.c: Use ARCH_FORK to actually fork. * sysdeps/unix/sysv/linux/i386/fork.c: New file. * Versions: Add pthread_* functions for libc. * forward.c: New file. * sysdeps/pthread/Makefile (libpthread-sysdeps_routines): Add errno-loc. * herrno.c: New file. * res.c: New file. * Makefile (libpthread-routines): Remove sem_post, sem_wait, sem_trywait, and sem_timedwait. Add herrno and res. * sem_init.c: Don't initialize lock and waiters members. * sem_open.c: Likewise. * sem_post.c: Removed. * sem_wait.c: Removed. * sem_trywait.c: Removed. * sem_timedwait.c: Removed. * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Complete rewrite. Includes full implementations of sem_post, sem_wait, sem_trywait, and sem_timedwait. * sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Adjust for new implementation. * sysdeps/unix/sysv/linux/internaltypes.h (struct sem): Remove lock and waiters fields. * tst-sem3.c: Improve error message. * tst-signal3.c: Likewise. * init.c (__pthread_initialize_minimal): Use set_tid_address syscall to tell the kernel about the termination futex and to initialize tid member. Don't initialize main_thread. * descr.h (struct pthread): Remove main_thread member. * cancelllation.c (__do_cancel): Remove code handling main thread. The main thread is not special anymore. * allocatestack.c (__reclaim_stacks): Mark stacks as unused. Add size of the stacks to stack_cache_actsize. * pt-readv.c: Add missing "defined". * pt-sigwait.c: Likewise. * pt-writev.c: Likewise. 2002-11-09 Ulrich Drepper <drepper@redhat.com> * Versions: Export __connect from libpthread. Patch by Luca Barbieri <ldb@ldb.ods.org>. * Makefile (libpthread-routines): Add pt-raise. * sysdeps/unix/sysv/linux/raise.c: New file. * sysdeps/unix/sysv/linux/pt-raise.c: New file. * sysdeps/generic/pt-raise.c: New file. * pthread_cond_init.c: Initialize all data elements of the condvar structure. Patch by Luca Barbieri <ldb@ldb.ods.org>. * pthread_attr_init.c: Actually implement 2.0 compatibility version. * pthread_create.c: Likewise. * Makefile (tests): Add tst-key1, tst-key2, tst-key3. * tst-key1.c: New file. * tst-key2.c: New file. * tst-key3.c: New file. * Versions: Export pthread_detach for version GLIBC_2.0. Reported by Saurabh Desai <sdesai@austin.ibm.com>. 2002-11-08 Ulrich Drepper <drepper@redhat.com> * pthread_key_create.c: Terminate search after an unused key was found. Patch by Luca Barbieri <ldb@ldb.ods.org>. * sysdeps/unix/sysv/linux/i386/pthread_once.S: Return zero. Patch by Luca Barbieri <ldb@ldb.ods.org>. 2002-10-10 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Use slow generic dynamic lookup for errno in PIC. * allocatestack.c (get_cached_stack): Rearrange code slightly to release the stack lock as soon as possible. Call _dl_allocate_tls_init for TCB from the cache to re-initialize the static TLS block. (allocate_stack): Call _dl_allocate_tls_init for user-provided stack. * cancellation.c: Renamed from cancelation.c. * Makefile: Adjust accordingly. * pthreadP.h (CANCELLATION_P): Renamed from CANCELATION_P. * cleanup_defer.c: Use CANCELLATION_P. * pthread_testcancel.c: Likewise. * descr.h: Fix spelling in comments. * init.c: Likewise. * pthread_getattr_np.c: Likewise. * pthread_getschedparam.c: Likewise. * pthread_setschedparam.c: Likewise. * Versions: Likewise. * pt-pselect.c: New file. * Makefile (libpthread-routines): Add pt-pselect. * Versions: Add pselect. * tst-cancel4.c: New file. * Makefile (tests): Add tst-cancel4. 2002-10-09 Ulrich Drepper <drepper@redhat.com> * pthread_mutex_lock.c: Always record lock ownership. * pthread_mutex_timedlock.c: Likewise. * pthread_mutex_trylock.c: Likewise. * pt-readv.c: New file. * pt-writev.c: New file. * pt-creat.c: New file. * pt-msgrcv.c: New file. * pt-msgsnd.c: New file. * pt-poll.c: New file. * pt-select.c: New file. * pt-sigpause.c: New file. * pt-sigsuspend.c: New file. * pt-sigwait.c: New file. * pt-sigwaitinfo.c: New file. * pt-waitid.c: New file. * Makefile (libpthread-routines): Add pt-readv, pt-writev, pt-creat, pt-msgrcv, pt-msgsnd, pt-poll, pt-select, pt-sigpause, pt-sigsuspend, pt-sigwait, pt-sigwaitinfo, and pt-waitid. * Versions: Add all the new functions. * tst-exit1.c: New file. * Makefile (tests): Add tst-exit1. * sem_timedwait.c: Minor optimization for more optimal fastpath. 2002-10-08 Ulrich Drepper <drepper@redhat.com> * pt-fcntl.c: Only enable asynchronous cancellation for F_SETLKW. * pthread_join.c: Enable asynchronous cancellation around lll_wait_tid call. pthread_join is an official cancellation point. * pthread_timedjoin.c: Likewise. * pthread_cond_wait.c: Revert order in which internal lock are dropped and the condvar's mutex are retrieved. * pthread_cond_timedwait.c: Likewise. Reported by dice@saros.East.Sun.COM. 2002-10-07 Ulrich Drepper <drepper@redhat.com> * pthreadP.h: Cut out all type definitions and move them... * sysdeps/unix/sysv/linux/internaltypes.h: ...here. New file. * pthreadP.h: Include <internaltypes.h>. * sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Little performance tweaks. * sem_trywait.c: Shuffle #includes around to get right order. * sem_timedwait.c: Likewise. * sem_post.c: Likewise. * sem_wait.c: Likewise. * nptl 0.3 released. * Makefile (tests): Add tst-signal3. * tst-signal3.c: New file. 2002-10-05 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Tell the compiler that the asms modify the sem object. (__lll_sem_timedwait): Now takes struct sem* as first parameter. * sysdeps/unix/sysv/linux/i386/bits/semaphore.h (sem_t): Don't expose the actual members. * pthreadP.h (struct sem): New type. Actual semaphore type. * semaphoreP.h: Include pthreadP.h. * sem_getvalue.c: Adjust to sem_t change. * sem_init.c: Likewise. * sem_open.c: Likewise. * sem_post.c: Likewise. * sem_timedwait.c: Likewise. * sem_trywait.c: Likewise. * sem_wait.c: Likewise. 2002-10-04 Ulrich Drepper <drepper@redhat.com> * Makefile (tests): Add tst-basic2, tst-exec1, tst-exec3, tst-exec3. * tst-basic2.c: New file. * tst-exec1.c: New file. * tst-exec2.c: New file. * tst-exec3.c: New file. * tst-fork1.c: Remove extra */. * nptl 0.2 released. The API for IA-32 is complete.
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
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); +} |