diff --git a/malloc/malloc.c b/malloc/malloc.c index 17dd0a9c96..e00eb0f4e2 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -3781,7 +3781,8 @@ public_mEMALIGn(size_t alignment, size_t bytes) } #endif } - } + } else + (void)mutex_unlock(&ar_ptr->mutex); assert(!p || chunk_is_mmapped(mem2chunk(p)) || ar_ptr == arena_for_chunk(mem2chunk(p))); return p; 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 + + * 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 * 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 , 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 , 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 #include #include #include @@ -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 , 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