]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/lowlevellock.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl / lowlevellock.c
CommitLineData
f3c13160 1/* low level locking for pthread library. Generic futex-using version.
b168057a 2 Copyright (C) 2003-2015 Free Software Foundation, Inc.
f3c13160
RM
3 This file is part of the GNU C Library.
4 Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
f3c13160
RM
19
20#include <errno.h>
21#include <sysdep.h>
22#include <lowlevellock.h>
23#include <sys/time.h>
05087fbb 24#include <atomic.h>
f3c13160
RM
25
26void
e51deae7 27__lll_lock_wait_private (int *futex)
f3c13160 28{
c012be6f 29 if (*futex == 2)
d52c62df 30 lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
c012be6f
UD
31
32 while (atomic_exchange_acq (futex, 2) != 0)
d52c62df 33 lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
e51deae7
UD
34}
35
36
467d1345 37/* These functions don't get included in libc.so */
ce9f10f7 38#if IS_IN (libpthread)
e51deae7
UD
39void
40__lll_lock_wait (int *futex, int private)
41{
c012be6f 42 if (*futex == 2)
d52c62df 43 lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
c012be6f
UD
44
45 while (atomic_exchange_acq (futex, 2) != 0)
d52c62df 46 lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
f3c13160 47}
f3c13160
RM
48
49
50int
e51deae7 51__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
f3c13160 52{
f3c13160 53 /* Reject invalid timeouts. */
31195be2 54 if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
f3c13160
RM
55 return EINVAL;
56
c012be6f
UD
57 /* Try locking. */
58 while (atomic_exchange_acq (futex, 2) != 0)
f3c13160
RM
59 {
60 struct timeval tv;
f3c13160
RM
61
62 /* Get the current time. */
bd0fa4ce 63 (void) __gettimeofday (&tv, NULL);
f3c13160
RM
64
65 /* Compute relative timeout. */
c012be6f 66 struct timespec rt;
bd0fa4ce
UD
67 rt.tv_sec = abstime->tv_sec - tv.tv_sec;
68 rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
69 if (rt.tv_nsec < 0)
f3c13160 70 {
bd0fa4ce
UD
71 rt.tv_nsec += 1000000000;
72 --rt.tv_sec;
f3c13160
RM
73 }
74
c012be6f
UD
75 if (rt.tv_sec < 0)
76 return ETIMEDOUT;
f3c13160 77
d52c62df 78 /* If *futex == 2, wait until woken or timeout. */
c012be6f 79 lll_futex_timed_wait (futex, 2, &rt, private);
bd0fa4ce 80 }
f3c13160 81
c012be6f 82 return 0;
f3c13160 83}
f3c13160
RM
84
85
d52c62df
TR
86/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
87 wake-up when the clone terminates. The memory location contains the
88 thread ID while the clone is running and is reset to zero by the kernel
89 afterwards. The kernel up to version 3.16.3 does not use the private futex
90 operations for futex wake-up when the clone terminates. */
f3c13160
RM
91int
92__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
93{
94 int tid;
f3c13160 95
31195be2 96 if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
f3c13160
RM
97 return EINVAL;
98
99 /* Repeat until thread terminated. */
100 while ((tid = *tidp) != 0)
101 {
102 struct timeval tv;
103 struct timespec rt;
f3c13160
RM
104
105 /* Get the current time. */
bd0fa4ce 106 (void) __gettimeofday (&tv, NULL);
f3c13160
RM
107
108 /* Compute relative timeout. */
bd0fa4ce
UD
109 rt.tv_sec = abstime->tv_sec - tv.tv_sec;
110 rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
111 if (rt.tv_nsec < 0)
f3c13160 112 {
bd0fa4ce
UD
113 rt.tv_nsec += 1000000000;
114 --rt.tv_sec;
f3c13160
RM
115 }
116
117 /* Already timed out? */
bd0fa4ce
UD
118 if (rt.tv_sec < 0)
119 return ETIMEDOUT;
f3c13160 120
d52c62df
TR
121 /* If *tidp == tid, wait until thread terminates or the wait times out.
122 The kernel up to version 3.16.3 does not use the private futex
123 operations for futex wake-up when the clone terminates.
124 */
835abc5c 125 if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
bd0fa4ce 126 return ETIMEDOUT;
f3c13160
RM
127 }
128
bd0fa4ce 129 return 0;
f3c13160 130}
f3c13160 131#endif