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/linux/i386 | |
parent | 6938e63f714b15c377d8cbf8e97b6f15b0e1b692 (diff) |
Initial revisioncvs/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/linux/i386')
26 files changed, 2818 insertions, 0 deletions
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 |