]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl/pthread_rwlock_unlock.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl / pthread_rwlock_unlock.c
index d4923838e718b03b5739a0ebf0490d55caf36776..b8c8f204db30a48d87098237fe6d9a773591df35 100644 (file)
@@ -1,4 +1,4 @@
-/* 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;
 }