diff options
Diffstat (limited to 'nptl/sysdeps/unix')
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S | 41 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sem_post.c | 15 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/structsem.sym | 2 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S | 36 |
4 files changed, 83 insertions, 11 deletions
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 ac045b6e34..2edcdde4f0 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, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -34,12 +34,21 @@ __new_sem_post: movl 8(%esp), %ebx +#if VALUE == 0 + movl (%ebx), %eax +#else + movl VALUE(%ebx), %eax +#endif +0: cmpl $SEM_VALUE_MAX, %eax + je 3f + leal 1(%eax), %edx LOCK #if VALUE == 0 - addl $1, (%ebx) + cmpxchgl %edx, (%ebx) #else - addl $1, VALUE(%ebx) + cmpxchgl %edx, VALUE(%ebx) #endif + jnz 0b cmpl $0, NWAITERS(%ebx) je 2f @@ -82,6 +91,32 @@ __new_sem_post: orl $-1, %eax popl %ebx ret + +3: +#ifdef PIC + call __i686.get_pc_thunk.bx +#else + movl $5f, %ebx +5: +#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 $EOVERFLOW, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl $EOVERFLOW, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EOVERFLOW, (%eax) +#endif + + orl $-1, %eax + popl %ebx + ret .size __new_sem_post,.-__new_sem_post versioned_symbol(libpthread, __new_sem_post, sem_post, GLIBC_2_1) #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) diff --git a/nptl/sysdeps/unix/sysv/linux/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sem_post.c index 25b676fcd2..58b226f63d 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, 2007 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -31,7 +31,18 @@ __new_sem_post (sem_t *sem) { struct new_sem *isem = (struct new_sem *) sem; - int nr = atomic_increment_val (&isem->value); + __typeof (isem->value) cur; + do + { + cur = isem->value; + if (isem->value == SEM_VALUE_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + } + while (atomic_compare_and_exchange_bool_acq (&isem->value, cur + 1, cur)); + atomic_full_barrier (); if (isem->nwaiters > 0) { diff --git a/nptl/sysdeps/unix/sysv/linux/structsem.sym b/nptl/sysdeps/unix/sysv/linux/structsem.sym index 4f32c68da5..0e2a15f2b5 100644 --- a/nptl/sysdeps/unix/sysv/linux/structsem.sym +++ b/nptl/sysdeps/unix/sysv/linux/structsem.sym @@ -1,3 +1,4 @@ +#include <limits.h> #include <stddef.h> #include <sched.h> #include <bits/pthreadtypes.h> @@ -8,3 +9,4 @@ VALUE offsetof (struct new_sem, value) PRIVATE offsetof (struct new_sem, private) NWAITERS offsetof (struct new_sem, nwaiters) +SEM_VALUE_MAX SEM_VALUE_MAX 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 adbbcdfa71..b4014c6505 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, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -30,12 +30,21 @@ .type sem_post,@function .align 16 sem_post: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +0: cmpl $SEM_VALUE_MAX, %eax + je 3f + leal 1(%eax), %esi LOCK #if VALUE == 0 - addl $1, (%rdi) + cmpxchgl %esi, (%rdi) #else - addl $1, VALUE(%rdi) + cmpxchgl %esi, VALUE(%rdi) #endif + jnz 0b cmpq $0, NWAITERS(%rdi) je 2f @@ -54,13 +63,28 @@ sem_post: 1: #if USE___THREAD - movq errno@gottpoff(%rip), %rdx - movl $EINVAL, %fs:(%rdx) + movl $EINVAL, %eax #else callq __errno_location@plt - movl $EINVAL, (%rax) + movl $EINVAL, %edx #endif + jmp 4f +3: +#if USE___THREAD + movl $EOVERFLOW, %eax +#else + callq __errno_location@plt + movl $EOVERFLOW, %edx +#endif + +4: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %eax, %fs:(%rdx) +#else + movl %edx, (%rax) +#endif orl $-1, %eax retq .size sem_post,.-sem_post |