]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl/pthread_rwlock_timedrdlock.c
Add per-thread cache to malloc
[thirdparty/glibc.git] / nptl / pthread_rwlock_timedrdlock.c
index 80ea83a3dd82e7043cc95d1ad56e5020ee318916..9f084f8c3486885da770417bec46fd33d26164e4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2017 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <pthread.h>
-#include <pthreadP.h>
+#include "pthread_rwlock_common.c"
 
-
-/* Try to acquire read lock for RWLOCK or return after specfied time.  */
+/* See pthread_rwlock_common.c.  */
 int
-pthread_rwlock_timedrdlock (rwlock, abstime)
-     pthread_rwlock_t *rwlock;
-     const struct timespec *abstime;
+pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
+    const struct timespec *abstime)
 {
-  int result = 0;
-
-  /* Make sure we are along.  */
-  lll_mutex_lock(rwlock->__data.__lock);
-
-  while (1)
-    {
-      int err;
-
-      /* Get the rwlock if there is no writer...  */
-      if (rwlock->__data.__writer == 0
-         /* ...and if either no writer is waiting or we prefer readers.  */
-         && (!rwlock->__data.__nr_writers_queued
-             || rwlock->__data.__flags == 0))
-       {
-         /* Increment the reader counter.  Avoid overflow.  */
-         if (++rwlock->__data.__nr_readers == 0)
-           {
-             /* Overflow on number of readers.  */
-             --rwlock->__data.__nr_readers;
-             result = EAGAIN;
-           }
-
-         break;
-       }
-
-      /* Make sure we are not holding the rwlock as a writer.  This is
-        a deadlock situation we recognize and report.  */
-      if (__builtin_expect (rwlock->__data.__writer
-                           == THREAD_GETMEM (THREAD_SELF, tid), 0))
-       {
-         result = EDEADLK;
-         break;
-       }
-
-      /* Make sure the passed in timeout value is valid.  Ideally this
-        test would be executed once.  But since it must not be
-        performed if we would not block at all simply moving the test
-        to the front is no option.  Replicating all the code is
-        costly while this test is not.  */
-      if (__builtin_expect (abstime->tv_nsec >= 1000000000
-                            || abstime->tv_nsec < 0, 0))
-       {
-         result = EINVAL;
-         break;
-       }
-
-      /* Get the current time.  So far we support only one clock.  */
-      struct timeval tv;
-      (void) gettimeofday (&tv, NULL);
-
-      /* Convert the absolute timeout value to a relative timeout.  */
-      struct timespec rt;
-      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
-      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
-      if (rt.tv_nsec < 0)
-       {
-         rt.tv_nsec += 1000000000;
-         --rt.tv_sec;
-       }
-      /* Did we already time out?  */
-      if (rt.tv_sec < 0)
-       {
-         /* Yep, return with an appropriate error.  */
-         result = ETIMEDOUT;
-         break;
-       }
-
-      /* Remember that we are a reader.  */
-      if (++rwlock->__data.__nr_readers_queued == 0)
-       {
-         /* Overflow on number of queued readers.  */
-         --rwlock->__data.__nr_readers_queued;
-         result = EAGAIN;
-         break;
-       }
-
-      int waitval = rwlock->__data.__readers_wakeup;
-
-      /* Free the lock.  */
-      lll_mutex_unlock (rwlock->__data.__lock);
-
-      /* Wait for the writer to finish.  */
-      err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
-                                 waitval, &rt);
-
-      /* Get the lock.  */
-      lll_mutex_lock (rwlock->__data.__lock);
-
-      --rwlock->__data.__nr_readers_queued;
-
-      /* Did the futex call time out?  */
-      if (err == -ETIMEDOUT)
-       {
-         /* Yep, report it.  */
-         result = ETIMEDOUT;
-         break;
-       }
-    }
-
-  /* We are done, free the lock.  */
-  lll_mutex_unlock (rwlock->__data.__lock);
-
-  return result;
+  /* Make sure the passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  /* ??? Just move this to __pthread_rwlock_rdlock_full?  */
+  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
+  return __pthread_rwlock_rdlock_full (rwlock, abstime);
 }