summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--nptl/ChangeLog9
-rw-r--r--nptl/DESIGN-rwlock.txt4
-rw-r--r--nptl/sysdeps/pthread/pthread_rwlock_unlock.c21
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S26
-rw-r--r--sysdeps/unix/sysv/linux/ia64/sysdep.S13
6 files changed, 63 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index b9e7b6c364..a7e4c09b71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2003-02-24 David Mosberger <davidm@hpl.hp.com>
+
+ * sysdeps/unix/sysv/linux/ia64/sysdep.S (__syscall_error): Fix
+ unwind info.
+
2003-02-27 Ulrich Drepper <drepper@redhat.com>
* resolv/res_libc.c [USE___THREAD] (_res): Don't need the
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 11db7094ca..e81af68ce1 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,12 @@
+2003-02-27 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/pthread/pthread_rwlock_unlock.c
+ (__pthread_rwlock_unlock): Release internal lock early. Don't try
+ to wake up readers if there are none.
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S:
+ Release internal lock before wake threads.
+
2003-02-26 Ulrich Drepper <drepper@redhat.com>
* Makefile (tests): Add tst-rwlock10 and tst-rwlock11.
diff --git a/nptl/DESIGN-rwlock.txt b/nptl/DESIGN-rwlock.txt
index d97c084484..cdbd4ce9ef 100644
--- a/nptl/DESIGN-rwlock.txt
+++ b/nptl/DESIGN-rwlock.txt
@@ -96,11 +96,15 @@ pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
if (!rwlock->readers) {
if (rwlock->nr_writers_queued) {
++rwlock->writer_wakeup;
+ lll_unlock(rwlock->lock);
futex_wake(&rwlock->writer_wakeup, 1);
+ return;
} else
if (rwlock->nr_readers_queued) {
++rwlock->readers_wakeup;
+ lll_unlock(rwlock->lock);
futex_wake(&rwlock->readers_wakeup, MAX_INT);
+ return;
}
}
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_unlock.c b/nptl/sysdeps/pthread/pthread_rwlock_unlock.c
index 6e0c92ba3f..9cae8b6c22 100644
--- a/nptl/sysdeps/pthread/pthread_rwlock_unlock.c
+++ b/nptl/sysdeps/pthread/pthread_rwlock_unlock.c
@@ -24,27 +24,32 @@
#include <pthreadP.h>
/* Unlock RWLOCK. */
-int __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+int
+__pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
{
- lll_mutex_lock(rwlock->__data.__lock);
+ lll_mutex_lock (rwlock->__data.__lock);
if (rwlock->__data.__writer)
rwlock->__data.__writer = 0;
else
- rwlock->__data.__nr_readers--;
- if (!rwlock->__data.__nr_readers)
+ --rwlock->__data.__nr_readers;
+ if (rwlock->__data.__nr_readers == 0)
{
if (rwlock->__data.__nr_writers_queued)
{
++rwlock->__data.__writer_wakeup;
- lll_futex_wake(&rwlock->__data.__writer_wakeup, 1);
+ lll_mutex_unlock (rwlock->__data.__lock);
+ lll_futex_wake (&rwlock->__data.__writer_wakeup, 1);
+ return 0;
}
- else
+ else if (rwlock->__data.__nr_readers_queued)
{
++rwlock->__data.__readers_wakeup;
- lll_futex_wake(&rwlock->__data.__readers_wakeup, INT_MAX);
+ lll_mutex_unlock (rwlock->__data.__lock);
+ lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX);
+ return 0;
}
}
- lll_mutex_unlock(rwlock->__data.__lock);
+ lll_mutex_unlock (rwlock->__data.__lock);
return 0;
}
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S
index bb5f8d1bc8..7dd97ba49e 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S
@@ -76,10 +76,25 @@ __pthread_rwlock_unlock:
leal READERS_WAKEUP(%edi), %ebx
0: incl (%ebx)
- xorl %esi, %esi
+ LOCK
+#if MUTEX == 0
+ decl (%edi)
+#else
+ decl MUTEX(%edi)
+#endif
+ jne 7f
+
+8: xorl %esi, %esi
movl $SYS_futex, %eax
ENTER_KERNEL
+ xorl %eax, %eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ ret
+
+ .align 16
6: LOCK
#if MUTEX == 0
decl (%edi)
@@ -112,6 +127,15 @@ __pthread_rwlock_unlock:
call __lll_mutex_unlock_wake
jmp 4b
+7:
+#if MUTEX == 0
+ movl %edi, %eax
+#else
+ leal MUTEX(%edx), %eax
+#endif
+ call __lll_mutex_unlock_wake
+ jmp 8b
+
.size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock
.globl pthread_rwlock_unlock
diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.S b/sysdeps/unix/sysv/linux/ia64/sysdep.S
index 31b5f9bde9..c053c3a053 100644
--- a/sysdeps/unix/sysv/linux/ia64/sysdep.S
+++ b/sysdeps/unix/sysv/linux/ia64/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
@@ -23,18 +23,19 @@
ENTRY(__syscall_error)
#ifdef _LIBC_REENTRANT
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0)
- alloc r35=ar.pfs, 0, 4, 0, 0
+ alloc r33=ar.pfs, 0, 4, 0, 0
mov r32=rp
- mov r33=r8
+ .body
+ mov r35=r8
mov r34=r1
;;
- br.call.sptk.many b0 = __errno_location#
+ br.call.sptk.many b0 = __errno_location
.Lret0: /* force new bundle */
- st4 [r8]=r33
+ st4 [r8]=r35
mov r1=r34
mov rp=r32
mov r8=-1
- mov ar.pfs=r35
+ mov ar.pfs=r33
#else /* _LIBC_REENTRANT */
/*
* Note that the gp has to be set properly for this to work.