]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 2002-2015 Free Software Foundation, Inc. |
683040c3 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
683040c3 UD |
18 | |
19 | #include <sysdep.h> | |
20 | #include <pthread-errnos.h> | |
e51deae7 | 21 | #include <lowlevellock.h> |
683040c3 | 22 | #include <lowlevelrobustlock.h> |
e51deae7 | 23 | #include <kernel-features.h> |
683040c3 UD |
24 | |
25 | .text | |
26 | ||
683040c3 UD |
27 | #define FUTEX_WAITERS 0x80000000 |
28 | #define FUTEX_OWNER_DIED 0x40000000 | |
29 | ||
e51deae7 UD |
30 | #ifdef __ASSUME_PRIVATE_FUTEX |
31 | # define LOAD_FUTEX_WAIT(reg) \ | |
32 | xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg | |
33 | #else | |
34 | # if FUTEX_WAIT == 0 | |
35 | # define LOAD_FUTEX_WAIT(reg) \ | |
36 | xorl $FUTEX_PRIVATE_FLAG, reg ; \ | |
37 | andl %gs:PRIVATE_FUTEX, reg | |
38 | # else | |
39 | # define LOAD_FUTEX_WAIT(reg) \ | |
40 | xorl $FUTEX_PRIVATE_FLAG, reg ; \ | |
41 | andl %gs:PRIVATE_FUTEX, reg ; \ | |
42 | orl $FUTEX_WAIT, reg | |
43 | # endif | |
44 | #endif | |
683040c3 | 45 | |
e51deae7 UD |
46 | .globl __lll_robust_lock_wait |
47 | .type __lll_robust_lock_wait,@function | |
48 | .hidden __lll_robust_lock_wait | |
683040c3 | 49 | .align 16 |
e51deae7 | 50 | __lll_robust_lock_wait: |
cd248c3f | 51 | cfi_startproc |
683040c3 | 52 | pushl %edx |
cd248c3f | 53 | cfi_adjust_cfa_offset(4) |
683040c3 | 54 | pushl %ebx |
cd248c3f | 55 | cfi_adjust_cfa_offset(4) |
683040c3 | 56 | pushl %esi |
cd248c3f UD |
57 | cfi_adjust_cfa_offset(4) |
58 | cfi_offset(%edx, -8) | |
59 | cfi_offset(%ebx, -12) | |
60 | cfi_offset(%esi, -16) | |
683040c3 | 61 | |
e51deae7 | 62 | movl %edx, %ebx |
683040c3 | 63 | xorl %esi, %esi /* No timeout. */ |
e51deae7 | 64 | LOAD_FUTEX_WAIT (%ecx) |
683040c3 UD |
65 | |
66 | 4: movl %eax, %edx | |
67 | orl $FUTEX_WAITERS, %edx | |
68 | ||
69 | testl $FUTEX_OWNER_DIED, %eax | |
70 | jnz 3f | |
71 | ||
72 | cmpl %edx, %eax /* NB: %edx == 2 */ | |
73 | je 1f | |
74 | ||
75 | LOCK | |
76 | cmpxchgl %edx, (%ebx) | |
77 | jnz 2f | |
78 | ||
79 | 1: movl $SYS_futex, %eax | |
80 | ENTER_KERNEL | |
81 | ||
82 | movl (%ebx), %eax | |
83 | ||
84 | 2: test %eax, %eax | |
85 | jne 4b | |
86 | ||
87 | movl %gs:TID, %edx | |
42b6ddfc | 88 | orl $FUTEX_WAITERS, %edx |
683040c3 UD |
89 | LOCK |
90 | cmpxchgl %edx, (%ebx) | |
91 | jnz 4b | |
92 | /* NB: %eax == 0 */ | |
93 | ||
94 | 3: popl %esi | |
cd248c3f UD |
95 | cfi_adjust_cfa_offset(-4) |
96 | cfi_restore(%esi) | |
683040c3 | 97 | popl %ebx |
cd248c3f UD |
98 | cfi_adjust_cfa_offset(-4) |
99 | cfi_restore(%ebx) | |
683040c3 | 100 | popl %edx |
cd248c3f UD |
101 | cfi_adjust_cfa_offset(-4) |
102 | cfi_restore(%edx) | |
683040c3 | 103 | ret |
cd248c3f | 104 | cfi_endproc |
e51deae7 | 105 | .size __lll_robust_lock_wait,.-__lll_robust_lock_wait |
683040c3 UD |
106 | |
107 | ||
e51deae7 UD |
108 | .globl __lll_robust_timedlock_wait |
109 | .type __lll_robust_timedlock_wait,@function | |
110 | .hidden __lll_robust_timedlock_wait | |
683040c3 | 111 | .align 16 |
e51deae7 | 112 | __lll_robust_timedlock_wait: |
cd248c3f | 113 | cfi_startproc |
683040c3 UD |
114 | /* Check for a valid timeout value. */ |
115 | cmpl $1000000000, 4(%edx) | |
116 | jae 3f | |
117 | ||
118 | pushl %edi | |
cd248c3f | 119 | cfi_adjust_cfa_offset(4) |
683040c3 | 120 | pushl %esi |
cd248c3f | 121 | cfi_adjust_cfa_offset(4) |
683040c3 | 122 | pushl %ebx |
cd248c3f | 123 | cfi_adjust_cfa_offset(4) |
683040c3 | 124 | pushl %ebp |
cd248c3f UD |
125 | cfi_adjust_cfa_offset(4) |
126 | cfi_offset(%edi, -8) | |
127 | cfi_offset(%esi, -12) | |
128 | cfi_offset(%ebx, -16) | |
129 | cfi_offset(%ebp, -20) | |
683040c3 UD |
130 | |
131 | /* Stack frame for the timespec and timeval structs. */ | |
132 | subl $12, %esp | |
cd248c3f | 133 | cfi_adjust_cfa_offset(12) |
683040c3 UD |
134 | |
135 | movl %ecx, %ebp | |
136 | movl %edx, %edi | |
137 | ||
138 | 1: movl %eax, 8(%esp) | |
139 | ||
140 | /* Get current time. */ | |
141 | movl %esp, %ebx | |
142 | xorl %ecx, %ecx | |
e51deae7 | 143 | movl $__NR_gettimeofday, %eax |
683040c3 UD |
144 | ENTER_KERNEL |
145 | ||
146 | /* Compute relative timeout. */ | |
147 | movl 4(%esp), %eax | |
148 | movl $1000, %edx | |
149 | mul %edx /* Milli seconds to nano seconds. */ | |
150 | movl (%edi), %ecx | |
151 | movl 4(%edi), %edx | |
152 | subl (%esp), %ecx | |
153 | subl %eax, %edx | |
154 | jns 4f | |
155 | addl $1000000000, %edx | |
156 | subl $1, %ecx | |
157 | 4: testl %ecx, %ecx | |
158 | js 8f /* Time is already up. */ | |
159 | ||
160 | /* Store relative timeout. */ | |
161 | movl %ecx, (%esp) | |
162 | movl %edx, 4(%esp) | |
163 | ||
164 | movl %ebp, %ebx | |
165 | ||
166 | movl 8(%esp), %edx | |
167 | movl %edx, %eax | |
168 | orl $FUTEX_WAITERS, %edx | |
169 | ||
170 | testl $FUTEX_OWNER_DIED, %eax | |
171 | jnz 6f | |
172 | ||
173 | cmpl %eax, %edx | |
174 | je 2f | |
175 | ||
176 | LOCK | |
177 | cmpxchgl %edx, (%ebx) | |
178 | movl $0, %ecx /* Must use mov to avoid changing cc. */ | |
179 | jnz 5f | |
180 | ||
181 | 2: | |
182 | /* Futex call. */ | |
183 | movl %esp, %esi | |
e51deae7 UD |
184 | movl 20(%esp), %ecx |
185 | LOAD_FUTEX_WAIT (%ecx) | |
683040c3 UD |
186 | movl $SYS_futex, %eax |
187 | ENTER_KERNEL | |
188 | movl %eax, %ecx | |
189 | ||
190 | movl (%ebx), %eax | |
191 | ||
192 | 5: testl %eax, %eax | |
193 | jne 7f | |
194 | ||
195 | movl %gs:TID, %edx | |
42b6ddfc | 196 | orl $FUTEX_WAITERS, %edx |
683040c3 UD |
197 | LOCK |
198 | cmpxchgl %edx, (%ebx) | |
199 | jnz 7f | |
200 | ||
201 | 6: addl $12, %esp | |
cd248c3f | 202 | cfi_adjust_cfa_offset(-12) |
683040c3 | 203 | popl %ebp |
cd248c3f UD |
204 | cfi_adjust_cfa_offset(-4) |
205 | cfi_restore(%ebp) | |
683040c3 | 206 | popl %ebx |
cd248c3f UD |
207 | cfi_adjust_cfa_offset(-4) |
208 | cfi_restore(%ebx) | |
683040c3 | 209 | popl %esi |
cd248c3f UD |
210 | cfi_adjust_cfa_offset(-4) |
211 | cfi_restore(%esi) | |
683040c3 | 212 | popl %edi |
cd248c3f UD |
213 | cfi_adjust_cfa_offset(-4) |
214 | cfi_restore(%edi) | |
683040c3 UD |
215 | ret |
216 | ||
cd248c3f UD |
217 | 3: movl $EINVAL, %eax |
218 | ret | |
219 | ||
220 | cfi_adjust_cfa_offset(28) | |
221 | cfi_offset(%edi, -8) | |
222 | cfi_offset(%esi, -12) | |
223 | cfi_offset(%ebx, -16) | |
224 | cfi_offset(%ebp, -20) | |
683040c3 UD |
225 | /* Check whether the time expired. */ |
226 | 7: cmpl $-ETIMEDOUT, %ecx | |
227 | jne 1b | |
228 | ||
229 | 8: movl $ETIMEDOUT, %eax | |
230 | jmp 6b | |
cd248c3f | 231 | cfi_endproc |
e51deae7 | 232 | .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait |