-/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
#include <errno.h>
#include <sysdep.h>
-#include <lowlevellock.h>
+#include <futex-internal.h>
#include <pthread.h>
#include <pthreadP.h>
#include <stap-probe.h>
-/* Unlock RWLOCK. */
+#include "pthread_rwlock_common.c"
+
+/* See pthread_rwlock_common.c for an overview. */
int
__pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
{
LIBC_PROBE (rwlock_unlock, 1, rwlock);
- lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
- if (rwlock->__data.__writer)
- rwlock->__data.__writer = 0;
+ /* We distinguish between having acquired a read vs. a write lock by looking
+ at the writer TID. If it's equal to our TID, we must be the writer
+ because nobody else can have stored this value. Also, if we are a
+ reader, we will read from the wrunlock store with value 0 by the most
+ recent writer because that writer happens-before us. */
+ if (atomic_load_relaxed (&rwlock->__data.__cur_writer)
+ == THREAD_GETMEM (THREAD_SELF, tid))
+ __pthread_rwlock_wrunlock (rwlock);
else
- --rwlock->__data.__nr_readers;
- if (rwlock->__data.__nr_readers == 0)
- {
- if (rwlock->__data.__nr_writers_queued)
- {
- ++rwlock->__data.__writer_wakeup;
- lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
- lll_futex_wake (&rwlock->__data.__writer_wakeup, 1,
- rwlock->__data.__shared);
- return 0;
- }
- else if (rwlock->__data.__nr_readers_queued)
- {
- ++rwlock->__data.__readers_wakeup;
- lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
- lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX,
- rwlock->__data.__shared);
- return 0;
- }
- }
- lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
+ __pthread_rwlock_rdunlock (rwlock);
return 0;
}