aboutsummaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S41
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_post.c15
-rw-r--r--nptl/sysdeps/unix/sysv/linux/structsem.sym2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S36
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