about summary refs log tree commit diff
path: root/nptl
diff options
context:
space:
mode:
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog8
-rw-r--r--nptl/pthread-errnos.sym1
-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
6 files changed, 92 insertions, 11 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index ec834340dc..9c37906467 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,11 @@
+2008-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread-errnos.sym: Add EOVERFLOW.
+	* sysdeps/unix/sysv/linux/structsem.sym: Add SEM_VALUE_MAX.
+	* sysdeps/unix/sysv/linux/sem_post.c: Don't overflow value field.
+	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise.
+
 2007-12-14  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/x86_64/pthreaddef.h (ARCH_RETRY_MMAP): Take additional
diff --git a/nptl/pthread-errnos.sym b/nptl/pthread-errnos.sym
index 2bb4d0d3ca..0975b7a373 100644
--- a/nptl/pthread-errnos.sym
+++ b/nptl/pthread-errnos.sym
@@ -8,5 +8,6 @@ EDEADLK		EDEADLK
 EINTR		EINTR
 EINVAL		EINVAL
 ENOSYS		ENOSYS
+EOVERFLOW	EOVERFLOW
 ETIMEDOUT	ETIMEDOUT
 EWOULDBLOCK	EWOULDBLOCK
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