diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-07-12 18:26:36 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2007-07-12 18:26:36 +0000 |
commit | 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (patch) | |
tree | 2ea1f8305970753e4a657acb2ccc15ca3eec8e2c /nptl/sysdeps/unix/sysv/linux/i386 | |
parent | 7d58530341304d403a6626d7f7a1913165fe2f32 (diff) | |
download | glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.gz |
2.5-18.1
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386')
21 files changed, 876 insertions, 387 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h index 4d1c9450b5..f53d0e5a72 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 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 @@ -43,11 +43,17 @@ typedef union } pthread_attr_t; +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + /* Data structures for mutex handling. The structure of the attribute type is not exposed on purpose. */ typedef union { - struct + struct __pthread_mutex_s { int __lock; unsigned int __count; @@ -56,7 +62,11 @@ typedef union binary compatibility. */ int __kind; unsigned int __nusers; - int __spins; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; } __data; char __size[__SIZEOF_PTHREAD_MUTEX_T]; long int __align; @@ -155,6 +165,6 @@ typedef union /* Extra attributes for the cleanup functions. */ -#define __cleanup_fct_attribute __attribute ((regparm (1))) +#define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) #endif /* bits/pthreadtypes.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/i386/clone.S b/nptl/sysdeps/unix/sysv/linux/i386/clone.S index 95c17f18e4..675a997e97 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/clone.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/clone.S @@ -1,2 +1,9 @@ -#define RESET_PID -#include <sysdeps/unix/sysv/linux/i386/clone.S> +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <clone.S> +#else +# define RESET_PID +# include_next <clone.S> +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S index 223b111083..88885b735d 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S @@ -22,7 +22,7 @@ #ifndef UP # define LOCK \ cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \ - je,pt 0f; \ + je 0f; \ lock; \ 0: #endif diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S index dc65b709a1..e2da5b04cf 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -41,9 +41,16 @@ .hidden __lll_mutex_lock_wait .align 16 __lll_mutex_lock_wait: + cfi_startproc pushl %edx + cfi_adjust_cfa_offset(4) pushl %ebx + cfi_adjust_cfa_offset(4) pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) movl $2, %edx movl %ecx, %ebx @@ -60,12 +67,19 @@ __lll_mutex_lock_wait: xchgl %eax, (%ebx) /* NB: lock is implied */ testl %eax, %eax - jnz,pn 1b + jnz 1b popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) ret + cfi_endproc .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait @@ -75,17 +89,27 @@ __lll_mutex_lock_wait: .hidden __lll_mutex_timedlock_wait .align 16 __lll_mutex_timedlock_wait: + cfi_startproc /* Check for a valid timeout value. */ cmpl $1000000000, 4(%edx) jae 3f pushl %edi + cfi_adjust_cfa_offset(4) pushl %esi + cfi_adjust_cfa_offset(4) pushl %ebx + cfi_adjust_cfa_offset(4) pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) /* Stack frame for the timespec and timeval structs. */ subl $8, %esp + cfi_adjust_cfa_offset(8) movl %ecx, %ebp movl %edx, %edi @@ -140,12 +164,29 @@ __lll_mutex_timedlock_wait: jnz 7f 6: addl $8, %esp + cfi_adjust_cfa_offset(-8) popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) ret +3: movl $EINVAL, %eax + ret + + cfi_adjust_cfa_offset(24) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) /* Check whether the time expired. */ 7: cmpl $-ETIMEDOUT, %ecx je 5f @@ -157,11 +198,9 @@ __lll_mutex_timedlock_wait: jz 6b jmp 1b -3: movl $EINVAL, %eax - ret - 5: movl $ETIMEDOUT, %eax jmp 6b + cfi_endproc .size __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait #endif @@ -200,9 +239,16 @@ lll_unlock_wake_cb: .hidden __lll_mutex_unlock_wake .align 16 __lll_mutex_unlock_wake: + cfi_startproc pushl %ebx + cfi_adjust_cfa_offset(4) pushl %ecx + cfi_adjust_cfa_offset(4) pushl %edx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%ecx, -12) + cfi_offset(%edx, -16) movl %eax, %ebx movl $0, (%eax) @@ -212,9 +258,16 @@ __lll_mutex_unlock_wake: ENTER_KERNEL popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) popl %ecx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ecx) popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) ret + cfi_endproc .size __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S new file mode 100644 index 0000000000..73d8bc4ccc --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S @@ -0,0 +1,227 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 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 <pthread-errnos.h> +#include <lowlevelrobustlock.h> + + .text + +#ifndef LOCK +# ifdef UP +# define LOCK +# else +# define LOCK lock +# endif +#endif + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + + + .globl __lll_robust_mutex_lock_wait + .type __lll_robust_mutex_lock_wait,@function + .hidden __lll_robust_mutex_lock_wait + .align 16 +__lll_robust_mutex_lock_wait: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl %ecx, %ebx + xorl %esi, %esi /* No timeout. */ + xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + +4: movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + cmpl %edx, %eax /* NB: %edx == 2 */ + je 1f + + LOCK + cmpxchgl %edx, (%ebx) + jnz 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + + movl (%ebx), %eax + +2: test %eax, %eax + jne 4b + + movl %gs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%ebx) + jnz 4b + /* NB: %eax == 0 */ + +3: popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait + + + .globl __lll_robust_mutex_timedlock_wait + .type __lll_robust_mutex_timedlock_wait,@function + .hidden __lll_robust_mutex_timedlock_wait + .align 16 +__lll_robust_mutex_timedlock_wait: + cfi_startproc + /* Check for a valid timeout value. */ + cmpl $1000000000, 4(%edx) + jae 3f + + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + + /* Stack frame for the timespec and timeval structs. */ + subl $12, %esp + cfi_adjust_cfa_offset(12) + + movl %ecx, %ebp + movl %edx, %edi + +1: movl %eax, 8(%esp) + + /* Get current time. */ + movl %esp, %ebx + xorl %ecx, %ecx + movl $SYS_gettimeofday, %eax + ENTER_KERNEL + + /* 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 + subl $1, %ecx +4: testl %ecx, %ecx + js 8f /* Time is already up. */ + + /* Store relative timeout. */ + movl %ecx, (%esp) + movl %edx, 4(%esp) + + movl %ebp, %ebx + + movl 8(%esp), %edx + movl %edx, %eax + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 6f + + cmpl %eax, %edx + je 2f + + LOCK + cmpxchgl %edx, (%ebx) + movl $0, %ecx /* Must use mov to avoid changing cc. */ + jnz 5f + +2: + /* Futex call. */ + movl %esp, %esi + xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %ecx + + movl (%ebx), %eax + +5: testl %eax, %eax + jne 7f + + movl %gs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%ebx) + jnz 7f + +6: addl $12, %esp + cfi_adjust_cfa_offset(-12) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + ret + +3: movl $EINVAL, %eax + ret + + cfi_adjust_cfa_offset(28) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + /* Check whether the time expired. */ +7: cmpl $-ETIMEDOUT, %ecx + jne 1b + +8: movl $ETIMEDOUT, %eax + jmp 6b + cfi_endproc + .size __lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait 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 index 114284c44c..fe7a8b9c66 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S @@ -82,7 +82,7 @@ pthread_barrier_wait: #else cmpl %edx, CURR_EVENT(%ebx) #endif - je,pn 8b + je 8b /* Increment LEFT. If this brings the count back to the initial count unlock the object. */ @@ -92,7 +92,7 @@ pthread_barrier_wait: xaddl %edx, LEFT(%ebx) subl $1, %ecx cmpl %ecx, %edx - jne,pt 10f + jne 10f /* Release the mutex. We cannot release the lock before waking the waiting threads since otherwise a new thread might @@ -131,7 +131,7 @@ pthread_barrier_wait: xaddl %edx, LEFT(%ebx) subl $1, %ecx cmpl %ecx, %edx - jne,pt 5f + jne 5f /* Release the mutex. We cannot release the lock before waking the waiting threads since otherwise a new thread might diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S index 5471c1c927..56f7be8246 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -21,6 +21,7 @@ #include <shlib-compat.h> #include <lowlevelcond.h> #include <kernel-features.h> +#include <pthread-pi-defines.h> #ifdef UP # define LOCK @@ -94,6 +95,10 @@ __pthread_cond_broadcast: 8: cmpl $-1, %edi je 9f + /* XXX: The kernel so far doesn't support requeue to PI futex. */ + testl $PI_BIT, MUTEX_KIND(%edi) + jne 9f + /* Wake up all threads. */ movl $FUTEX_CMP_REQUEUE, %ecx movl $SYS_futex, %eax diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S index 3c5a1db59c..d0f931ff15 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -31,7 +31,9 @@ #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 -#define FUTEX_REQUEUE 3 +#define FUTEX_WAKE_OP 5 + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) #define EINVAL 22 @@ -79,21 +81,46 @@ __pthread_cond_signal: addl $1, (%ebx) /* Wake up one thread. */ - movl $FUTEX_WAKE, %ecx + pushl %esi + pushl %ebp + movl $FUTEX_WAKE_OP, %ecx movl $SYS_futex, %eax movl $1, %edx + movl $1, %esi + movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp + /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for + sysenter. + ENTER_KERNEL */ + int $0x80 + popl %ebp + popl %esi + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpl $-4095, %eax + jae 7f + +6: xorl %eax, %eax + popl %edi + popl %ebx + ret + +7: movl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + /* %edx should be 1 already from $FUTEX_WAKE_OP syscall. + movl $1, %edx */ ENTER_KERNEL /* Unlock. Note that at this point %edi always points to cond_lock. */ 4: LOCK subl $1, (%edi) - jne 5f + je 6b -6: xorl %eax, %eax - popl %edi - popl %ebx - ret + /* Unlock in loop requires wakeup. */ +5: movl %edi, %eax + call __lll_mutex_unlock_wake + jmp 6b /* Initial locking failed. */ 1: @@ -105,10 +132,6 @@ __pthread_cond_signal: call __lll_mutex_lock_wait jmp 2b - /* Unlock in loop requires wakeup. */ -5: movl %edi, %eax - call __lll_mutex_unlock_wake - jmp 6b .size __pthread_cond_signal, .-__pthread_cond_signal versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, GLIBC_2_3_2) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S index 699c2cb227..f481a8e43c 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -406,12 +406,22 @@ __condvar_tw_cleanup: cmpl 20(%esp), %eax jne 3f - addl $1, wakeup_seq(%ebx) + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movl total_seq(%ebx), %eax + movl total_seq+4(%ebx), %edi + cmpl wakeup_seq+4(%ebx), %edi + jb 6f + ja 7f + cmpl wakeup_seq(%ebx), %eax + jbe 7f + +6: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) - addl $1, cond_futex(%ebx) - addl $1, woken_seq(%ebx) +7: addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) 3: subl $(1 << clock_bits), cond_nwaiters(%ebx) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S index d282785151..f16c7d9198 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -297,12 +297,22 @@ __condvar_w_cleanup: cmpl 12(%esp), %eax jne 3f - addl $1, wakeup_seq(%ebx) + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movl total_seq(%ebx), %eax + movl total_seq+4(%ebx), %edi + cmpl wakeup_seq+4(%ebx), %edi + jb 6f + ja 7f + cmpl wakeup_seq(%ebx), %eax + jbe 7f + +6: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) - addl $1, cond_futex(%ebx) - addl $1, woken_seq(%ebx) +7: addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) 3: subl $(1 << clock_bits), cond_nwaiters(%ebx) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S index 3d67329bd1..71e96d2228 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -65,9 +65,14 @@ __new_sem_post: #endif addl $_GLOBAL_OFFSET_TABLE_, %ebx #if USE___THREAD - movl %gs:0, %edx - subl errno@gottpoff(%ebx), %edx +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx movl $EINVAL, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl $EINVAL, %gs:(%edx) +# endif #else call __errno_location@plt movl $EINVAL, (%eax) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S index 5b24476936..bf70e17fca 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -49,12 +49,12 @@ sem_timedwait: movl (%ecx), %eax 2: testl %eax, %eax - je,pn 1f + je 1f leal -1(%eax), %edx LOCK cmpxchgl %edx, (%ecx) - jne,pn 2b + jne 2b xorl %eax, %eax ret @@ -79,10 +79,7 @@ sem_timedwait: jae 6f cfi_offset(3, -16) /* %ebx */ -7: call __pthread_enable_asynccancel - movl %eax, 8(%esp) - - xorl %ecx, %ecx +7: xorl %ecx, %ecx movl %esp, %ebx movl %ecx, %edx movl $SYS_gettimeofday, %eax @@ -105,6 +102,10 @@ sem_timedwait: movl %ecx, (%esp) /* Store relative timeout. */ movl %edx, 4(%esp) + + call __pthread_enable_asynccancel + movl %eax, 8(%esp) + movl 28(%esp), %ebx xorl %ecx, %ecx movl %esp, %esi @@ -117,7 +118,7 @@ sem_timedwait: call __pthread_disable_asynccancel testl %esi, %esi - je,pt 9f + je 9f cmpl $-EWOULDBLOCK, %esi jne 3f @@ -128,7 +129,7 @@ sem_timedwait: leal -1(%eax), %ecx LOCK cmpxchgl %ecx, (%ebx) - jne,pn 8b + jne 8b addl $12, %esp cfi_adjust_cfa_offset(-12) @@ -158,9 +159,14 @@ sem_timedwait: #endif addl $_GLOBAL_OFFSET_TABLE_, %ebx #if USE___THREAD - movl %gs:0, %edx - subl errno@gottpoff(%ebx), %edx +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif #else call __errno_location@plt movl %esi, (%eax) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S index a7c405d95f..fbc3b3c932 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -42,7 +42,7 @@ __new_sem_trywait: leal -1(%eax), %edx LOCK cmpxchgl %edx, (%ecx) - jne,pn 2b + jne 2b xorl %eax, %eax ret @@ -55,9 +55,14 @@ __new_sem_trywait: #endif addl $_GLOBAL_OFFSET_TABLE_, %ecx #if USE___THREAD - movl %gs:0, %edx - subl errno@gottpoff(%ecx), %edx +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ecx), %edx + addl %gs:0, %edx movl $EAGAIN, (%edx) +# else + movl errno@gotntpoff(%ecx), %edx + movl $EAGAIN, %gs:(%edx) +# endif #else call __errno_location@plt movl $EAGAIN, (%eax) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S index b7674dc3ba..b1296275d0 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -57,12 +57,12 @@ __new_sem_wait: cfi_offset(6, -12) /* %esi */ 3: movl (%ebx), %eax 2: testl %eax, %eax - je,pn 1f + je 1f leal -1(%eax), %edx LOCK cmpxchgl %edx, (%ebx) - jne,pn 2b + jne 2b xorl %eax, %eax movl 4(%esp), %esi @@ -73,7 +73,7 @@ __new_sem_wait: cfi_adjust_cfa_offset(-12) ret - cfi_adjust_cfa_offset(8) + cfi_adjust_cfa_offset(12) cfi_offset(3, -8) /* %ebx */ cfi_offset(6, -12) /* %esi */ 1: call __pthread_enable_asynccancel @@ -102,9 +102,14 @@ __new_sem_wait: #endif addl $_GLOBAL_OFFSET_TABLE_, %ebx #if USE___THREAD - movl %gs:0, %edx - subl errno@gottpoff(%ebx), %edx +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif #else call __errno_location@plt movl %esi, (%eax) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S new file mode 100644 index 0000000000..f768e16a7d --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2006 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/lowlevelrobustlock.S" diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S new file mode 100644 index 0000000000..f768e16a7d --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2006 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/lowlevelrobustlock.S" diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h index b86f11c9b4..21de09fe91 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -35,6 +35,9 @@ #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ @@ -65,18 +68,112 @@ #define BUSY_WAIT_NOP asm ("rep; nop") +#define LLL_STUB_UNWIND_INFO_START \ + ".section .eh_frame,\"a\",@progbits\n" \ +"5:\t" ".long 7f-6f # Length of Common Information Entry\n" \ +"6:\t" ".long 0x0 # CIE Identifier Tag\n\t" \ + ".byte 0x1 # CIE Version\n\t" \ + ".ascii \"zR\\0\" # CIE Augmentation\n\t" \ + ".uleb128 0x1 # CIE Code Alignment Factor\n\t" \ + ".sleb128 -4 # CIE Data Alignment Factor\n\t" \ + ".byte 0x8 # CIE RA Column\n\t" \ + ".uleb128 0x1 # Augmentation size\n\t" \ + ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" \ + ".byte 0xc # DW_CFA_def_cfa\n\t" \ + ".uleb128 0x4\n\t" \ + ".uleb128 0x0\n\t" \ + ".align 4\n" \ +"7:\t" ".long 17f-8f # FDE Length\n" \ +"8:\t" ".long 8b-5b # FDE CIE offset\n\t" \ + ".long 1b-. # FDE initial location\n\t" \ + ".long 4b-1b # FDE address range\n\t" \ + ".uleb128 0x0 # Augmentation size\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 10f-9f\n" \ +"9:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-1b\n" +#define LLL_STUB_UNWIND_INFO_END \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 12f-11f\n" \ +"11:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-2b\n" \ +"12:\t" ".byte 0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 16f-13f\n" \ +"13:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 15f-14f\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"14:\t" ".4byte 3b-.\n\t" \ + ".byte 0x1c # DW_OP_minus\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"15:\t" ".4byte 18f-.\n\t" \ + ".byte 0x22 # DW_OP_plus\n" \ +"16:\t" ".align 4\n" \ +"17:\t" ".previous\n" + +/* Unwind info for + 1: lea ..., ... + 2: call ... + 3: jmp 18f + 4: + snippet. */ +#define LLL_STUB_UNWIND_INFO_3 \ +LLL_STUB_UNWIND_INFO_START \ +"10:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + +/* Unwind info for + 1: lea ..., ... + 0: movl ..., ... + 2: call ... + 3: jmp 18f + 4: + snippet. */ +#define LLL_STUB_UNWIND_INFO_4 \ +LLL_STUB_UNWIND_INFO_START \ +"10:\t" ".byte 0x40 + (0b-1b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 20f-19f\n" \ +"19:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-0b\n" \ +"20:\t" ".byte 0x40 + (2b-0b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + + #define lll_futex_wait(futex, val) \ - do { \ - int __ignore; \ + ({ \ + int __status; \ register __typeof (val) _val asm ("edx") = (val); \ __asm __volatile (LLL_EBX_LOAD \ LLL_ENTER_KERNEL \ LLL_EBX_LOAD \ - : "=a" (__ignore) \ + : "=a" (__status) \ : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0), \ "c" (FUTEX_WAIT), "d" (_val), \ - "i" (offsetof (tcbhead_t, sysinfo))); \ - } while (0) + "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ + __status; \ + }) + + +#define lll_futex_timed_wait(futex, val, timeout) \ + ({ \ + int __status; \ + register __typeof (val) _val asm ("edx") = (val); \ + __asm __volatile (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__status) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ + "c" (FUTEX_WAIT), "d" (_val), \ + "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ + __status; \ + }) #define lll_futex_wake(futex, nr) \ @@ -121,6 +218,16 @@ extern int __lll_mutex_unlock_wake (int *__futex) ret; }) +#define lll_robust_mutex_trylock(futex, id) \ + ({ int ret; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (id), "m" (futex), \ + "0" (LLL_MUTEX_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + + #define lll_mutex_cond_trylock(futex) \ ({ int ret; \ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ @@ -137,18 +244,39 @@ extern int __lll_mutex_unlock_wake (int *__futex) "jnz _L_mutex_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_lock_%=,@function\n" \ - "_L_mutex_lock_%=:\n\t" \ - "leal %2, %%ecx\n\t" \ - "call __lll_mutex_lock_wait\n\t" \ - "jmp 1f\n\t" \ - ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \ + "_L_mutex_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_mutex_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_mutex_lock_%=, 4b-1b\n\t" \ ".previous\n" \ - "1:" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (1), "m" (futex) \ : "memory"); }) +#define lll_robust_mutex_lock(futex, id) \ + ({ int result, ignore; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_robust_mutex_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_mutex_lock_%=,@function\n" \ + "_L_robust_mutex_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_robust_mutex_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_mutex_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=a" (result), "=c" (ignore), "=m" (futex) \ + : "0" (0), "1" (id), "m" (futex) \ + : "memory"); \ + result; }) + + /* Special version of lll_mutex_lock which causes the unlock function to always wakeup waiters. */ #define lll_mutex_cond_lock(futex) \ @@ -157,32 +285,54 @@ extern int __lll_mutex_unlock_wake (int *__futex) "jnz _L_mutex_cond_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_cond_lock_%=,@function\n" \ - "_L_mutex_cond_lock_%=:\n\t" \ - "leal %2, %%ecx\n\t" \ - "call __lll_mutex_lock_wait\n\t" \ - "jmp 1f\n\t" \ - ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n" \ + "_L_mutex_cond_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_mutex_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_mutex_cond_lock_%=, 4b-1b\n\t" \ ".previous\n" \ - "1:" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (2), "m" (futex) \ : "memory"); }) +#define lll_robust_mutex_cond_lock(futex, id) \ + ({ int result, ignore; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_robust_mutex_cond_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_mutex_cond_lock_%=,@function\n" \ + "_L_robust_mutex_cond_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_robust_mutex_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_mutex_cond_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=a" (result), "=c" (ignore), "=m" (futex) \ + : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex) \ + : "memory"); \ + result; }) + + #define lll_mutex_timedlock(futex, timeout) \ ({ int result, ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ "jnz _L_mutex_timedlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_timedlock_%=,@function\n" \ - "_L_mutex_timedlock_%=:\n\t" \ - "leal %3, %%ecx\n\t" \ - "movl %7, %%edx\n\t" \ - "call __lll_mutex_timedlock_wait\n\t" \ - "jmp 1f\n\t" \ - ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\ + "_L_mutex_timedlock_%=:\n" \ + "1:\tleal %3, %%ecx\n" \ + "0:\tmovl %7, %%edx\n" \ + "2:\tcall __lll_mutex_timedlock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_mutex_timedlock_%=, 4b-1b\n\t" \ ".previous\n" \ - "1:" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ : "=a" (result), "=c" (ignore1), "=&d" (ignore2), \ "=m" (futex) \ : "0" (0), "1" (1), "m" (futex), "m" (timeout) \ @@ -190,24 +340,95 @@ extern int __lll_mutex_unlock_wake (int *__futex) result; }) +#define lll_robust_mutex_timedlock(futex, timeout, id) \ + ({ int result, ignore1, ignore2; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ + "jnz _L_robust_mutex_timedlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_mutex_timedlock_%=,@function\n" \ + "_L_robust_mutex_timedlock_%=:\n" \ + "1:\tleal %3, %%ecx\n" \ + "0:\tmovl %7, %%edx\n" \ + "2:\tcall __lll_robust_mutex_timedlock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_mutex_timedlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (result), "=c" (ignore1), "=&d" (ignore2), \ + "=m" (futex) \ + : "0" (0), "1" (id), "m" (futex), "m" (timeout) \ + : "memory"); \ + result; }) + + #define lll_mutex_unlock(futex) \ (void) ({ int ignore; \ - __asm __volatile (LOCK_INSTR "subl $1,%0\n\t" \ + __asm __volatile (LOCK_INSTR "subl $1, %0\n\t" \ "jne _L_mutex_unlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_unlock_%=,@function\n" \ - "_L_mutex_unlock_%=:\n\t" \ - "leal %0, %%eax\n\t" \ - "call __lll_mutex_unlock_wake\n\t" \ - "jmp 1f\n\t" \ - ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ + "_L_mutex_unlock_%=:\n" \ + "1:\tleal %0, %%eax\n" \ + "2:\tcall __lll_mutex_unlock_wake\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_mutex_unlock_%=, 4b-1b\n\t" \ ".previous\n" \ - "1:" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ : "=m" (futex), "=&a" (ignore) \ : "m" (futex) \ : "memory"); }) +#define lll_robust_mutex_unlock(futex) \ + (void) ({ int ignore; \ + __asm __volatile (LOCK_INSTR "andl %2, %0\n\t" \ + "jne _L_robust_mutex_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_mutex_unlock_%=,@function\n" \ + "_L_robust_mutex_unlock_%=:\n\t" \ + "1:\tleal %0, %%eax\n" \ + "2:\tcall __lll_mutex_unlock_wake\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_mutex_unlock_%=, 4b-1b\n\t"\ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=m" (futex), "=&a" (ignore) \ + : "i" (FUTEX_WAITERS), "m" (futex) \ + : "memory"); }) + + +#define lll_robust_mutex_dead(futex) \ + (void) ({ int __ignore; \ + register int _nr asm ("edx") = 1; \ + __asm __volatile (LOCK_INSTR "orl %5, (%2)\n\t" \ + LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (&(futex)), \ + "c" (FUTEX_WAKE), "d" (_nr), \ + "i" (FUTEX_OWNER_DIED), \ + "i" (offsetof (tcbhead_t, sysinfo))); }) + + +#define lll_futex_wake(futex, nr) \ + do { \ + int __ignore; \ + register __typeof (nr) _nr asm ("edx") = (nr); \ + __asm __volatile (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), \ + "c" (FUTEX_WAKE), "d" (_nr), \ + "i" (0) /* phony, to align next arg's number */, \ + "i" (offsetof (tcbhead_t, sysinfo))); \ + } while (0) + + #define lll_mutex_islocked(futex) \ (futex != 0) @@ -250,7 +471,7 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; # define lll_trylock(futex) \ ({ unsigned char ret; \ __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \ - "je,pt 0f\n\t" \ + "je 0f\n\t" \ "lock\n" \ "0:\tcmpxchgl %2, %1; setne %0" \ : "=a" (ret), "=m" (futex) \ @@ -264,19 +485,20 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; # define lll_lock(futex) \ (void) ({ int ignore1, ignore2; \ __asm __volatile ("cmpl $0, %%gs:%P6\n\t" \ - "je,pt 0f\n\t" \ + "je 0f\n\t" \ "lock\n" \ "0:\tcmpxchgl %1, %2\n\t" \ - "jnz _L_mutex_lock_%=\n\t" \ + "jnz _L_lock_%=\n\t" \ ".subsection 1\n\t" \ - ".type _L_mutex_lock_%=,@function\n" \ - "_L_mutex_lock_%=:\n\t" \ - "leal %2, %%ecx\n\t" \ - "call __lll_mutex_lock_wait\n\t" \ - "jmp 1f\n\t" \ - ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \ + ".type _L_lock_%=,@function\n" \ + "_L_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_mutex_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_lock_%=, 4b-1b\n\t" \ ".previous\n" \ - "1:" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (1), "m" (futex), \ "i" (offsetof (tcbhead_t, multiple_threads)) \ @@ -286,19 +508,20 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; # define lll_unlock(futex) \ (void) ({ int ignore; \ __asm __volatile ("cmpl $0, %%gs:%P3\n\t" \ - "je,pt 0f\n\t" \ + "je 0f\n\t" \ "lock\n" \ - "0:\tsubl $1,%0\n\t" \ - "jne _L_mutex_unlock_%=\n\t" \ + "0:\tsubl $1,%0\n\t" \ + "jne _L_unlock_%=\n\t" \ ".subsection 1\n\t" \ - ".type _L_mutex_unlock_%=,@function\n" \ - "_L_mutex_unlock_%=:\n\t" \ - "leal %0, %%eax\n\t" \ - "call __lll_mutex_unlock_wake\n\t" \ - "jmp 1f\n\t" \ - ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ + ".type _L_unlock_%=,@function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleal %0, %%eax\n" \ + "2:\tcall __lll_mutex_unlock_wake\n" \ + "3:\tjmp 18f\n\t" \ + "4:\t.size _L_unlock_%=, 4b-1b\n\t" \ ".previous\n" \ - "1:" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ : "=m" (futex), "=&a" (ignore) \ : "m" (futex), \ "i" (offsetof (tcbhead_t, multiple_threads)) \ @@ -325,12 +548,13 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; "1:\tmovl %1, %%eax\n\t" \ LLL_ENTER_KERNEL \ "cmpl $0, (%%ebx)\n\t" \ - "jne,pn 1b\n\t" \ + "jne 1b\n\t" \ LLL_EBX_LOAD \ : "=&a" (__ignore) \ : "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0), \ "c" (FUTEX_WAIT), "d" (_tid), \ - "i" (offsetof (tcbhead_t, sysinfo))); \ + "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ } while (0) extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h index cc3282fbdd..6557359b43 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/not-cancel.h @@ -1,5 +1,5 @@ /* Uncancelable versions of cancelable interfaces. Linux/NPTL version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -26,13 +26,21 @@ extern int __close_nocancel (int) attribute_hidden; extern int __read_nocancel (int, void *, size_t) attribute_hidden; extern int __write_nocancel (int, const void *, size_t) attribute_hidden; extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; +extern int __openat_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +extern int __openat64_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; #else -#define __open_nocancel(name, ...) __open (name, __VA_ARGS__) -#define __close_nocancel(fd) __close (fd) -#define __read_nocancel(fd, buf, len) __read (fd, buf, len) -#define __write_nocancel(fd, buf, len) __write (fd, buf, len) -#define __waitpid_nocancel(pid, stat_loc, options) \ +# define __open_nocancel(name, ...) __open (name, __VA_ARGS__) +# define __close_nocancel(fd) __close (fd) +# define __read_nocancel(fd, buf, len) __read (fd, buf, len) +# define __write_nocancel(fd, buf, len) __write (fd, buf, len) +# define __waitpid_nocancel(pid, stat_loc, options) \ __waitpid (pid, stat_loc, options) +# define __openat_nocancel(fd, fname, oflag, mode) \ + openat (fd, fname, oflag, mode) +# define __openat64_nocancel(fd, fname, oflag, mode) \ + openat64 (fd, fname, oflag, mode) #endif /* Uncancelable open. */ @@ -41,6 +49,16 @@ extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; #define open_not_cancel_2(name, flags) \ __open_nocancel (name, flags) +/* Uncancelable openat. */ +#define openat_not_cancel(fd, fname, oflag, mode) \ + __openat_nocancel (fd, fname, oflag, mode) +#define openat_not_cancel_3(fd, fname, oflag) \ + __openat_nocancel (fd, fname, oflag, 0) +#define openat64_not_cancel(fd, fname, oflag, mode) \ + __openat64_nocancel (fd, fname, oflag, mode) +#define openat64_not_cancel_3(fd, fname, oflag) \ + __openat64_nocancel (fd, fname, oflag, 0) + /* Uncancelable close. */ #define close_not_cancel(fd) \ __close_nocancel (fd) @@ -73,3 +91,15 @@ extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; # define waitpid_not_cancel(pid, stat_loc, options) \ INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) #endif + +/* Uncancelable pause. */ +#define pause_not_cancel() \ + __pause_nocancel () + +/* Uncancelable nanosleep. */ +#define nanosleep_not_cancel(requested_time, remaining) \ + __nanosleep_nocancel (requested_time, remaining) + +/* Uncancelable sigsuspend. */ +#define sigsuspend_not_cancel(set) \ + __sigsuspend_nocancel (set) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/smp.h b/nptl/sysdeps/unix/sysv/linux/i386/smp.h new file mode 100644 index 0000000000..f68a0c0758 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/i386/smp.h @@ -0,0 +1,56 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/utsname.h> +#include <not-cancel.h> + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + union + { + struct utsname uts; + char buf[512]; + } u; + char *cp; + + /* Try reading the number using `sysctl' first. */ + if (uname (&u.uts) == 0) + cp = u.uts.version; + else + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || read_not_cancel (fd, u.buf, sizeof (u.buf)) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + u.buf[0] = '\0'; + + close_not_cancel_no_status (fd); + cp = u.buf; + } + + return strstr (cp, "SMP") != NULL; +} diff --git a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h index 8142455781..d60dcd33d5 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. @@ -29,7 +29,6 @@ # define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ - L(name##START): \ cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \ jne L(pseudo_cancel); \ .type __##syscall_name##_nocancel,@function; \ @@ -51,258 +50,11 @@ POPSTATE_##args \ cmpl $-4095, %eax; \ jae SYSCALL_ERROR_LABEL; \ - L(pseudo_end): \ - \ - /* Create unwinding information for the syscall wrapper. */ \ - .section .eh_frame,"a",@progbits; \ - L(STARTFRAME): \ - /* Length of the CIE. */ \ - .long L(ENDCIE)-L(STARTCIE); \ - L(STARTCIE): \ - /* CIE ID. */ \ - .long 0; \ - /* Version number. */ \ - .byte 1; \ - /* NUL-terminated augmentation string. */ \ - AUGMENTATION_STRING; \ - /* Code alignment factor. */ \ - .uleb128 1; \ - /* Data alignment factor. */ \ - .sleb128 -4; \ - /* Return address register column. */ \ - .byte 8; \ - /* Optional augmentation parameter. */ \ - AUGMENTATION_PARAM \ - /* Start of the table initialization. */ \ - .byte 0xc; /* DW_CFA_def_cfa */ \ - .uleb128 4; \ - .uleb128 4; \ - .byte 0x88; /* DW_CFA_offset, column 0x8 */ \ - .uleb128 1; \ - .align 4; \ - L(ENDCIE): \ - /* Length of the FDE. */ \ - .long L(ENDFDE)-L(STARTFDE); \ - L(STARTFDE): \ - /* CIE pointer. */ \ - .long L(STARTFDE)-L(STARTFRAME); \ - /* Start address of the code. */ \ - START_SYMBOL_REF (name); \ - /* Length of the code. */ \ - .long L(name##END)-L(name##START); \ - /* Augmentation data. */ \ - AUGMENTATION_PARAM_FDE \ - /* The rest of the code depends on the number of parameters the syscall \ - takes. */ \ - EH_FRAME_##args(name); \ - .align 4; \ - L(ENDFDE): \ - .previous - -# ifdef SHARED -/* NUL-terminated augmentation string. Note "z" means there is an - augmentation value later on. */ -# define AUGMENTATION_STRING .string "zR" -# define AUGMENTATION_PARAM \ - /* Augmentation value length. */ \ - .uleb128 1; \ - /* Encoding: DW_EH_PE_pcrel + DW_EH_PE_sdata4. */ \ - .byte 0x1b; -# define AUGMENTATION_PARAM_FDE \ - /* No augmentation data. */ \ - .uleb128 0; -# define START_SYMBOL_REF(name) \ - /* PC-relative start address of the code. */ \ - .long L(name##START)-. -# else -/* No augmentation. */ -# define AUGMENTATION_STRING .ascii "\0" -# define AUGMENTATION_PARAM /* nothing */ -# define AUGMENTATION_PARAM_FDE /* nothing */ -# define START_SYMBOL_REF(name) \ - /* Absolute start address of the code. */ \ - .long L(name##START) -# endif - -/* Callframe description for syscalls without parameters. This is very - simple. The only place the stack pointer is changed is when the old - cancellation state value is saved. */ -# define EH_FRAME_0(name) \ - .byte 0x40+L(PUSHSTATE)-L(name##START); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x40+L(POPSTATE)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4 - -/* For syscalls with one and two parameters the code is the same as for - those which take no parameter. */ -# define EH_FRAME_1(name) \ - .byte 0x40+L(SAVEBX1)-L(name##START); /* DW_CFA_advance_loc+N */ \ - .byte 9; /* DW_CFA_register */ \ - .uleb128 3; /* %ebx */ \ - .uleb128 2; /* %edx */ \ - .byte 0x40+L(RESTBX1)-L(SAVEBX1); /* DW_CFA_advance_loc+N */ \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(PUSHSTATE)-L(RESTBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x40+L(SAVEBX2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \ - .byte 9; /* DW_CFA_register */ \ - .uleb128 3; /* %ebx */ \ - .uleb128 2; /* %edx */ \ - .byte 0x40+L(RESTBX2)-L(SAVEBX2); /* DW_CFA_advance_loc+N */ \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(POPSTATE)-L(RESTBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4 - -# define EH_FRAME_2(name) EH_FRAME_1 (name) - -/* For syscalls with three parameters the stack pointer is changed - also to save the content of the %ebx register. */ -# define EH_FRAME_3(name) \ - .byte 0x40+L(PUSHBX1)-L(name##START); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x83; /* DW_CFA_offset %ebx */ \ - .uleb128 2; \ - .byte 0x40+L(POPBX1)-L(PUSHBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4; \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(PUSHSTATE)-L(POPBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x40+L(PUSHBX2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0x83; /* DW_CFA_offset %ebx */ \ - .uleb128 3; \ - .byte 0x40+L(POPBX2)-L(PUSHBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(POPSTATE)-L(POPBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4 - -/* With four parameters the syscall wrappers have to save %ebx and %esi. */ -# define EH_FRAME_4(name) \ - .byte 0x40+L(PUSHSI1)-L(name##START); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x86; /* DW_CFA_offset %esi */ \ - .uleb128 2; \ - .byte 0x40+L(PUSHBX1)-L(PUSHSI1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0x83; /* DW_CFA_offset %ebx */ \ - .uleb128 3; \ - .byte 0x40+L(POPBX1)-L(PUSHBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(POPSI1)-L(POPBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4; \ - .byte 0xc6; /* DW_CFA_restore %esi */ \ - .byte 0x40+L(PUSHSTATE)-L(POPSI1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x40+L(PUSHSI2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0x86; /* DW_CFA_offset %esi */ \ - .uleb128 3; \ - .byte 0x40+L(PUSHBX2)-L(PUSHSI2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 16; \ - .byte 0x83; /* DW_CFA_offset %ebx */ \ - .uleb128 4; \ - .byte 0x40+L(POPBX2)-L(PUSHBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(POPSI2)-L(POPBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0xc6; /* DW_CFA_restore %esi */ \ - .byte 0x40+L(POPSTATE)-L(POPSI2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4 - -/* With five parameters the syscall wrappers have to save %ebx, %esi, - and %edi. */ -# define EH_FRAME_5(name) \ - .byte 0x40+L(PUSHDI1)-L(name##START); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x87; /* DW_CFA_offset %edi */ \ - .uleb128 2; \ - .byte 0x40+L(PUSHSI1)-L(PUSHDI1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0x86; /* DW_CFA_offset %esi */ \ - .uleb128 3; \ - .byte 0x40+L(PUSHBX1)-L(PUSHSI1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 16; \ - .byte 0x83; /* DW_CFA_offset %ebx */ \ - .uleb128 4; \ - .byte 0x40+L(POPBX1)-L(PUSHBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(POPSI1)-L(POPBX1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0xc6; /* DW_CFA_restore %esi */ \ - .byte 0x40+L(POPDI1)-L(POPSI1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4; \ - .byte 0xc7; /* DW_CFA_restore %edi */ \ - .byte 0x40+L(PUSHSTATE)-L(POPDI1); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0x40+L(PUSHDI2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0x87; /* DW_CFA_offset %edi */ \ - .uleb128 3; \ - .byte 0x40+L(PUSHSI2)-L(PUSHDI2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 16; \ - .byte 0x86; /* DW_CFA_offset %esi */ \ - .uleb128 4; \ - .byte 0x40+L(PUSHBX2)-L(PUSHSI2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 20; \ - .byte 0x83; /* DW_CFA_offset %ebx */ \ - .uleb128 5; \ - .byte 0x40+L(POPBX2)-L(PUSHBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 16; \ - .byte 0xc3; /* DW_CFA_restore %ebx */ \ - .byte 0x40+L(POPSI2)-L(POPBX2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 12; \ - .byte 0xc6; /* DW_CFA_restore %esi */ \ - .byte 0x40+L(POPDI2)-L(POPSI2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 8; \ - .byte 0xc7; /* DW_CFA_restore %edi */ \ - .byte 0x40+L(POPSTATE)-L(POPDI2); /* DW_CFA_advance_loc+N */ \ - .byte 14; /* DW_CFA_def_cfa_offset */ \ - .uleb128 4 - - -# undef ASM_SIZE_DIRECTIVE -# define ASM_SIZE_DIRECTIVE(name) L(name##END): .size name,.-name; + L(pseudo_end): # define SAVE_OLDTYPE_0 movl %eax, %ecx; # define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 -# define SAVE_OLDTYPE_2 pushl %eax; L(PUSHSTATE): +# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); # define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 # define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 # define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 @@ -313,11 +65,13 @@ # define _PUSHCARGS_0 /* No arguments to push. */ # define _POPCARGS_0 /* No arguments to pop. */ -# define PUSHCARGS_1 movl %ebx, %edx; L(SAVEBX2): PUSHCARGS_0 +# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 # define DOCARGS_1 _DOARGS_1 (4) -# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; L(RESTBX2): -# define _PUSHCARGS_1 pushl %ebx; L(PUSHBX2): _PUSHCARGS_0 -# define _POPCARGS_1 _POPCARGS_0; popl %ebx; L(POPBX2): +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebx); # define PUSHCARGS_2 PUSHCARGS_1 # define DOCARGS_2 _DOARGS_2 (12) @@ -334,14 +88,18 @@ # define PUSHCARGS_4 _PUSHCARGS_4 # define DOCARGS_4 _DOARGS_4 (28) # define POPCARGS_4 _POPCARGS_4 -# define _PUSHCARGS_4 pushl %esi; L(PUSHSI2): _PUSHCARGS_3 -# define _POPCARGS_4 _POPCARGS_3; popl %esi; L(POPSI2): +# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (esi); # define PUSHCARGS_5 _PUSHCARGS_5 # define DOCARGS_5 _DOARGS_5 (36) # define POPCARGS_5 _POPCARGS_5 -# define _PUSHCARGS_5 pushl %edi; L(PUSHDI2): _PUSHCARGS_4 -# define _POPCARGS_5 _POPCARGS_4; popl %edi; L(POPDI2): +# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# define _POPCARGS_5 _POPCARGS_4; popl %edi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (edi); # ifdef IS_IN_libpthread # define CENABLE call __pthread_enable_asynccancel; @@ -356,9 +114,11 @@ # error Unsupported library # endif # define POPSTATE_0 \ - pushl %eax; L(PUSHSTATE): movl %ecx, %eax; CDISABLE; popl %eax; L(POPSTATE): + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); # define POPSTATE_1 POPSTATE_0 -# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; L(POPSTATE): +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ + cfi_adjust_cfa_offset (-4); # define POPSTATE_3 POPSTATE_2 # define POPSTATE_4 POPSTATE_3 # define POPSTATE_5 POPSTATE_4 @@ -377,3 +137,9 @@ # define NO_CANCELLATION 1 #endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/i386/vfork.S b/nptl/sysdeps/unix/sysv/linux/i386/vfork.S index 52336102c7..37f0842051 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/vfork.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/vfork.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1999,2002,2004,2006 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 @@ -16,10 +16,17 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <tcb-offsets.h> +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <vfork.S> +#else + +# include <tcb-offsets.h> /* Save the PID value. */ -#define SAVE_PID \ +# define SAVE_PID \ movl %gs:PID, %edx; \ movl %edx, %eax; \ negl %eax; \ @@ -28,11 +35,11 @@ 1: movl %eax, %gs:PID /* Restore the old PID value in the parent. */ -#define RESTORE_PID \ +# define RESTORE_PID \ testl %eax, %eax; \ je 1f; \ movl %edx, %gs:PID; \ 1: - -#include <sysdeps/unix/sysv/linux/i386/vfork.S> +# include_next <vfork.S> +#endif |