]>
Commit | Line | Data |
---|---|---|
0bc91edf UD |
1 | /* Copyright (C) 2002, 2003 Free Software Foundation, Inc. |
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 | |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
19 | ||
20 | #include <sysdep.h> | |
21 | #include <shlib-compat.h> | |
22 | #include <lowlevelcond.h> | |
23 | #include <tcb-offsets.h> | |
24 | ||
25 | #ifdef UP | |
26 | # define LOCK | |
27 | #else | |
28 | # define LOCK lock | |
29 | #endif | |
30 | ||
31 | #define SYS_futex 202 | |
32 | #define FUTEX_WAIT 0 | |
33 | #define FUTEX_WAKE 1 | |
34 | ||
35 | ||
36 | .text | |
37 | ||
38 | .align 16 | |
39 | .type __condvar_cleanup, @function | |
40 | .globl __condvar_cleanup | |
41 | .hidden __condvar_cleanup | |
42 | __condvar_cleanup: | |
43 | /* Get internal lock. */ | |
44 | movq %rdi, %r8 | |
5a03acfe | 45 | movq 8(%rdi), %rdi |
0bc91edf | 46 | movl $1, %esi |
3a226d33 | 47 | xorl %eax, %eax |
0bc91edf UD |
48 | LOCK |
49 | #if cond_lock == 0 | |
3a226d33 | 50 | cmpxchgl %esi, (%rdi) |
0bc91edf | 51 | #else |
3a226d33 | 52 | cmpxchgl %esi, cond_lock(%rdi) |
0bc91edf | 53 | #endif |
3a226d33 | 54 | jz 1f |
0bc91edf UD |
55 | |
56 | #if cond_lock != 0 | |
57 | addq $cond_lock, %rdi | |
58 | #endif | |
59 | callq __lll_mutex_lock_wait | |
60 | #if cond_lock != 0 | |
61 | subq $cond_lock, %rdi | |
62 | #endif | |
63 | ||
7abed170 | 64 | 1: incq wakeup_seq(%rdi) |
0bc91edf | 65 | |
7abed170 | 66 | incq woken_seq(%rdi) |
0bc91edf UD |
67 | |
68 | LOCK | |
69 | #if cond_lock == 0 | |
70 | decl (%rdi) | |
71 | #else | |
72 | decl cond_lock(%rdi) | |
73 | #endif | |
74 | je 2f | |
75 | #if cond_lock != 0 | |
76 | addq $cond_lock, %rdi | |
77 | #endif | |
78 | callq __lll_mutex_unlock_wake | |
79 | ||
24a49f38 UD |
80 | /* Wake up all waiters to make sure no signal gets lost. */ |
81 | 2: addq $wakeup_seq, %rdi | |
82 | movq $FUTEX_WAKE, %rsi | |
83 | movl $0x7fffffff, %edx | |
84 | movq $SYS_futex, %rax | |
85 | syscall | |
86 | ||
5a03acfe | 87 | movq 16(%r8), %rdi |
69431c9a | 88 | callq __pthread_mutex_cond_lock |
0bc91edf | 89 | |
7661d9f7 | 90 | retq |
0bc91edf UD |
91 | .size __condvar_cleanup, .-__condvar_cleanup |
92 | ||
93 | ||
94 | /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ | |
95 | .globl __pthread_cond_wait | |
96 | .type __pthread_cond_wait, @function | |
97 | .align 16 | |
98 | __pthread_cond_wait: | |
ad2be852 | 99 | .LSTARTCODE: |
5a03acfe | 100 | pushq %r12 |
ad2be852 | 101 | .Lpush_r12: |
0bc91edf | 102 | subq $64, %rsp |
ad2be852 | 103 | .Lsubq: |
7abed170 UD |
104 | /* Stack frame: |
105 | ||
106 | rsp + 64 | |
107 | +--------------------------+ | |
108 | rsp + 32 | cleanup buffer | | |
109 | +--------------------------+ | |
110 | rsp + 24 | old wake_seq value | | |
111 | +--------------------------+ | |
112 | rsp + 16 | mutex pointer | | |
113 | +--------------------------+ | |
114 | rsp + 8 | condvar pointer | | |
115 | +--------------------------+ | |
116 | rsp + 0 | old cancellation mode | | |
117 | +--------------------------+ | |
118 | */ | |
0bc91edf UD |
119 | |
120 | /* Prepare structure passed to cancellation handler. */ | |
121 | movq %rdi, 8(%rsp) | |
122 | movq %rsi, 16(%rsp) | |
123 | ||
7661d9f7 UD |
124 | movq %rsi, dep_mutex(%rdi) |
125 | ||
0bc91edf UD |
126 | /* Get internal lock. */ |
127 | movl $1, %esi | |
3a226d33 | 128 | xorl %eax, %eax |
0bc91edf UD |
129 | LOCK |
130 | #if cond_lock == 0 | |
3a226d33 | 131 | cmpxchgl %esi, (%rdi) |
0bc91edf | 132 | #else |
3a226d33 | 133 | cmpxchgl %esi, cond_lock(%rdi) |
0bc91edf | 134 | #endif |
0bc91edf UD |
135 | jne 1f |
136 | ||
137 | /* Unlock the mutex. */ | |
7661d9f7 | 138 | 2: movq 16(%rsp), %rdi |
61623643 UD |
139 | xorq %rsi, %rsi |
140 | callq __pthread_mutex_unlock_usercnt | |
0bc91edf UD |
141 | |
142 | testl %eax, %eax | |
143 | jne 12f | |
144 | ||
35e148cb | 145 | movq 8(%rsp), %rdi |
7abed170 | 146 | incq total_seq(%rdi) |
0bc91edf UD |
147 | |
148 | /* Install cancellation handler. */ | |
149 | #ifdef PIC | |
5a03acfe | 150 | leaq __condvar_cleanup(%rip), %rsi |
0bc91edf UD |
151 | #else |
152 | leaq __condvar_cleanup, %rsi | |
153 | #endif | |
154 | leaq 32(%rsp), %rdi | |
155 | movq %rsp, %rdx | |
156 | callq __pthread_cleanup_push | |
157 | ||
158 | /* Get and store current wakeup_seq value. */ | |
159 | movq 8(%rsp), %rdi | |
160 | movq wakeup_seq(%rdi), %r12 | |
161 | movq %r12, 24(%rsp) | |
162 | ||
163 | /* Unlock. */ | |
164 | 8: LOCK | |
165 | #if cond_lock == 0 | |
166 | decl (%rdi) | |
167 | #else | |
168 | decl cond_lock(%rdi) | |
169 | #endif | |
170 | jne 3f | |
171 | ||
69431c9a | 172 | 4: callq __pthread_enable_asynccancel |
7661d9f7 | 173 | movl %eax, (%rsp) |
0bc91edf | 174 | |
32a589b1 | 175 | movq 8(%rsp), %rdi |
0bc91edf UD |
176 | xorq %r10, %r10 |
177 | movq %r12, %rdx | |
178 | addq $wakeup_seq-cond_lock, %rdi | |
179 | movq $SYS_futex, %rax | |
92ed3daf | 180 | movq %r10, %rsi /* movq $FUTEX_WAIT, %rsi */ |
0bc91edf | 181 | syscall |
0bc91edf | 182 | |
7661d9f7 | 183 | movl (%rsp), %edi |
0bc91edf UD |
184 | callq __pthread_disable_asynccancel |
185 | ||
186 | /* Lock. */ | |
187 | movq 8(%rsp), %rdi | |
188 | movl $1, %esi | |
3a226d33 | 189 | xorl %eax, %eax |
0bc91edf UD |
190 | LOCK |
191 | #if cond_lock == 0 | |
3a226d33 | 192 | cmpxchgl %esi, (%rdi) |
0bc91edf | 193 | #else |
3a226d33 | 194 | cmpxchgl %esi, cond_lock(%rdi) |
0bc91edf | 195 | #endif |
3a226d33 | 196 | jnz 5f |
0bc91edf UD |
197 | |
198 | 6: movq woken_seq(%rdi), %rax | |
199 | ||
200 | movq wakeup_seq(%rdi), %r12 | |
201 | ||
46a32546 UD |
202 | cmpq 24(%rsp), %r12 |
203 | jbe 8b | |
0bc91edf UD |
204 | |
205 | cmpq %rax, %r12 | |
206 | jna 8b | |
207 | ||
208 | incq woken_seq(%rdi) | |
209 | ||
210 | LOCK | |
211 | #if cond_lock == 0 | |
212 | decl (%rdi) | |
213 | #else | |
214 | decl cond_lock(%rdi) | |
215 | #endif | |
216 | jne 10f | |
217 | ||
218 | /* Remove cancellation handler. */ | |
219 | 11: movq 32+CLEANUP_PREV(%rsp), %rdx | |
35e148cb | 220 | movq %rdx, %fs:CLEANUP |
0bc91edf UD |
221 | |
222 | movq 16(%rsp), %rdi | |
69431c9a | 223 | callq __pthread_mutex_cond_lock |
0bc91edf | 224 | 14: addq $64, %rsp |
ad2be852 | 225 | .Laddq: |
0bc91edf UD |
226 | |
227 | popq %r12 | |
ad2be852 | 228 | .Lpop_r12: |
0bc91edf UD |
229 | |
230 | /* We return the result of the mutex_lock operation. */ | |
231 | retq | |
232 | ||
233 | /* Initial locking failed. */ | |
234 | 1: | |
ad2be852 | 235 | .LSbl1: |
0bc91edf UD |
236 | #if cond_lock != 0 |
237 | addq $cond_lock, %rdi | |
238 | #endif | |
239 | callq __lll_mutex_lock_wait | |
240 | jmp 2b | |
241 | ||
242 | /* Unlock in loop requires waekup. */ | |
243 | 3: | |
244 | #if cond_lock != 0 | |
245 | addq $cond_lock, %rdi | |
246 | #endif | |
247 | callq __lll_mutex_unlock_wake | |
0bc91edf UD |
248 | jmp 4b |
249 | ||
250 | /* Locking in loop failed. */ | |
251 | 5: | |
252 | #if cond_lock != 0 | |
253 | addq $cond_lock, %rdi | |
254 | #endif | |
6c477888 | 255 | callq __lll_mutex_lock_wait |
0bc91edf UD |
256 | #if cond_lock != 0 |
257 | subq $cond_lock, %rdi | |
258 | #endif | |
259 | jmp 6b | |
260 | ||
261 | /* Unlock after loop requires wakeup. */ | |
262 | 10: | |
263 | #if cond_lock != 0 | |
264 | addq $cond_lock, %rdi | |
265 | #endif | |
266 | callq __lll_mutex_unlock_wake | |
267 | jmp 11b | |
268 | ||
269 | /* The initial unlocking of the mutex failed. */ | |
270 | 12: movq %rax, %r10 | |
271 | movq 8(%rsp), %rdi | |
272 | LOCK | |
273 | #if cond_lock == 0 | |
274 | decl (%rdi) | |
275 | #else | |
276 | decl cond_lock(%rdi) | |
277 | #endif | |
278 | jne 13f | |
279 | ||
280 | #if cond_lock != 0 | |
281 | addq $cond_lock, %rdi | |
282 | #endif | |
283 | callq __lll_mutex_unlock_wake | |
284 | ||
285 | 13: movq %r10, %rax | |
286 | jmp 14b | |
ad2be852 | 287 | .LENDCODE: |
0bc91edf UD |
288 | .size __pthread_cond_wait, .-__pthread_cond_wait |
289 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | |
290 | GLIBC_2_3_2) | |
ad2be852 UD |
291 | |
292 | ||
293 | .section .eh_frame,"a",@progbits | |
294 | .LSTARTFRAME: | |
39a46c42 | 295 | .long L(ENDCIE)-L(STARTCIE) # Length of the CIE. |
ad2be852 | 296 | .LSTARTCIE: |
39a46c42 UD |
297 | .long 0 # CIE ID. |
298 | .byte 1 # Version number. | |
ad2be852 | 299 | #ifdef SHARED |
39a46c42 UD |
300 | .string "zR" # NUL-terminated augmentation |
301 | # string. | |
ad2be852 | 302 | #else |
39a46c42 UD |
303 | .ascii "\0" # NUL-terminated augmentation |
304 | # string. | |
ad2be852 | 305 | #endif |
39a46c42 UD |
306 | .uleb128 1 # Code alignment factor. |
307 | .sleb128 -8 # Data alignment factor. | |
308 | .byte 16 # Return address register | |
309 | # column. | |
ad2be852 | 310 | #ifdef SHARED |
39a46c42 UD |
311 | .uleb128 1 # Augmentation value length. |
312 | .byte 0x1b # Encoding: DW_EH_PE_pcrel | |
313 | # + DW_EH_PE_sdata4. | |
ad2be852 | 314 | #endif |
39a46c42 | 315 | .byte 0x0c # DW_CFA_def_cfa |
ad2be852 UD |
316 | .uleb128 7 |
317 | .uleb128 8 | |
39a46c42 | 318 | .byte 0x90 # DW_CFA_offset, column 0x8 |
ad2be852 UD |
319 | .uleb128 1 |
320 | .align 8 | |
321 | .LENDCIE: | |
322 | ||
39a46c42 | 323 | .long .LENDFDE-.LSTARTFDE # Length of the FDE. |
ad2be852 | 324 | .LSTARTFDE: |
39a46c42 | 325 | .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. |
ad2be852 | 326 | #ifdef SHARED |
39a46c42 UD |
327 | .long .LSTARTCODE-. # PC-relative start address |
328 | # of the code | |
ad2be852 | 329 | #else |
39a46c42 | 330 | .long .LSTARTCODE # Start address of the code. |
ad2be852 | 331 | #endif |
39a46c42 | 332 | .long .LENDCODE-.LSTARTCODE # Length of the code. |
ad2be852 | 333 | #ifdef SHARED |
39a46c42 | 334 | .uleb128 0 # No augmentation data. |
ad2be852 | 335 | #endif |
39a46c42 UD |
336 | .byte 0x40+.Lpush_r12-.LSTARTCODE # DW_CFA_advance_loc+N |
337 | .byte 14 # DW_CFA_def_cfa_offset | |
ad2be852 | 338 | .uleb128 16 |
39a46c42 UD |
339 | .byte 0x8c # DW_CFA_offset %r12 |
340 | .uleb128 2 | |
341 | .byte 0x40+.Lsubq-.Lpush_r12 # DW_CFA_advance_loc+N | |
342 | .byte 14 # DW_CFA_def_cfa_offset | |
ad2be852 | 343 | .uleb128 80 |
18ddd3aa UD |
344 | .byte 2 # DW_CFA_advance_loc1 |
345 | .byte .Laddq-.Lsubq | |
39a46c42 | 346 | .byte 14 # DW_CFA_def_cfa_offset |
ad2be852 | 347 | .uleb128 16 |
39a46c42 UD |
348 | .byte 0x40+.Lpop_r12-.Laddq # DW_CFA_advance_loc+N |
349 | .byte 14 # DW_CFA_def_cfa_offset | |
ad2be852 | 350 | .uleb128 8 |
39a46c42 UD |
351 | .byte 0xcc # DW_CFA_restore %r12 |
352 | .byte 0x40+.LSbl1-.Lpop_r12 # DW_CFA_advance_loc+N | |
353 | .byte 14 # DW_CFA_def_cfa_offset | |
ad2be852 | 354 | .uleb128 80 |
39a46c42 UD |
355 | .byte 0x8c # DW_CFA_offset %r12 |
356 | .uleb128 2 | |
ad2be852 UD |
357 | .align 8 |
358 | .LENDFDE: |