aboutsummaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-05-26 01:31:40 +0000
committerUlrich Drepper <drepper@redhat.com>2007-05-26 01:31:40 +0000
commit3d2dd6ca71fa9933e3413625d606f4b486661409 (patch)
tree50d0226ef087227746ee01737977810d8120951a /nptl
parent2af4e3e5668f70976762282cfff715e68929aa81 (diff)
downloadglibc-3d2dd6ca71fa9933e3413625d606f4b486661409.tar
glibc-3d2dd6ca71fa9933e3413625d606f4b486661409.tar.gz
glibc-3d2dd6ca71fa9933e3413625d606f4b486661409.tar.bz2
glibc-3d2dd6ca71fa9933e3413625d606f4b486661409.zip
* semaphoreP.h: Declare __old_sem_init and __old_sem_wait.
* sem_init.c (__new_sem_init): Rewrite to initialize all three fields in the structure. (__old_sem_init): New function. * sem_open.c: Initialize all fields of the structure. * sem_getvalue.c: Adjust for renamed element. * sysdeps/unix/sysv/linux/Makefile [subdir=nptl] (gen-as-const-headers): Add structsem.sym. * sysdeps/unix/sysv/linux/structsem.sym: New file. * sysdeps/unix/sysv/linux/internaltypes.h: Rename struct sem to struct new_sem. Add struct old_sem. * sysdeps/unix/sysv/linux/sem_post.c: Wake only when there are waiters. * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. * sysdeps/unix/sysv/linux/sem_wait.c: Indicate that there are waiters. * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. * Makefile (tests): Add tst-sem10, tst-sem11, tst-sem12. * tst-sem10.c: New file. * tst-sem11.c: New file. * tst-sem12.c: New file. * tst-typesizes.c: Test struct new_sem and struct old_sem instead of struct sem. 2007-05-25 Ulrich Drepper <drepper@redhat.com>
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog29
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/sem_getvalue.c6
-rw-r--r--nptl/sem_init.c47
-rw-r--r--nptl/sem_open.c12
-rw-r--r--nptl/semaphoreP.h4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Makefile5
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S230
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S284
-rw-r--r--nptl/sysdeps/unix/sysv/linux/internaltypes.h13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_post.c30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_timedwait.c68
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_wait.c60
-rw-r--r--nptl/sysdeps/unix/sysv/linux/structsem.sym10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S17
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S223
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S222
-rw-r--r--nptl/tst-typesizes.c5
19 files changed, 1088 insertions, 197 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 923364cae5..4778511191 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,4 +1,33 @@
2007-05-25 Ulrich Drepper <drepper@redhat.com>
+
+ * semaphoreP.h: Declare __old_sem_init and __old_sem_wait.
+ * sem_init.c (__new_sem_init): Rewrite to initialize all three
+ fields in the structure.
+ (__old_sem_init): New function.
+ * sem_open.c: Initialize all fields of the structure.
+ * sem_getvalue.c: Adjust for renamed element.
+ * sysdeps/unix/sysv/linux/Makefile [subdir=nptl]
+ (gen-as-const-headers): Add structsem.sym.
+ * sysdeps/unix/sysv/linux/structsem.sym: New file.
+ * sysdeps/unix/sysv/linux/internaltypes.h: Rename struct sem to
+ struct new_sem. Add struct old_sem.
+ * sysdeps/unix/sysv/linux/sem_post.c: Wake only when there are waiters.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise.
+ * sysdeps/unix/sysv/linux/sem_wait.c: Indicate that there are waiters.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise.
+ * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise.
+ * Makefile (tests): Add tst-sem10, tst-sem11, tst-sem12.
+ * tst-sem10.c: New file.
+ * tst-sem11.c: New file.
+ * tst-sem12.c: New file.
+ * tst-typesizes.c: Test struct new_sem and struct old_sem instead
+ of struct sem.
+
+2007-05-25 Ulrich Drepper <drepper@redhat.com>
Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
diff --git a/nptl/Makefile b/nptl/Makefile
index 42f2fe699f..a9eac89e41 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -218,7 +218,7 @@ tests = tst-typesizes \
tst-once1 tst-once2 tst-once3 tst-once4 \
tst-key1 tst-key2 tst-key3 tst-key4 \
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
- tst-sem8 tst-sem9 \
+ tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 \
tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
tst-align tst-align2 tst-align3 \
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
diff --git a/nptl/sem_getvalue.c b/nptl/sem_getvalue.c
index 6bc7ea82b4..3b17e59629 100644
--- a/nptl/sem_getvalue.c
+++ b/nptl/sem_getvalue.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -27,11 +27,11 @@ __new_sem_getvalue (sem, sval)
sem_t *sem;
int *sval;
{
- struct sem *isem = (struct sem *) sem;
+ struct new_sem *isem = (struct new_sem *) sem;
/* XXX Check for valid SEM parameter. */
- *sval = isem->count;
+ *sval = isem->value;
return 0;
}
diff --git a/nptl/sem_init.c b/nptl/sem_init.c
index 8709911ac3..e29d900588 100644
--- a/nptl/sem_init.c
+++ b/nptl/sem_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -22,6 +22,7 @@
#include <lowlevellock.h>
#include <shlib-compat.h>
#include "semaphoreP.h"
+#include <kernel-features.h>
int
@@ -38,18 +39,50 @@ __new_sem_init (sem, pshared, value)
}
/* Map to the internal type. */
- struct sem *isem = (struct sem *) sem;
+ struct new_sem *isem = (struct new_sem *) sem;
- /* Use the value the user provided. */
- isem->count = value;
+ /* Use the values the user provided. */
+ isem->value = value;
+#ifdef __ASSUME_PRIVATE_FUTEX
+ isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG;
+#else
+ isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF,
+ header.private_futex);
+#endif
- /* We can completely ignore the PSHARED parameter since inter-process
- use needs no special preparation. */
+ isem->nwaiters = 0;
return 0;
}
versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
+
+
+
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_init, __old_sem_init)
+int
+attribute_compat_text_section
+__old_sem_init (sem, pshared, value)
+ sem_t *sem;
+ int pshared;
+ unsigned int value;
+{
+ /* Parameter sanity check. */
+ if (__builtin_expect (value > SEM_VALUE_MAX, 0))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* Map to the internal type. */
+ struct old_sem *isem = (struct old_sem *) sem;
+
+ /* Use the value the user provided. */
+ isem->value = value;
+
+ /* We cannot store the PSHARED attribute. So we always use the
+ operations needed for shared semaphores. */
+
+ return 0;
+}
compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
#endif
diff --git a/nptl/sem_open.c b/nptl/sem_open.c
index 66bcb13aec..27d308e920 100644
--- a/nptl/sem_open.c
+++ b/nptl/sem_open.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -304,12 +304,14 @@ sem_open (const char *name, int oflag, ...)
/* Create the initial file content. */
sem_t initsem;
- struct sem *iinitsem = (struct sem *) &initsem;
- iinitsem->count = value;
+ struct new_sem *iinitsem = (struct new_sem *) &initsem;
+ iinitsem->value = value;
+ iinitsem->private = 0;
+ iinitsem->nwaiters = 0;
/* Initialize the remaining bytes as well. */
- memset ((char *) &initsem + sizeof (struct sem), '\0',
- sizeof (sem_t) - sizeof (struct sem));
+ memset ((char *) &initsem + sizeof (struct new_sem), '\0',
+ sizeof (sem_t) - sizeof (struct new_sem));
tmpfname = (char *) alloca (mountpoint.dirlen + 6 + 1);
char *xxxxxx = __mempcpy (tmpfname, mountpoint.dir, mountpoint.dirlen);
diff --git a/nptl/semaphoreP.h b/nptl/semaphoreP.h
index 754609a1a8..9659059900 100644
--- a/nptl/semaphoreP.h
+++ b/nptl/semaphoreP.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -60,8 +60,10 @@ extern int __sem_search (const void *a, const void *b) attribute_hidden;
/* Prototypes of functions with multiple interfaces. */
extern int __new_sem_init (sem_t *sem, int pshared, unsigned int value);
+extern int __old_sem_init (sem_t *sem, int pshared, unsigned int value);
extern int __new_sem_destroy (sem_t *sem);
extern int __new_sem_post (sem_t *sem);
extern int __new_sem_wait (sem_t *sem);
+extern int __old_sem_wait (sem_t *sem);
extern int __new_sem_trywait (sem_t *sem);
extern int __new_sem_getvalue (sem_t *sem, int *sval);
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
index cfcdb6d97f..ad5ae6ad12 100644
--- a/nptl/sysdeps/unix/sysv/linux/Makefile
+++ b/nptl/sysdeps/unix/sysv/linux/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -25,7 +25,8 @@ libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock
gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \
lowlevelbarrier.sym unwindbuf.sym \
- lowlevelrobustlock.sym pthread-pi-defines.sym
+ lowlevelrobustlock.sym pthread-pi-defines.sym \
+ structsem.sym
endif
ifeq ($(subdir),posix)
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 71e96d2228..e66db146ec 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, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -20,6 +20,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <pthread-errnos.h>
+#include <structsem.h>
#ifndef UP
# define LOCK lock
@@ -40,19 +41,26 @@ __new_sem_post:
pushl %ebx
movl 8(%esp), %ebx
- movl $1, %edx
+
LOCK
- xaddl %edx, (%ebx)
+#if VALUE == 0
+ addl $1, (%ebx)
+#else
+ addl $1, VALUE(%ebx)
+#endif
+
+ cmpl $0, NWAITERS(%ebx)
+ je 2f
movl $SYS_futex, %eax
movl $FUTEX_WAKE, %ecx
- addl $1, %edx
+ movl $1, %edx
ENTER_KERNEL
testl %eax, %eax
js 1f
- xorl %eax, %eax
+2: xorl %eax, %eax
popl %ebx
ret
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 bf70e17fca..3677ab3bf9 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
@@ -20,6 +20,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <pthread-errnos.h>
+#include <structsem.h>
#ifndef UP
# define LOCK lock
@@ -32,19 +33,18 @@
#define FUTEX_WAKE 1
+#if VALUE != 0
+# error "code needs to be rewritten for VALUE != 0"
+#endif
+
+
.text
.globl sem_timedwait
.type sem_timedwait,@function
.align 16
- cfi_startproc
sem_timedwait:
- /* First check for cancellation. */
- movl %gs:CANCELHANDLING, %eax
- andl $0xfffffff9, %eax
- cmpl $8, %eax
- je 10f
-
+.LSTARTCODE:
movl 4(%esp), %ecx
movl (%ecx), %eax
@@ -61,24 +61,24 @@ sem_timedwait:
/* Check whether the timeout value is valid. */
1: pushl %esi
- cfi_adjust_cfa_offset(4)
+.Lpush_esi:
pushl %edi
- cfi_adjust_cfa_offset(4)
+.Lpush_edi:
pushl %ebx
- cfi_adjust_cfa_offset(4)
+.Lpush_ebx:
subl $12, %esp
- cfi_adjust_cfa_offset(12)
+.Lsub_esp:
movl 32(%esp), %edi
- cfi_offset(7, -12) /* %edi */
/* Check for invalid nanosecond field. */
cmpl $1000000000, 4(%edi)
movl $EINVAL, %esi
- cfi_offset(6, -8) /* %esi */
jae 6f
- cfi_offset(3, -16) /* %ebx */
+ LOCK
+ incl NWAITERS(%ecx)
+
7: xorl %ecx, %ecx
movl %esp, %ebx
movl %ecx, %edx
@@ -103,10 +103,11 @@ sem_timedwait:
movl %ecx, (%esp) /* Store relative timeout. */
movl %edx, 4(%esp)
+.LcleanupSTART:
call __pthread_enable_asynccancel
movl %eax, 8(%esp)
- movl 28(%esp), %ebx
+ movl 28(%esp), %ebx /* Load semaphore address. */
xorl %ecx, %ecx
movl %esp, %esi
movl $SYS_futex, %eax
@@ -116,6 +117,7 @@ sem_timedwait:
movl 8(%esp), %eax
call __pthread_disable_asynccancel
+.LcleanupEND:
testl %esi, %esi
je 9f
@@ -131,24 +133,22 @@ sem_timedwait:
cmpxchgl %ecx, (%ebx)
jne 8b
- addl $12, %esp
- cfi_adjust_cfa_offset(-12)
xorl %eax, %eax
+
+10: LOCK
+ decl NWAITERS(%ebx)
+
+ addl $12, %esp
+.Ladd_esp:
popl %ebx
- cfi_adjust_cfa_offset(-4)
- cfi_restore(3)
+.Lpop_ebx:
popl %edi
- cfi_adjust_cfa_offset(-4)
- cfi_restore(7)
+.Lpop_edi:
popl %esi
- cfi_adjust_cfa_offset(-4)
- cfi_restore(6)
+.Lpop_esi:
ret
- cfi_adjust_cfa_offset(24)
- cfi_offset(6, -8) /* %esi */
- cfi_offset(7, -12) /* %edi */
- cfi_offset(3, -16) /* %ebx */
+.Lafter_ret:
3: negl %esi
6:
#ifdef PIC
@@ -172,25 +172,163 @@ sem_timedwait:
movl %esi, (%eax)
#endif
- addl $12, %esp
- cfi_adjust_cfa_offset(-12)
+ movl 28(%esp), %ebx /* Load semaphore address. */
orl $-1, %eax
- popl %ebx
- cfi_adjust_cfa_offset(-4)
- cfi_restore(3)
- popl %edi
- cfi_adjust_cfa_offset(-4)
- cfi_restore(7)
- popl %esi
- cfi_adjust_cfa_offset(-4)
- cfi_restore(6)
- ret
+ jmp 10b
+ .size sem_timedwait,.-sem_timedwait
-10: /* Canceled. */
- movl $0xffffffff, %gs:RESULT
+
+ .type sem_wait_cleanup,@function
+sem_wait_cleanup:
LOCK
- orl $0x10, %gs:CANCELHANDLING
- movl %gs:CLEANUP_JMP_BUF, %eax
- jmp HIDDEN_JUMPTARGET (__pthread_unwind)
- cfi_endproc
- .size sem_timedwait,.-sem_timedwait
+ decl NWAITERS(%ebx)
+ movl %eax, (%esp)
+.LcallUR:
+ call _Unwind_Resume@PLT
+ hlt
+.LENDCODE:
+ .size sem_wait_cleanup,.-sem_wait_cleanup
+
+
+ .section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+ .byte 0xff # @LPStart format (omit)
+ .byte 0xff # @TType format (omit)
+ .byte 0x01 # call-site format
+ # DW_EH_PE_uleb128
+ .uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+ .uleb128 .LcleanupSTART-.LSTARTCODE
+ .uleb128 .LcleanupEND-.LcleanupSTART
+ .uleb128 sem_wait_cleanup-.LSTARTCODE
+ .uleb128 0
+ .uleb128 .LcallUR-.LSTARTCODE
+ .uleb128 .LENDCODE-.LcallUR
+ .uleb128 0
+ .uleb128 0
+.Lcstend:
+
+
+ .section .eh_frame,"a",@progbits
+.LSTARTFRAME:
+ .long .LENDCIE-.LSTARTCIE # Length of the CIE.
+.LSTARTCIE:
+ .long 0 # CIE ID.
+ .byte 1 # Version number.
+#ifdef SHARED
+ .string "zPLR" # NUL-terminated augmentation
+ # string.
+#else
+ .string "zPL" # NUL-terminated augmentation
+ # string.
+#endif
+ .uleb128 1 # Code alignment factor.
+ .sleb128 -4 # Data alignment factor.
+ .byte 8 # Return address register
+ # column.
+#ifdef SHARED
+ .uleb128 7 # Augmentation value length.
+ .byte 0x9b # Personality: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4
+ # + DW_EH_PE_indirect
+ .long DW.ref.__gcc_personality_v0-.
+ .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+ .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+#else
+ .uleb128 6 # Augmentation value length.
+ .byte 0x0 # Personality: absolute
+ .long __gcc_personality_v0
+ .byte 0x0 # LSDA Encoding: absolute
+#endif
+ .byte 0x0c # DW_CFA_def_cfa
+ .uleb128 4
+ .uleb128 4
+ .byte 0x88 # DW_CFA_offset, column 0x10
+ .uleb128 1
+ .align 4
+.LENDCIE:
+
+ .long .LENDFDE-.LSTARTFDE # Length of the FDE.
+.LSTARTFDE:
+ .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
+#ifdef SHARED
+ .long .LSTARTCODE-. # PC-relative start address
+ # of the code.
+#else
+ .long .LSTARTCODE # Start address of the code.
+#endif
+ .long .LENDCODE-.LSTARTCODE # Length of the code.
+ .uleb128 4 # Augmentation size
+#ifdef SHARED
+ .long .LexceptSTART-.
+#else
+ .long .LexceptSTART
+#endif
+
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_esi-.LSTARTCODE
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 8
+ .byte 0x86 # DW_CFA_offset %esi
+ .uleb128 2
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_edi-.Lpush_esi
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 12
+ .byte 0x87 # DW_CFA_offset %edi
+ .uleb128 3
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_ebx-.Lpush_edi
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 0x83 # DW_CFA_offset %ebx
+ .uleb128 4
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lsub_esp-.Lpush_ebx
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 28
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Ladd_esp-.Lsub_esp
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_ebx-.Ladd_esp
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 12
+ .byte 0xc3 # DW_CFA_restore %ebx
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_edi-.Lpop_ebx
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 8
+ .byte 0xc7 # DW_CFA_restore %edi
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_esi-.Lpop_edi
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 4
+ .byte 0xc6 # DW_CFA_restore %esi
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lafter_ret-.Lpop_esi
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 28
+ .byte 0x86 # DW_CFA_offset %esi
+ .uleb128 2
+ .byte 0x87 # DW_CFA_offset %edi
+ .uleb128 3
+ .byte 0x83 # DW_CFA_offset %ebx
+ .uleb128 4
+ .align 4
+.LENDFDE:
+
+
+#ifdef SHARED
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
+ .align 4
+ .type DW.ref.__gcc_personality_v0, @object
+ .size DW.ref.__gcc_personality_v0, 4
+DW.ref.__gcc_personality_v0:
+ .long __gcc_personality_v0
+#endif
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 b1296275d0..bb4d6443e9 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, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -20,6 +20,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <pthread-errnos.h>
+#include <structsem.h>
#ifndef UP
# define LOCK lock
@@ -31,19 +32,253 @@
#define FUTEX_WAKE 1
+#if VALUE != 0
+# error "code needs to be rewritten for VALUE != 0"
+#endif
+
.text
.globl __new_sem_wait
.type __new_sem_wait,@function
.align 16
- cfi_startproc
__new_sem_wait:
- /* First check for cancellation. */
- movl %gs:CANCELHANDLING, %eax
- andl $0xfffffff9, %eax
- cmpl $8, %eax
- je 5f
+.LSTARTCODE:
+ pushl %ebx
+.Lpush_ebx:
+ pushl %esi
+.Lpush_esi:
+ subl $4, %esp
+.Lsub_esp:
+
+ movl 16(%esp), %ebx
+
+ movl (%ebx), %eax
+2: testl %eax, %eax
+ je 1f
+
+ leal -1(%eax), %edx
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ jne 2b
+7: xorl %eax, %eax
+
+9: movl 4(%esp), %esi
+ movl 8(%esp), %ebx
+ addl $12, %esp
+.Ladd_esp:
+ ret
+
+.Lafter_ret:
+1: LOCK
+ incl NWAITERS(%ebx)
+
+.LcleanupSTART:
+6: call __pthread_enable_asynccancel
+ movl %eax, (%esp)
+
+ xorl %esi, %esi
+ movl $SYS_futex, %eax
+ movl %esi, %ecx
+ movl %esi, %edx
+ ENTER_KERNEL
+ movl %eax, %esi
+
+ movl (%esp), %eax
+ call __pthread_disable_asynccancel
+.LcleanupEND:
+
+ testl %esi, %esi
+ je 3f
+ cmpl $-EWOULDBLOCK, %esi
+ jne 4f
+
+3:
+ movl (%ebx), %eax
+5: testl %eax, %eax
+ je 6b
+
+ leal -1(%eax), %edx
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ jne 5b
+
+ LOCK
+ decl NWAITERS(%ebx)
+ jmp 7b
+
+4: LOCK
+ decl NWAITERS(%ebx)
+
+ negl %esi
+#ifdef PIC
+ call __i686.get_pc_thunk.bx
+#else
+ movl $8f, %ebx
+8:
+#endif
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+#if USE___THREAD
+# 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)
+#endif
+ orl $-1, %eax
+
+ jmp 9b
+ .size __new_sem_wait,.-__new_sem_wait
+ versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1)
+
+
+ .type sem_wait_cleanup,@function
+sem_wait_cleanup:
+ LOCK
+ decl NWAITERS(%ebx)
+ movl %eax, (%esp)
+.LcallUR:
+ call _Unwind_Resume@PLT
+ hlt
+.LENDCODE:
+ .size sem_wait_cleanup,.-sem_wait_cleanup
+
+
+ .section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+ .byte 0xff # @LPStart format (omit)
+ .byte 0xff # @TType format (omit)
+ .byte 0x01 # call-site format
+ # DW_EH_PE_uleb128
+ .uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+ .uleb128 .LcleanupSTART-.LSTARTCODE
+ .uleb128 .LcleanupEND-.LcleanupSTART
+ .uleb128 sem_wait_cleanup-.LSTARTCODE
+ .uleb128 0
+ .uleb128 .LcallUR-.LSTARTCODE
+ .uleb128 .LENDCODE-.LcallUR
+ .uleb128 0
+ .uleb128 0
+.Lcstend:
+
+
+ .section .eh_frame,"a",@progbits
+.LSTARTFRAME:
+ .long .LENDCIE-.LSTARTCIE # Length of the CIE.
+.LSTARTCIE:
+ .long 0 # CIE ID.
+ .byte 1 # Version number.
+#ifdef SHARED
+ .string "zPLR" # NUL-terminated augmentation
+ # string.
+#else
+ .string "zPL" # NUL-terminated augmentation
+ # string.
+#endif
+ .uleb128 1 # Code alignment factor.
+ .sleb128 -4 # Data alignment factor.
+ .byte 8 # Return address register
+ # column.
+#ifdef SHARED
+ .uleb128 7 # Augmentation value length.
+ .byte 0x9b # Personality: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4
+ # + DW_EH_PE_indirect
+ .long DW.ref.__gcc_personality_v0-.
+ .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+ .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+#else
+ .uleb128 6 # Augmentation value length.
+ .byte 0x0 # Personality: absolute
+ .long __gcc_personality_v0
+ .byte 0x0 # LSDA Encoding: absolute
+#endif
+ .byte 0x0c # DW_CFA_def_cfa
+ .uleb128 4
+ .uleb128 4
+ .byte 0x88 # DW_CFA_offset, column 0x10
+ .uleb128 1
+ .align 4
+.LENDCIE:
+
+ .long .LENDFDE-.LSTARTFDE # Length of the FDE.
+.LSTARTFDE:
+ .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
+#ifdef SHARED
+ .long .LSTARTCODE-. # PC-relative start address
+ # of the code.
+#else
+ .long .LSTARTCODE # Start address of the code.
+#endif
+ .long .LENDCODE-.LSTARTCODE # Length of the code.
+ .uleb128 4 # Augmentation size
+#ifdef SHARED
+ .long .LexceptSTART-.
+#else
+ .long .LexceptSTART
+#endif
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_ebx-.LSTARTCODE
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 8
+ .byte 0x83 # DW_CFA_offset %ebx
+ .uleb128 2
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_esi-.Lpush_ebx
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 12
+ .byte 0x86 # DW_CFA_offset %esi
+ .uleb128 3
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lsub_esp-.Lpush_esi
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Ladd_esp-.Lsub_esp
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 4
+ .byte 0xc3 # DW_CFA_restore %ebx
+ .byte 0xc6 # DW_CFA_restore %esi
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lafter_ret-.Ladd_esp
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 0x83 # DW_CFA_offset %ebx
+ .uleb128 2
+ .byte 0x86 # DW_CFA_offset %esi
+ .uleb128 3
+ .align 4
+.LENDFDE:
+
+
+#ifdef SHARED
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
+ .align 4
+ .type DW.ref.__gcc_personality_v0, @object
+ .size DW.ref.__gcc_personality_v0, 4
+DW.ref.__gcc_personality_v0:
+ .long __gcc_personality_v0
+#endif
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+ .section ".text.compat", "ax"
+ .global __old_sem_wait
+ .type __old_sem_wait,@function
+ .align 16
+ cfi_startproc
+__old_sem_wait:
pushl %ebx
cfi_adjust_cfa_offset(4)
pushl %esi
@@ -52,9 +287,9 @@ __new_sem_wait:
cfi_adjust_cfa_offset(4)
movl 16(%esp), %ebx
- cfi_offset(3, -8) /* %ebx */
+ cfi_offset(ebx, -8)
- cfi_offset(6, -12) /* %esi */
+ cfi_offset(esi, -12)
3: movl (%ebx), %eax
2: testl %eax, %eax
je 1f
@@ -65,17 +300,17 @@ __new_sem_wait:
jne 2b
xorl %eax, %eax
- movl 4(%esp), %esi
- cfi_restore(6)
+5: movl 4(%esp), %esi
movl 8(%esp), %ebx
- cfi_restore(3)
addl $12, %esp
+ cfi_restore(ebx)
+ cfi_restore(esi)
cfi_adjust_cfa_offset(-12)
ret
cfi_adjust_cfa_offset(12)
- cfi_offset(3, -8) /* %ebx */
- cfi_offset(6, -12) /* %esi */
+ cfi_offset(ebx, -8)
+ cfi_offset(esi, -12)
1: call __pthread_enable_asynccancel
movl %eax, (%esp)
@@ -115,25 +350,8 @@ __new_sem_wait:
movl %esi, (%eax)
#endif
orl $-1, %eax
- movl 4(%esp), %esi
- cfi_restore(6)
- movl 8(%esp), %ebx
- cfi_restore(3)
- addl $12, %esp
- cfi_adjust_cfa_offset(-12)
- ret
-
-5: /* Canceled. */
- movl $0xffffffff, %gs:RESULT
- LOCK
- orl $0x10, %gs:CANCELHANDLING
- movl %gs:CLEANUP_JMP_BUF, %eax
- jmp HIDDEN_JUMPTARGET (__pthread_unwind)
+ jmp 5b
cfi_endproc
- .size __new_sem_wait,.-__new_sem_wait
- versioned_symbol(libpthread, __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
+ .size __old_sem_wait,.-__old_sem_wait
compat_symbol(libpthread, __old_sem_wait, sem_wait, GLIBC_2_0)
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
index 1dec19e57d..eff932cab2 100644
--- a/nptl/sysdeps/unix/sysv/linux/internaltypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -137,9 +137,16 @@ struct pthread_key_struct
/* Semaphore variable structure. */
-struct sem
+struct new_sem
{
- unsigned int count;
+ unsigned int value;
+ int private;
+ unsigned long int nwaiters;
+};
+
+struct old_sem
+{
+ unsigned int value;
};
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sem_post.c
index 671b43f7f7..f8bc695292 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_post.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_post.c
@@ -1,5 +1,5 @@
/* sem_post -- post to a POSIX semaphore. Generic futex-using version.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@@ -29,10 +29,33 @@
int
__new_sem_post (sem_t *sem)
{
+ struct new_sem *isem = (struct new_sem *) sem;
+
+ int nr = atomic_increment_val (&isem->value);
+ atomic_full_barrier ();
+ if (isem->nwaiters > 0)
+ {
+ int err = lll_futex_wake (&isem->value, 1);
+ if (__builtin_expect (err, 0) < 0)
+ {
+ __set_errno (-err);
+ return -1;
+ }
+ }
+ return 0;
+}
+versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
+
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+attribute_compat_text_section
+__old_sem_post (sem_t *sem)
+{
int *futex = (int *) sem;
int nr = atomic_increment_val (futex);
- int err = lll_futex_wake (futex, nr);
+ int err = lll_futex_wake (futex, 1);
if (__builtin_expect (err, 0) < 0)
{
__set_errno (-err);
@@ -40,8 +63,5 @@ __new_sem_post (sem_t *sem)
}
return 0;
}
-versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_post, __old_sem_post)
compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index ef897c1e93..30f6a87df4 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
@@ -1,5 +1,5 @@
/* sem_timedwait -- wait on a semaphore. Generic futex-using version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
@@ -28,28 +28,39 @@
#include <shlib-compat.h>
+extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+
+
+void
+attribute_hidden
+__sem_wait_cleanup (void *arg)
+{
+ struct new_sem *isem = (struct new_sem *) arg;
+
+ atomic_decrement (&isem->nwaiters);
+}
+
+
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
- /* First check for cancellation. */
- CANCELLATION_P (THREAD_SELF);
-
- int *futex = (int *) sem;
- int val;
+ struct new_sem *isem = (struct new_sem *) sem;
int err;
- if (*futex > 0)
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ return 0;
+
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
{
- val = atomic_decrement_if_positive (futex);
- if (val > 0)
- return 0;
+ __set_errno (EINVAL);
+ return -1;
}
- err = -EINVAL;
- if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
- goto error_return;
+ atomic_increment (&isem->nwaiters);
+
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
- do
+ while (1)
{
struct timeval tv;
struct timespec rt;
@@ -70,7 +81,11 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Already timed out? */
err = -ETIMEDOUT;
if (sec < 0)
- goto error_return;
+ {
+ __set_errno (ETIMEDOUT);
+ err = -1;
+ break;
+ }
/* Do wait. */
rt.tv_sec = sec;
@@ -79,21 +94,28 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
- err = lll_futex_timed_wait (futex, 0, &rt);
+ err = lll_futex_timed_wait (&isem->value, 0, &rt);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
- goto error_return;
+ {
+ __set_errno (-err);
+ err = -1;
+ break;
+ }
- val = atomic_decrement_if_positive (futex);
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ {
+ err = 0;
+ break;
+ }
}
- while (val <= 0);
- return 0;
+ pthread_cleanup_pop (0);
+
+ atomic_decrement (&isem->nwaiters);
- error_return:
- __set_errno (-err);
- return -1;
+ return err;
}
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
index d1aa97571a..e35b6480f2 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
@@ -28,9 +28,66 @@
#include <shlib-compat.h>
+void
+attribute_hidden
+__sem_wait_cleanup (void *arg)
+{
+ struct new_sem *isem = (struct new_sem *) arg;
+
+ atomic_decrement (&isem->nwaiters);
+}
+
+
int
__new_sem_wait (sem_t *sem)
{
+ struct new_sem *isem = (struct new_sem *) sem;
+ int err;
+
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ return 0;
+
+ atomic_increment (&isem->nwaiters);
+
+ pthread_cleanup_push (__sem_wait_cleanup, isem);
+
+ while (1)
+ {
+ /* Enable asynchronous cancellation. Required by the standard. */
+ int oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_wait (&isem->value, 0);
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (oldtype);
+
+ if (err != 0 && err != -EWOULDBLOCK)
+ {
+ __set_errno (-err);
+ err = -1;
+ }
+
+ if (atomic_decrement_if_positive (&isem->value) > 0)
+ {
+ err = 0;
+ break;
+ }
+ }
+
+ pthread_cleanup_pop (0);
+
+ atomic_decrement (&isem->nwaiters);
+
+ return err;
+}
+versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
+
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+attribute_compat_text_section
+__old_sem_wait (sem_t *sem)
+{
int *futex = (int *) sem;
int err;
@@ -53,8 +110,5 @@ __new_sem_wait (sem_t *sem)
return -1;
}
-versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
-strong_alias (__new_sem_wait, __old_sem_wait)
compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/structsem.sym b/nptl/sysdeps/unix/sysv/linux/structsem.sym
new file mode 100644
index 0000000000..4f32c68da5
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/structsem.sym
@@ -0,0 +1,10 @@
+#include <stddef.h>
+#include <sched.h>
+#include <bits/pthreadtypes.h>
+#include "internaltypes.h"
+
+--
+
+VALUE offsetof (struct new_sem, value)
+PRIVATE offsetof (struct new_sem, private)
+NWAITERS offsetof (struct new_sem, nwaiters)
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
index 7f608a5974..1f5d0bba34 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -20,6 +20,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <pthread-errnos.h>
+#include <structsem.h>
#ifndef UP
# define LOCK lock
@@ -37,19 +38,25 @@
.type sem_post,@function
.align 16
sem_post:
- movl $1, %edx
LOCK
- xaddl %edx, (%rdi)
+#if VALUE == 0
+ addl $1, (%rdi)
+#else
+ addl $1, VALUE(%rdi)
+#endif
+
+ cmpq $0, NWAITERS(%rdi)
+ je 2f
movl $SYS_futex, %eax
movl $FUTEX_WAKE, %esi
- incl %edx
+ movl $1, %edx
syscall
testq %rax, %rax
js 1f
- xorl %eax, %eax
+2: xorl %eax, %eax
retq
1:
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
index 8c5c2a6974..1bb74c0368 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
@@ -20,6 +20,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <pthread-errnos.h>
+#include <structsem.h>
#ifndef UP
# define LOCK lock
@@ -28,6 +29,7 @@
#endif
#define SYS_futex 202
+#define FUTEX_WAIT 0
/* For the calculation see asm/vsyscall.h. */
#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
@@ -38,15 +40,23 @@
.globl sem_timedwait
.type sem_timedwait,@function
.align 16
- cfi_startproc
sem_timedwait:
+.LSTARTCODE:
+#if VALUE == 0
movl (%rdi), %eax
+#else
+ movl VALUE(%rdi), %eax
+#endif
2: testl %eax, %eax
je 1f
leaq -1(%rax), %rdx
LOCK
+#if VALUE == 0
cmpxchgl %edx, (%rdi)
+#else
+ cmpxchgl %edx, VALUE(%rdi)
+#endif
jne 2b
xorl %eax, %eax
@@ -54,25 +64,25 @@ sem_timedwait:
/* Check whether the timeout value is valid. */
1: pushq %r12
- cfi_adjust_cfa_offset(8)
+.Lpush_r12:
pushq %r13
- cfi_adjust_cfa_offset(8)
+.Lpush_r13:
pushq %r14
- cfi_adjust_cfa_offset(8)
+.Lpush_r14:
subq $24, %rsp
- cfi_adjust_cfa_offset(24)
+.Lsubq:
movq %rdi, %r12
- cfi_offset(12, -16) /* %r12 */
movq %rsi, %r13
- cfi_offset(13, -24) /* %r13 */
/* Check for invalid nanosecond field. */
cmpq $1000000000, 8(%r13)
movl $EINVAL, %r14d
- cfi_offset(14, -24) /* %r14 */
jae 6f
+ LOCK
+ addq $1, NWAITERS(%r12)
+
7: xorl %esi, %esi
movq %rsp, %rdi
movq $VSYSCALL_ADDR_vgettimeofday, %rax
@@ -96,12 +106,17 @@ sem_timedwait:
movq %rdi, (%rsp) /* Store relative timeout. */
movq %rsi, 8(%rsp)
+.LcleanupSTART:
call __pthread_enable_asynccancel
movl %eax, 16(%rsp)
movq %rsp, %r10
+#if VALUE == 0
movq %r12, %rdi
- xorl %esi, %esi
+#else
+ leaq VALUE(%r12), %rdi
+#endif
+ movl $FUTEX_WAIT, %esi
movl $SYS_futex, %eax
xorl %edx, %edx
syscall
@@ -109,39 +124,47 @@ sem_timedwait:
movl 16(%rsp), %edi
call __pthread_disable_asynccancel
+.LcleanupEND:
testq %r14, %r14
je 9f
cmpq $-EWOULDBLOCK, %r14
jne 3f
-9: movl (%r12), %eax
+9:
+#if VALUE == 0
+ movl (%r12), %eax
+#else
+ movl VALUE(%r12), %eax
+#endif
8: testl %eax, %eax
je 7b
leaq -1(%rax), %rcx
LOCK
+#if VALUE == 0
cmpxchgl %ecx, (%r12)
+#else
+ cmpxchgl %ecx, VALUE(%r12)
+#endif
jne 8b
xorl %eax, %eax
-10: addq $24, %rsp
- cfi_adjust_cfa_offset(-24)
+
+10: LOCK
+ subq $1, NWAITERS(%r12)
+
+ addq $24, %rsp
+.Laddq:
popq %r14
- cfi_adjust_cfa_offset(-8)
- cfi_restore(14)
+.Lpop_r14:
popq %r13
- cfi_adjust_cfa_offset(-8)
- cfi_restore(13)
+.Lpop_r13:
popq %r12
- cfi_adjust_cfa_offset(-8)
- cfi_restore(12)
+.Lpop_r12:
retq
- cfi_adjust_cfa_offset(48)
- cfi_offset(12, -16) /* %r12 */
- cfi_offset(13, -24) /* %r13 */
- cfi_offset(14, -32) /* %r14 */
+.Lafter_retq:
3: negq %r14
6:
#if USE___THREAD
@@ -154,5 +177,159 @@ sem_timedwait:
orl $-1, %eax
jmp 10b
- cfi_endproc
.size sem_timedwait,.-sem_timedwait
+
+
+ .type sem_timedwait_cleanup,@function
+sem_timedwait_cleanup:
+ LOCK
+ subq $1, NWAITERS(%r12)
+ movq %rax, %rdi
+.LcallUR:
+ call _Unwind_Resume@PLT
+ hlt
+.LENDCODE:
+ .size sem_timedwait_cleanup,.-sem_timedwait_cleanup
+
+
+ .section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+ .byte 0xff # @LPStart format (omit)
+ .byte 0xff # @TType format (omit)
+ .byte 0x01 # call-site format
+ # DW_EH_PE_uleb128
+ .uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+ .uleb128 .LcleanupSTART-.LSTARTCODE
+ .uleb128 .LcleanupEND-.LcleanupSTART
+ .uleb128 sem_timedwait_cleanup-.LSTARTCODE
+ .uleb128 0
+ .uleb128 .LcallUR-.LSTARTCODE
+ .uleb128 .LENDCODE-.LcallUR
+ .uleb128 0
+ .uleb128 0
+.Lcstend:
+
+
+ .section .eh_frame,"a",@progbits
+.LSTARTFRAME:
+ .long .LENDCIE-.LSTARTCIE # Length of the CIE.
+.LSTARTCIE:
+ .long 0 # CIE ID.
+ .byte 1 # Version number.
+#ifdef SHARED
+ .string "zPLR" # NUL-terminated augmentation
+ # string.
+#else
+ .string "zPL" # NUL-terminated augmentation
+ # string.
+#endif
+ .uleb128 1 # Code alignment factor.
+ .sleb128 -8 # Data alignment factor.
+ .byte 16 # Return address register
+ # column.
+#ifdef SHARED
+ .uleb128 7 # Augmentation value length.
+ .byte 0x9b # Personality: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4
+ # + DW_EH_PE_indirect
+ .long DW.ref.__gcc_personality_v0-.
+ .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+ .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+#else
+ .uleb128 10 # Augmentation value length.
+ .byte 0x0 # Personality: absolute
+ .quad __gcc_personality_v0
+ .byte 0x0 # LSDA Encoding: absolute
+#endif
+ .byte 0x0c # DW_CFA_def_cfa
+ .uleb128 7
+ .uleb128 8
+ .byte 0x90 # DW_CFA_offset, column 0x10
+ .uleb128 1
+ .align 8
+.LENDCIE:
+
+ .long .LENDFDE-.LSTARTFDE # Length of the FDE.
+.LSTARTFDE:
+ .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
+#ifdef SHARED
+ .long .LSTARTCODE-. # PC-relative start address
+ # of the code.
+ .long .LENDCODE-.LSTARTCODE # Length of the code.
+ .uleb128 4 # Augmentation size
+ .long .LexceptSTART-.
+#else
+ .quad .LSTARTCODE # Start address of the code.
+ .quad .LENDCODE-.LSTARTCODE # Length of the code.
+ .uleb128 8 # Augmentation size
+ .quad .LexceptSTART
+#endif
+
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_r12-.LSTARTCODE
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 0x8c # DW_CFA_offset %r12
+ .uleb128 2
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_r13-.Lpush_r12
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 24
+ .byte 0x8d # DW_CFA_offset %r13
+ .uleb128 3
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_r14-.Lpush_r13
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 32
+ .byte 0x8e # DW_CFA_offset %r14
+ .uleb128 4
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lsubq-.Lpush_r14
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 56
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Laddq-.Lsubq
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 32
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_r14-.Laddq
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 24
+ .byte 0xce # DW_CFA_restore %r14
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_r13-.Lpop_r14
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 0xcd # DW_CFA_restore %r13
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_r12-.Lpop_r13
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 8
+ .byte 0xcc # DW_CFA_restore %r12
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lafter_retq-.Lpop_r12
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 56
+ .byte 0x8c # DW_CFA_offset %r12
+ .uleb128 2
+ .byte 0x8d # DW_CFA_offset %r13
+ .uleb128 3
+ .byte 0x8e # DW_CFA_offset %r14
+ .uleb128 4
+ .align 8
+.LENDFDE:
+
+
+#ifdef SHARED
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
+ .align 8
+ .type DW.ref.__gcc_personality_v0, @object
+ .size DW.ref.__gcc_personality_v0, 8
+DW.ref.__gcc_personality_v0:
+ .quad __gcc_personality_v0
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
index 5bd78eb944..e958d63f55 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
@@ -20,6 +20,7 @@
#include <sysdep.h>
#include <shlib-compat.h>
#include <pthread-errnos.h>
+#include <structsem.h>
#ifndef UP
# define LOCK lock
@@ -28,6 +29,7 @@
#endif
#define SYS_futex 202
+#define FUTEX_WAIT 0
.text
@@ -35,57 +37,88 @@
.globl sem_wait
.type sem_wait,@function
.align 16
- cfi_startproc
sem_wait:
+.LSTARTCODE:
pushq %r12
- cfi_adjust_cfa_offset(8)
- cfi_offset(12, -16)
+.Lpush_r12:
pushq %r13
- cfi_adjust_cfa_offset(8)
+.Lpush_r13:
movq %rdi, %r13
- cfi_offset(13, -24)
-3: movl (%r13), %eax
+#if VALUE == 0
+ movl (%r13), %eax
+#else
+ movl VALUE(%r13), %eax
+#endif
2: testl %eax, %eax
je 1f
- leaq -1(%rax), %rdx
+ leal -1(%rax), %edx
LOCK
+#if VALUE == 0
cmpxchgl %edx, (%r13)
+#else
+ cmpxchgl %edx, VALUE(%r13)
+#endif
jne 2b
- xorl %eax, %eax
- popq %r13
- cfi_adjust_cfa_offset(-8)
- cfi_restore(13)
+7: xorl %eax, %eax
+
+9: popq %r13
+.Lpop_r13:
popq %r12
- cfi_adjust_cfa_offset(-8)
- cfi_restore(12)
+.Lpop_r12:
retq
- cfi_adjust_cfa_offset(16)
- cfi_offset(12, -16)
- cfi_offset(13, -24)
-1: call __pthread_enable_asynccancel
+.Lafter_retq:
+1: LOCK
+ addq $1, NWAITERS(%r13)
+
+.LcleanupSTART:
+6: call __pthread_enable_asynccancel
movl %eax, %r8d
xorq %r10, %r10
movl $SYS_futex, %eax
movq %r13, %rdi
- movq %r10, %rsi
- movq %r10, %rdx
+ movl $FUTEX_WAIT, %esi
+ xorl %edx, %edx
syscall
movq %rax, %r12
movl %r8d, %edi
call __pthread_disable_asynccancel
+.LcleanupEND:
testq %r12, %r12
- je 3b
+ je 3f
cmpq $-EWOULDBLOCK, %r12
- je 3b
- negq %r12
+ jne 4f
+
+3:
+#if VALUE == 0
+ movl (%r13), %eax
+#else
+ movl VALUE(%r13), %eax
+#endif
+5: testl %eax, %eax
+ je 6b
+
+ leal -1(%rax), %edx
+ LOCK
+#if VALUE == 0
+ cmpxchgl %edx, (%r13)
+#else
+ cmpxchgl %edx, VALUE(%r13)
+#endif
+ jne 5b
+
+ LOCK
+ subq $1, NWAITERS(%r13)
+ jmp 7b
+
+4: negq %r12
#if USE___THREAD
movq errno@gottpoff(%rip), %rdx
movl %r12d, %fs:(%rdx)
@@ -95,13 +128,142 @@ sem_wait:
#endif
orl $-1, %eax
- popq %r13
- cfi_adjust_cfa_offset(-8)
- cfi_restore(13)
- popq %r12
- cfi_adjust_cfa_offset(-8)
- cfi_restore(12)
+ LOCK
+ subq $1, NWAITERS(%r13)
- retq
- cfi_endproc
+ jmp 9b
.size sem_wait,.-sem_wait
+
+
+ .type sem_wait_cleanup,@function
+sem_wait_cleanup:
+ LOCK
+ subq $1, NWAITERS(%r13)
+ movq %rax, %rdi
+.LcallUR:
+ call _Unwind_Resume@PLT
+ hlt
+.LENDCODE:
+ .size sem_wait_cleanup,.-sem_wait_cleanup
+
+
+ .section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+ .byte 0xff # @LPStart format (omit)
+ .byte 0xff # @TType format (omit)
+ .byte 0x01 # call-site format
+ # DW_EH_PE_uleb128
+ .uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+ .uleb128 .LcleanupSTART-.LSTARTCODE
+ .uleb128 .LcleanupEND-.LcleanupSTART
+ .uleb128 sem_wait_cleanup-.LSTARTCODE
+ .uleb128 0
+ .uleb128 .LcallUR-.LSTARTCODE
+ .uleb128 .LENDCODE-.LcallUR
+ .uleb128 0
+ .uleb128 0
+.Lcstend:
+
+
+ .section .eh_frame,"a",@progbits
+.LSTARTFRAME:
+ .long .LENDCIE-.LSTARTCIE # Length of the CIE.
+.LSTARTCIE:
+ .long 0 # CIE ID.
+ .byte 1 # Version number.
+#ifdef SHARED
+ .string "zPLR" # NUL-terminated augmentation
+ # string.
+#else
+ .string "zPL" # NUL-terminated augmentation
+ # string.
+#endif
+ .uleb128 1 # Code alignment factor.
+ .sleb128 -8 # Data alignment factor.
+ .byte 16 # Return address register
+ # column.
+#ifdef SHARED
+ .uleb128 7 # Augmentation value length.
+ .byte 0x9b # Personality: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4
+ # + DW_EH_PE_indirect
+ .long DW.ref.__gcc_personality_v0-.
+ .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+ .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
+ # + DW_EH_PE_sdata4.
+#else
+ .uleb128 10 # Augmentation value length.
+ .byte 0x0 # Personality: absolute
+ .quad __gcc_personality_v0
+ .byte 0x0 # LSDA Encoding: absolute
+#endif
+ .byte 0x0c # DW_CFA_def_cfa
+ .uleb128 7
+ .uleb128 8
+ .byte 0x90 # DW_CFA_offset, column 0x10
+ .uleb128 1
+ .align 8
+.LENDCIE:
+
+ .long .LENDFDE-.LSTARTFDE # Length of the FDE.
+.LSTARTFDE:
+ .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
+#ifdef SHARED
+ .long .LSTARTCODE-. # PC-relative start address
+ # of the code.
+ .long .LENDCODE-.LSTARTCODE # Length of the code.
+ .uleb128 4 # Augmentation size
+ .long .LexceptSTART-.
+#else
+ .quad .LSTARTCODE # Start address of the code.
+ .quad .LENDCODE-.LSTARTCODE # Length of the code.
+ .uleb128 8 # Augmentation size
+ .quad .LexceptSTART
+#endif
+
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_r12-.LSTARTCODE
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 0x8c # DW_CFA_offset %r12
+ .uleb128 2
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpush_r13-.Lpush_r12
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 24
+ .byte 0x8d # DW_CFA_offset %r13
+ .uleb128 3
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_r13-.Lpush_r13
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 16
+ .byte 0xcd # DW_CFA_restore %r13
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lpop_r12-.Lpop_r13
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 8
+ .byte 0xcc # DW_CFA_restore %r12
+ .byte 4 # DW_CFA_advance_loc4
+ .long .Lafter_retq-.Lpop_r12
+ .byte 14 # DW_CFA_def_cfa_offset
+ .uleb128 24
+ .byte 0x8c # DW_CFA_offset %r12
+ .uleb128 2
+ .byte 0x8d # DW_CFA_offset %r13
+ .uleb128 3
+ .align 8
+.LENDFDE:
+
+
+#ifdef SHARED
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
+ .align 8
+ .type DW.ref.__gcc_personality_v0, @object
+ .size DW.ref.__gcc_personality_v0, 8
+DW.ref.__gcc_personality_v0:
+ .quad __gcc_personality_v0
+#endif
diff --git a/nptl/tst-typesizes.c b/nptl/tst-typesizes.c
index db8936f5f4..17a1e297d3 100644
--- a/nptl/tst-typesizes.c
+++ b/nptl/tst-typesizes.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
@@ -59,7 +59,8 @@ do_test (void)
TEST_TYPE2 (pthread_rwlockattr_t, struct pthread_rwlockattr);
TEST_TYPE2 (pthread_barrier_t, struct pthread_barrier);
TEST_TYPE2 (pthread_barrierattr_t, struct pthread_barrierattr);
- TEST_TYPE2 (sem_t, struct sem);
+ TEST_TYPE2 (sem_t, struct new_sem);
+ TEST_TYPE2 (sem_t, struct old_sem);
return result;
}