diff options
Diffstat (limited to 'libpthread/nptl/pthread_rwlock_init.c')
-rw-r--r-- | libpthread/nptl/pthread_rwlock_init.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/libpthread/nptl/pthread_rwlock_init.c b/libpthread/nptl/pthread_rwlock_init.c index 8055960e0..aab832eea 100644 --- a/libpthread/nptl/pthread_rwlock_init.c +++ b/libpthread/nptl/pthread_rwlock_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -18,6 +18,7 @@ 02111-1307 USA. */ #include "pthreadP.h" +#include <bits/kernel-features.h> static const struct pthread_rwlockattr default_attr = @@ -36,15 +37,36 @@ __pthread_rwlock_init ( iattr = ((const struct pthread_rwlockattr *) attr) ?: &default_attr; - rwlock->__data.__lock = 0; + memset (rwlock, '\0', sizeof (*rwlock)); + rwlock->__data.__flags = iattr->lockkind == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP; - rwlock->__data.__nr_readers = 0; - rwlock->__data.__writer = 0; - rwlock->__data.__readers_wakeup = 0; - rwlock->__data.__writer_wakeup = 0; - rwlock->__data.__nr_readers_queued = 0; - rwlock->__data.__nr_writers_queued = 0; + + /* The __SHARED field is computed to minimize the work that needs to + be done while handling the futex. There are two inputs: the + availability of private futexes and whether the rwlock is shared + or private. Unfortunately the value of a private rwlock is + fixed: it must be zero. The PRIVATE_FUTEX flag has the value + 0x80 in case private futexes are available and zero otherwise. + This leads to the following table: + + | pshared | result + | shared private | shared private | + ------------+-----------------+-----------------+ + !avail 0 | 0 0 | 0 0 | + avail 0x80 | 0x80 0 | 0 0x80 | + + If the pshared value is in locking functions XORed with avail + we get the expected result. */ +#ifdef __ASSUME_PRIVATE_FUTEX + rwlock->__data.__shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? 0 : FUTEX_PRIVATE_FLAG); +#else + rwlock->__data.__shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? 0 + : THREAD_GETMEM (THREAD_SELF, + header.private_futex)); +#endif return 0; } |