Back to index

glibc  2.9
lowlevellock.c
Go to the documentation of this file.
00001 /* low level locking for pthread library.  Generic futex-using version.
00002    Copyright (C) 2003, 2005, 2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <sysdep.h>
00022 #include <lowlevellock.h>
00023 #include <sys/time.h>
00024 
00025 void
00026 __lll_lock_wait_private (int *futex)
00027 {
00028   do
00029     {
00030       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
00031       if (oldval != 0)
00032        lll_futex_wait (futex, 2, LLL_PRIVATE);
00033     }
00034   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
00035 }
00036 
00037 
00038 /* These functions don't get included in libc.so  */
00039 #ifdef IS_IN_libpthread
00040 void
00041 __lll_lock_wait (int *futex, int private)
00042 {
00043   do
00044     {
00045       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
00046       if (oldval != 0)
00047        lll_futex_wait (futex, 2, private);
00048     }
00049   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
00050 }
00051 
00052 
00053 int
00054 __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
00055 {
00056   struct timespec rt;
00057 
00058   /* Reject invalid timeouts.  */
00059   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
00060     return EINVAL;
00061 
00062   /* Upgrade the lock.  */
00063   if (atomic_exchange_acq (futex, 2) == 0)
00064     return 0;
00065 
00066   do
00067     {
00068       struct timeval tv;
00069 
00070       /* Get the current time.  */
00071       (void) __gettimeofday (&tv, NULL);
00072 
00073       /* Compute relative timeout.  */
00074       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
00075       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
00076       if (rt.tv_nsec < 0)
00077        {
00078          rt.tv_nsec += 1000000000;
00079          --rt.tv_sec;
00080        }
00081 
00082       /* Already timed out?  */
00083       if (rt.tv_sec < 0)
00084        return ETIMEDOUT;
00085 
00086       // XYZ: Lost the lock to check whether it was private.
00087       lll_futex_timed_wait (futex, 2, &rt, private);
00088     }
00089   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
00090 
00091   return 0;
00092 }
00093 
00094 
00095 int
00096 __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
00097 {
00098   int tid;
00099 
00100   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
00101     return EINVAL;
00102 
00103   /* Repeat until thread terminated.  */
00104   while ((tid = *tidp) != 0)
00105     {
00106       struct timeval tv;
00107       struct timespec rt;
00108 
00109       /* Get the current time.  */
00110       (void) __gettimeofday (&tv, NULL);
00111 
00112       /* Compute relative timeout.  */
00113       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
00114       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
00115       if (rt.tv_nsec < 0)
00116        {
00117          rt.tv_nsec += 1000000000;
00118          --rt.tv_sec;
00119        }
00120 
00121       /* Already timed out?  */
00122       if (rt.tv_sec < 0)
00123        return ETIMEDOUT;
00124 
00125       /* Wait until thread terminates.  */
00126       // XYZ: Lost the lock to check whether it was private.
00127       if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
00128        return ETIMEDOUT;
00129     }
00130 
00131   return 0;
00132 }
00133 #endif