Annotation of /trunk/glibc/patches/glibc-2.16.0-unlock-mutex.patch
Parent Directory | Revision Log
Revision 1925 -
(hide annotations)
(download)
Sun Oct 28 19:05:24 2012 UTC (11 years, 11 months ago) by niro
File size: 20967 byte(s)
Sun Oct 28 19:05:24 2012 UTC (11 years, 11 months ago) by niro
File size: 20967 byte(s)
-more glibc-2.16 fixes
1 | niro | 1925 | --- a/nptl/Makefile |
2 | +++ b/nptl/Makefile | ||
3 | @@ -206,7 +206,7 @@ tests = tst-typesizes \ | ||
4 | tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ | ||
5 | tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ | ||
6 | tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ | ||
7 | - tst-cond20 tst-cond21 tst-cond22 tst-cond23 \ | ||
8 | + tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 \ | ||
9 | tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ | ||
10 | tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ | ||
11 | tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ | ||
12 | @@ -274,6 +275,7 @@ gen-as-const-headers = pthread-errnos.sym | ||
13 | |||
14 | LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst | ||
15 | |||
16 | +LDFLAGS-tst-cond24 = $(no-as-needed) -lrt | ||
17 | |||
18 | include ../Makeconfig | ||
19 | |||
20 | diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S | ||
21 | index d14d7de..6761c13 100644 | ||
22 | --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S | ||
23 | +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S | ||
24 | @@ -212,8 +212,23 @@ __pthread_cond_timedwait: | ||
25 | sete 24(%esp) | ||
26 | je 41f | ||
27 | |||
28 | - /* Normal and PI futexes dont mix. Use normal futex functions only | ||
29 | - if the kernel does not support the PI futex functions. */ | ||
30 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | ||
31 | + successfully, it has already locked the mutex for us and the | ||
32 | + pi_flag (24(%esp)) is set to denote that fact. However, if another | ||
33 | + thread changed the futex value before we entered the wait, the | ||
34 | + syscall may return an EAGAIN and the mutex is not locked. We go | ||
35 | + ahead with a success anyway since later we look at the pi_flag to | ||
36 | + decide if we got the mutex or not. The sequence numbers then make | ||
37 | + sure that only one of the threads actually wake up. We retry using | ||
38 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | ||
39 | + and PI futexes don't mix. | ||
40 | + | ||
41 | + Note that we don't check for EAGAIN specifically; we assume that the | ||
42 | + only other error the futex function could return is EAGAIN (barring | ||
43 | + the ETIMEOUT of course, for the timeout case in futex) since | ||
44 | + anything else would mean an error in our function. It is too | ||
45 | + expensive to do that check for every call (which is quite common in | ||
46 | + case of a large number of threads), so it has been skipped. */ | ||
47 | cmpl $-ENOSYS, %eax | ||
48 | jne 41f | ||
49 | xorl %ecx, %ecx | ||
50 | @@ -273,9 +288,24 @@ __pthread_cond_timedwait: | ||
51 | jne 9f | ||
52 | |||
53 | 15: cmpl $-ETIMEDOUT, %esi | ||
54 | - jne 8b | ||
55 | + je 28f | ||
56 | + | ||
57 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | ||
58 | + release the mutex we had acquired and go back. */ | ||
59 | + movl 24(%esp), %edx | ||
60 | + test %edx, %edx | ||
61 | + jz 8b | ||
62 | + | ||
63 | + /* Adjust the mutex values first and then unlock it. The unlock | ||
64 | + should always succeed or else the kernel did not lock the mutex | ||
65 | + correctly. */ | ||
66 | + movl dep_mutex(%ebx), %eax | ||
67 | + call __pthread_mutex_cond_lock_adjust | ||
68 | + xorl %edx, %edx | ||
69 | + call __pthread_mutex_unlock_usercnt | ||
70 | + jmp 8b | ||
71 | |||
72 | - addl $1, wakeup_seq(%ebx) | ||
73 | +28: addl $1, wakeup_seq(%ebx) | ||
74 | adcl $0, wakeup_seq+4(%ebx) | ||
75 | addl $1, cond_futex(%ebx) | ||
76 | movl $ETIMEDOUT, %esi | ||
77 | diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S | ||
78 | index 366de69..0af06ac 100644 | ||
79 | --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S | ||
80 | +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S | ||
81 | @@ -136,7 +136,6 @@ __pthread_cond_wait: | ||
82 | cmpl $PI_BIT, %eax | ||
83 | jne 18f | ||
84 | |||
85 | -90: | ||
86 | movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx | ||
87 | movl %ebp, %edx | ||
88 | xorl %esi, %esi | ||
89 | @@ -152,11 +151,22 @@ __pthread_cond_wait: | ||
90 | sete 16(%esp) | ||
91 | je 19f | ||
92 | |||
93 | - cmpl $-EAGAIN, %eax | ||
94 | - je 91f | ||
95 | - | ||
96 | - /* Normal and PI futexes dont mix. Use normal futex functions only | ||
97 | - if the kernel does not support the PI futex functions. */ | ||
98 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | ||
99 | + successfully, it has already locked the mutex for us and the | ||
100 | + pi_flag (16(%esp)) is set to denote that fact. However, if another | ||
101 | + thread changed the futex value before we entered the wait, the | ||
102 | + syscall may return an EAGAIN and the mutex is not locked. We go | ||
103 | + ahead with a success anyway since later we look at the pi_flag to | ||
104 | + decide if we got the mutex or not. The sequence numbers then make | ||
105 | + sure that only one of the threads actually wake up. We retry using | ||
106 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | ||
107 | + and PI futexes don't mix. | ||
108 | + | ||
109 | + Note that we don't check for EAGAIN specifically; we assume that the | ||
110 | + only other error the futex function could return is EAGAIN since | ||
111 | + anything else would mean an error in our function. It is too | ||
112 | + expensive to do that check for every call (which is quite common in | ||
113 | + case of a large number of threads), so it has been skipped. */ | ||
114 | cmpl $-ENOSYS, %eax | ||
115 | jne 19f | ||
116 | xorl %ecx, %ecx | ||
117 | @@ -206,12 +216,12 @@ __pthread_cond_wait: | ||
118 | cmpl 8(%esp), %edx | ||
119 | jne 7f | ||
120 | cmpl 4(%esp), %edi | ||
121 | - je 8b | ||
122 | + je 22f | ||
123 | |||
124 | 7: cmpl %ecx, %edx | ||
125 | jne 9f | ||
126 | cmp %eax, %edi | ||
127 | - je 8b | ||
128 | + je 22f | ||
129 | |||
130 | 9: addl $1, woken_seq(%ebx) | ||
131 | adcl $0, woken_seq+4(%ebx) | ||
132 | @@ -287,6 +297,22 @@ __pthread_cond_wait: | ||
133 | jmp 20b | ||
134 | |||
135 | cfi_adjust_cfa_offset(-FRAME_SIZE); | ||
136 | + | ||
137 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | ||
138 | + release the mutex we had acquired and go back. */ | ||
139 | +22: movl 16(%esp), %edx | ||
140 | + test %edx, %edx | ||
141 | + jz 8b | ||
142 | + | ||
143 | + /* Adjust the mutex values first and then unlock it. The unlock | ||
144 | + should always succeed or else the kernel did not lock the mutex | ||
145 | + correctly. */ | ||
146 | + movl dep_mutex(%ebx), %eax | ||
147 | + call __pthread_mutex_cond_lock_adjust | ||
148 | + xorl %edx, %edx | ||
149 | + call __pthread_mutex_unlock_usercnt | ||
150 | + jmp 8b | ||
151 | + | ||
152 | /* Initial locking failed. */ | ||
153 | 1: | ||
154 | #if cond_lock == 0 | ||
155 | @@ -400,77 +426,6 @@ __pthread_cond_wait: | ||
156 | call __lll_unlock_wake | ||
157 | jmp 11b | ||
158 | |||
159 | -91: | ||
160 | -.LcleanupSTART2: | ||
161 | - /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to | ||
162 | - call it again. */ | ||
163 | - | ||
164 | - /* Get internal lock. */ | ||
165 | - movl $1, %edx | ||
166 | - xorl %eax, %eax | ||
167 | - LOCK | ||
168 | -#if cond_lock == 0 | ||
169 | - cmpxchgl %edx, (%ebx) | ||
170 | -#else | ||
171 | - cmpxchgl %edx, cond_lock(%ebx) | ||
172 | -#endif | ||
173 | - jz 92f | ||
174 | - | ||
175 | -#if cond_lock == 0 | ||
176 | - movl %ebx, %edx | ||
177 | -#else | ||
178 | - leal cond_lock(%ebx), %edx | ||
179 | -#endif | ||
180 | -#if (LLL_SHARED-LLL_PRIVATE) > 255 | ||
181 | - xorl %ecx, %ecx | ||
182 | -#endif | ||
183 | - cmpl $-1, dep_mutex(%ebx) | ||
184 | - setne %cl | ||
185 | - subl $1, %ecx | ||
186 | - andl $(LLL_SHARED-LLL_PRIVATE), %ecx | ||
187 | -#if LLL_PRIVATE != 0 | ||
188 | - addl $LLL_PRIVATE, %ecx | ||
189 | -#endif | ||
190 | - call __lll_lock_wait | ||
191 | - | ||
192 | -92: | ||
193 | - /* Increment the cond_futex value again, so it can be used as a new | ||
194 | - expected value. */ | ||
195 | - addl $1, cond_futex(%ebx) | ||
196 | - movl cond_futex(%ebx), %ebp | ||
197 | - | ||
198 | - /* Unlock. */ | ||
199 | - LOCK | ||
200 | -#if cond_lock == 0 | ||
201 | - subl $1, (%ebx) | ||
202 | -#else | ||
203 | - subl $1, cond_lock(%ebx) | ||
204 | -#endif | ||
205 | - je 93f | ||
206 | -#if cond_lock == 0 | ||
207 | - movl %ebx, %eax | ||
208 | -#else | ||
209 | - leal cond_lock(%ebx), %eax | ||
210 | -#endif | ||
211 | -#if (LLL_SHARED-LLL_PRIVATE) > 255 | ||
212 | - xorl %ecx, %ecx | ||
213 | -#endif | ||
214 | - cmpl $-1, dep_mutex(%ebx) | ||
215 | - setne %cl | ||
216 | - subl $1, %ecx | ||
217 | - andl $(LLL_SHARED-LLL_PRIVATE), %ecx | ||
218 | -#if LLL_PRIVATE != 0 | ||
219 | - addl $LLL_PRIVATE, %ecx | ||
220 | -#endif | ||
221 | - call __lll_unlock_wake | ||
222 | - | ||
223 | -93: | ||
224 | - /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */ | ||
225 | - xorl %ecx, %ecx | ||
226 | - movl dep_mutex(%ebx), %edi | ||
227 | - jmp 90b | ||
228 | -.LcleanupEND2: | ||
229 | - | ||
230 | .size __pthread_cond_wait, .-__pthread_cond_wait | ||
231 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | ||
232 | GLIBC_2_3_2) | ||
233 | @@ -651,10 +606,6 @@ __condvar_w_cleanup: | ||
234 | .long .LcleanupEND-.Lsub_cond_futex | ||
235 | .long __condvar_w_cleanup-.LSTARTCODE | ||
236 | .uleb128 0 | ||
237 | - .long .LcleanupSTART2-.LSTARTCODE | ||
238 | - .long .LcleanupEND2-.LcleanupSTART2 | ||
239 | - .long __condvar_w_cleanup-.LSTARTCODE | ||
240 | - .uleb128 0 | ||
241 | .long .LcallUR-.LSTARTCODE | ||
242 | .long .LENDCODE-.LcallUR | ||
243 | .long 0 | ||
244 | diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S | ||
245 | index a1c8ca8..b669abb 100644 | ||
246 | --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S | ||
247 | +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S | ||
248 | @@ -103,7 +103,7 @@ __pthread_cond_timedwait: | ||
249 | mov %RSI_LP, dep_mutex(%rdi) | ||
250 | |||
251 | 22: | ||
252 | - xorl %r15d, %r15d | ||
253 | + xorb %r15b, %r15b | ||
254 | |||
255 | #ifndef __ASSUME_FUTEX_CLOCK_REALTIME | ||
256 | # ifdef PIC | ||
257 | @@ -190,18 +190,39 @@ __pthread_cond_timedwait: | ||
258 | movl $SYS_futex, %eax | ||
259 | syscall | ||
260 | |||
261 | - movl $1, %r15d | ||
262 | + cmpl $0, %eax | ||
263 | + sete %r15b | ||
264 | + | ||
265 | #ifdef __ASSUME_REQUEUE_PI | ||
266 | jmp 62f | ||
267 | #else | ||
268 | - cmpq $-4095, %rax | ||
269 | - jnae 62f | ||
270 | + je 62f | ||
271 | + | ||
272 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | ||
273 | + successfully, it has already locked the mutex for us and the | ||
274 | + pi_flag (%r15b) is set to denote that fact. However, if another | ||
275 | + thread changed the futex value before we entered the wait, the | ||
276 | + syscall may return an EAGAIN and the mutex is not locked. We go | ||
277 | + ahead with a success anyway since later we look at the pi_flag to | ||
278 | + decide if we got the mutex or not. The sequence numbers then make | ||
279 | + sure that only one of the threads actually wake up. We retry using | ||
280 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | ||
281 | + and PI futexes don't mix. | ||
282 | + | ||
283 | + Note that we don't check for EAGAIN specifically; we assume that the | ||
284 | + only other error the futex function could return is EAGAIN (barring | ||
285 | + the ETIMEOUT of course, for the timeout case in futex) since | ||
286 | + anything else would mean an error in our function. It is too | ||
287 | + expensive to do that check for every call (which is quite common in | ||
288 | + case of a large number of threads), so it has been skipped. */ | ||
289 | + cmpl $-ENOSYS, %eax | ||
290 | + jne 62f | ||
291 | |||
292 | subq $cond_futex, %rdi | ||
293 | #endif | ||
294 | |||
295 | 61: movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi | ||
296 | -60: xorl %r15d, %r15d | ||
297 | +60: xorb %r15b, %r15b | ||
298 | xorl %eax, %eax | ||
299 | /* The following only works like this because we only support | ||
300 | two clocks, represented using a single bit. */ | ||
301 | @@ -248,7 +269,23 @@ __pthread_cond_timedwait: | ||
302 | ja 39f | ||
303 | |||
304 | 45: cmpq $-ETIMEDOUT, %r14 | ||
305 | - jne 38b | ||
306 | + je 99f | ||
307 | + | ||
308 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | ||
309 | + release the mutex we had acquired and go back. */ | ||
310 | + test %r15b, %r15b | ||
311 | + jz 38b | ||
312 | + | ||
313 | + /* Adjust the mutex values first and then unlock it. The unlock | ||
314 | + should always succeed or else the kernel did not lock the | ||
315 | + mutex correctly. */ | ||
316 | + movq %r8, %rdi | ||
317 | + callq __pthread_mutex_cond_lock_adjust | ||
318 | + xorl %esi, %esi | ||
319 | + callq __pthread_mutex_unlock_usercnt | ||
320 | + /* Reload cond_var. */ | ||
321 | + movq 8(%rsp), %rdi | ||
322 | + jmp 38b | ||
323 | |||
324 | 99: incq wakeup_seq(%rdi) | ||
325 | incl cond_futex(%rdi) | ||
326 | @@ -298,7 +335,7 @@ __pthread_cond_timedwait: | ||
327 | /* If requeue_pi is used the kernel performs the locking of the | ||
328 | mutex. */ | ||
329 | 41: movq 16(%rsp), %rdi | ||
330 | - testl %r15d, %r15d | ||
331 | + testb %r15b, %r15b | ||
332 | jnz 64f | ||
333 | |||
334 | callq __pthread_mutex_cond_lock | ||
335 | diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S | ||
336 | index 6194852..ec403cd 100644 | ||
337 | --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S | ||
338 | +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S | ||
339 | @@ -136,19 +136,36 @@ __pthread_cond_wait: | ||
340 | cmpl $PI_BIT, %eax | ||
341 | jne 61f | ||
342 | |||
343 | -90: | ||
344 | movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi | ||
345 | movl $SYS_futex, %eax | ||
346 | syscall | ||
347 | |||
348 | - movl $1, %r8d | ||
349 | - cmpq $-EAGAIN, %rax | ||
350 | - je 91f | ||
351 | + cmpl $0, %eax | ||
352 | + sete %r8b | ||
353 | + | ||
354 | #ifdef __ASSUME_REQUEUE_PI | ||
355 | jmp 62f | ||
356 | #else | ||
357 | - cmpq $-4095, %rax | ||
358 | - jnae 62f | ||
359 | + je 62f | ||
360 | + | ||
361 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | ||
362 | + successfully, it has already locked the mutex for us and the | ||
363 | + pi_flag (%r8b) is set to denote that fact. However, if another | ||
364 | + thread changed the futex value before we entered the wait, the | ||
365 | + syscall may return an EAGAIN and the mutex is not locked. We go | ||
366 | + ahead with a success anyway since later we look at the pi_flag to | ||
367 | + decide if we got the mutex or not. The sequence numbers then make | ||
368 | + sure that only one of the threads actually wake up. We retry using | ||
369 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | ||
370 | + and PI futexes don't mix. | ||
371 | + | ||
372 | + Note that we don't check for EAGAIN specifically; we assume that the | ||
373 | + only other error the futex function could return is EAGAIN since | ||
374 | + anything else would mean an error in our function. It is too | ||
375 | + expensive to do that check for every call (which is quite common in | ||
376 | + case of a large number of threads), so it has been skipped. */ | ||
377 | + cmpl $-ENOSYS, %eax | ||
378 | + jne 62f | ||
379 | |||
380 | # ifndef __ASSUME_PRIVATE_FUTEX | ||
381 | movl $FUTEX_WAIT, %esi | ||
382 | @@ -161,7 +178,7 @@ __pthread_cond_wait: | ||
383 | #else | ||
384 | orl %fs:PRIVATE_FUTEX, %esi | ||
385 | #endif | ||
386 | -60: xorl %r8d, %r8d | ||
387 | +60: xorb %r8b, %r8b | ||
388 | movl $SYS_futex, %eax | ||
389 | syscall | ||
390 | |||
391 | @@ -191,10 +208,10 @@ __pthread_cond_wait: | ||
392 | jne 16f | ||
393 | |||
394 | cmpq 24(%rsp), %r9 | ||
395 | - jbe 8b | ||
396 | + jbe 19f | ||
397 | |||
398 | cmpq %rax, %r9 | ||
399 | - jna 8b | ||
400 | + jna 19f | ||
401 | |||
402 | incq woken_seq(%rdi) | ||
403 | |||
404 | @@ -236,7 +253,7 @@ __pthread_cond_wait: | ||
405 | /* If requeue_pi is used the kernel performs the locking of the | ||
406 | mutex. */ | ||
407 | 11: movq 16(%rsp), %rdi | ||
408 | - testl %r8d, %r8d | ||
409 | + testb %r8b, %r8b | ||
410 | jnz 18f | ||
411 | |||
412 | callq __pthread_mutex_cond_lock | ||
413 | @@ -253,6 +270,23 @@ __pthread_cond_wait: | ||
414 | xorl %eax, %eax | ||
415 | jmp 14b | ||
416 | |||
417 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | ||
418 | + release the mutex we had acquired and go back. */ | ||
419 | +19: testb %r8b, %r8b | ||
420 | + jz 8b | ||
421 | + | ||
422 | + /* Adjust the mutex values first and then unlock it. The unlock | ||
423 | + should always succeed or else the kernel did not lock the mutex | ||
424 | + correctly. */ | ||
425 | + movq 16(%rsp), %rdi | ||
426 | + callq __pthread_mutex_cond_lock_adjust | ||
427 | + movq %rdi, %r8 | ||
428 | + xorl %esi, %esi | ||
429 | + callq __pthread_mutex_unlock_usercnt | ||
430 | + /* Reload cond_var. */ | ||
431 | + movq 8(%rsp), %rdi | ||
432 | + jmp 8b | ||
433 | + | ||
434 | /* Initial locking failed. */ | ||
435 | 1: | ||
436 | #if cond_lock != 0 | ||
437 | @@ -331,69 +365,6 @@ __pthread_cond_wait: | ||
438 | 13: movq %r10, %rax | ||
439 | jmp 14b | ||
440 | |||
441 | -91: | ||
442 | -.LcleanupSTART2: | ||
443 | - /* FUTEX_WAIT_REQUEUE_PI returned EAGAIN. We need to | ||
444 | - call it again. */ | ||
445 | - movq 8(%rsp), %rdi | ||
446 | - | ||
447 | - /* Get internal lock. */ | ||
448 | - movl $1, %esi | ||
449 | - xorl %eax, %eax | ||
450 | - LOCK | ||
451 | -#if cond_lock == 0 | ||
452 | - cmpxchgl %esi, (%rdi) | ||
453 | -#else | ||
454 | - cmpxchgl %esi, cond_lock(%rdi) | ||
455 | -#endif | ||
456 | - jz 92f | ||
457 | - | ||
458 | -#if cond_lock != 0 | ||
459 | - addq $cond_lock, %rdi | ||
460 | -#endif | ||
461 | - LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) | ||
462 | - movl $LLL_PRIVATE, %eax | ||
463 | - movl $LLL_SHARED, %esi | ||
464 | - cmovne %eax, %esi | ||
465 | - callq __lll_lock_wait | ||
466 | -#if cond_lock != 0 | ||
467 | - subq $cond_lock, %rdi | ||
468 | -#endif | ||
469 | -92: | ||
470 | - /* Increment the cond_futex value again, so it can be used as a new | ||
471 | - expected value. */ | ||
472 | - incl cond_futex(%rdi) | ||
473 | - movl cond_futex(%rdi), %edx | ||
474 | - | ||
475 | - /* Release internal lock. */ | ||
476 | - LOCK | ||
477 | -#if cond_lock == 0 | ||
478 | - decl (%rdi) | ||
479 | -#else | ||
480 | - decl cond_lock(%rdi) | ||
481 | -#endif | ||
482 | - jz 93f | ||
483 | - | ||
484 | -#if cond_lock != 0 | ||
485 | - addq $cond_lock, %rdi | ||
486 | -#endif | ||
487 | - LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) | ||
488 | - movl $LLL_PRIVATE, %eax | ||
489 | - movl $LLL_SHARED, %esi | ||
490 | - cmovne %eax, %esi | ||
491 | - /* The call preserves %rdx. */ | ||
492 | - callq __lll_unlock_wake | ||
493 | -#if cond_lock != 0 | ||
494 | - subq $cond_lock, %rdi | ||
495 | -#endif | ||
496 | -93: | ||
497 | - /* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */ | ||
498 | - xorq %r10, %r10 | ||
499 | - mov dep_mutex(%rdi), %R8_LP | ||
500 | - leaq cond_futex(%rdi), %rdi | ||
501 | - jmp 90b | ||
502 | -.LcleanupEND2: | ||
503 | - | ||
504 | .size __pthread_cond_wait, .-__pthread_cond_wait | ||
505 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | ||
506 | GLIBC_2_3_2) | ||
507 | @@ -547,10 +518,6 @@ __condvar_cleanup1: | ||
508 | .uleb128 .LcleanupEND-.LcleanupSTART | ||
509 | .uleb128 __condvar_cleanup1-.LSTARTCODE | ||
510 | .uleb128 0 | ||
511 | - .uleb128 .LcleanupSTART2-.LSTARTCODE | ||
512 | - .uleb128 .LcleanupEND2-.LcleanupSTART2 | ||
513 | - .uleb128 __condvar_cleanup1-.LSTARTCODE | ||
514 | - .uleb128 0 | ||
515 | .uleb128 .LcallUR-.LSTARTCODE | ||
516 | .uleb128 .LENDCODE-.LcallUR | ||
517 | .uleb128 0 | ||
518 | diff --git a/nptl/tst-cond24.c b/nptl/tst-cond24.c | ||
519 | new file mode 100644 | ||
520 | index 0000000..2eb2df1 | ||
521 | --- /dev/null | ||
522 | +++ b/nptl/tst-cond24.c | ||
523 | @@ -0,0 +1,249 @@ | ||
524 | +/* Verify that condition variables synchronized by PI mutexes don't hang. | ||
525 | + Copyright (C) 2012 Free Software Foundation, Inc. | ||
526 | + This file is part of the GNU C Library. | ||
527 | + | ||
528 | + The GNU C Library is free software; you can redistribute it and/or | ||
529 | + modify it under the terms of the GNU Lesser General Public | ||
530 | + License as published by the Free Software Foundation; either | ||
531 | + version 2.1 of the License, or (at your option) any later version. | ||
532 | + | ||
533 | + The GNU C Library is distributed in the hope that it will be useful, | ||
534 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
535 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
536 | + Lesser General Public License for more details. | ||
537 | + | ||
538 | + You should have received a copy of the GNU Lesser General Public | ||
539 | + License along with the GNU C Library; if not, see | ||
540 | + <http://www.gnu.org/licenses/>. */ | ||
541 | + | ||
542 | +#include <pthread.h> | ||
543 | +#include <stdio.h> | ||
544 | +#include <stdlib.h> | ||
545 | +#include <string.h> | ||
546 | +#include <errno.h> | ||
547 | +#include <sys/types.h> | ||
548 | +#include <sys/syscall.h> | ||
549 | +#include <unistd.h> | ||
550 | +#include <sys/time.h> | ||
551 | +#include <time.h> | ||
552 | + | ||
553 | +#define THREADS_NUM 5 | ||
554 | +#define MAXITER 50000 | ||
555 | + | ||
556 | +static pthread_mutex_t mutex; | ||
557 | +static pthread_mutexattr_t mutex_attr; | ||
558 | +static pthread_cond_t cond; | ||
559 | +static pthread_t threads[THREADS_NUM]; | ||
560 | +static int pending = 0; | ||
561 | + | ||
562 | +typedef void * (*threadfunc) (void *); | ||
563 | + | ||
564 | +void * | ||
565 | +thread_fun_timed (void *arg) | ||
566 | +{ | ||
567 | + int *ret = arg; | ||
568 | + int rv, i; | ||
569 | + | ||
570 | + printf ("Started thread_fun_timed[%d]\n", *ret); | ||
571 | + | ||
572 | + for (i = 0; i < MAXITER / THREADS_NUM; i++) | ||
573 | + { | ||
574 | + rv = pthread_mutex_lock (&mutex); | ||
575 | + if (rv) | ||
576 | + { | ||
577 | + printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); | ||
578 | + *ret = 1; | ||
579 | + goto out; | ||
580 | + } | ||
581 | + | ||
582 | + while (!pending) | ||
583 | + { | ||
584 | + struct timespec ts; | ||
585 | + clock_gettime(CLOCK_REALTIME, &ts); | ||
586 | + ts.tv_sec += 20; | ||
587 | + rv = pthread_cond_timedwait (&cond, &mutex, &ts); | ||
588 | + | ||
589 | + /* There should be no timeout either. */ | ||
590 | + if (rv) | ||
591 | + { | ||
592 | + printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv); | ||
593 | + *ret = 1; | ||
594 | + goto out; | ||
595 | + } | ||
596 | + } | ||
597 | + | ||
598 | + pending--; | ||
599 | + | ||
600 | + rv = pthread_mutex_unlock (&mutex); | ||
601 | + if (rv) | ||
602 | + { | ||
603 | + printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); | ||
604 | + *ret = 1; | ||
605 | + goto out; | ||
606 | + } | ||
607 | + } | ||
608 | + | ||
609 | + *ret = 0; | ||
610 | + | ||
611 | +out: | ||
612 | + return ret; | ||
613 | +} | ||
614 | + | ||
615 | +void * | ||
616 | +thread_fun (void *arg) | ||
617 | +{ | ||
618 | + int *ret = arg; | ||
619 | + int rv, i; | ||
620 | + | ||
621 | + printf ("Started thread_fun[%d]\n", *ret); | ||
622 | + | ||
623 | + for (i = 0; i < MAXITER / THREADS_NUM; i++) | ||
624 | + { | ||
625 | + rv = pthread_mutex_lock (&mutex); | ||
626 | + if (rv) | ||
627 | + { | ||
628 | + printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); | ||
629 | + *ret = 1; | ||
630 | + goto out; | ||
631 | + } | ||
632 | + | ||
633 | + while (!pending) | ||
634 | + { | ||
635 | + rv = pthread_cond_wait (&cond, &mutex); | ||
636 | + | ||
637 | + if (rv) | ||
638 | + { | ||
639 | + printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv); | ||
640 | + *ret = 1; | ||
641 | + goto out; | ||
642 | + } | ||
643 | + } | ||
644 | + | ||
645 | + pending--; | ||
646 | + | ||
647 | + rv = pthread_mutex_unlock (&mutex); | ||
648 | + if (rv) | ||
649 | + { | ||
650 | + printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); | ||
651 | + *ret = 1; | ||
652 | + goto out; | ||
653 | + } | ||
654 | + } | ||
655 | + | ||
656 | + *ret = 0; | ||
657 | + | ||
658 | +out: | ||
659 | + return ret; | ||
660 | +} | ||
661 | + | ||
662 | +static int | ||
663 | +do_test_wait (threadfunc f) | ||
664 | +{ | ||
665 | + int i; | ||
666 | + int rv; | ||
667 | + int counter = 0; | ||
668 | + int retval[THREADS_NUM]; | ||
669 | + | ||
670 | + puts ("Starting test"); | ||
671 | + | ||
672 | + rv = pthread_mutexattr_init (&mutex_attr); | ||
673 | + if (rv) | ||
674 | + { | ||
675 | + printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv); | ||
676 | + return 1; | ||
677 | + } | ||
678 | + | ||
679 | + rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT); | ||
680 | + if (rv) | ||
681 | + { | ||
682 | + printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv); | ||
683 | + return 1; | ||
684 | + } | ||
685 | + | ||
686 | + rv = pthread_mutex_init (&mutex, &mutex_attr); | ||
687 | + if (rv) | ||
688 | + { | ||
689 | + printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv); | ||
690 | + return 1; | ||
691 | + } | ||
692 | + | ||
693 | + rv = pthread_cond_init (&cond, NULL); | ||
694 | + if (rv) | ||
695 | + { | ||
696 | + printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv); | ||
697 | + return 1; | ||
698 | + } | ||
699 | + | ||
700 | + for (i = 0; i < THREADS_NUM; i++) | ||
701 | + { | ||
702 | + retval[i] = i; | ||
703 | + rv = pthread_create (&threads[i], NULL, f, &retval[i]); | ||
704 | + if (rv) | ||
705 | + { | ||
706 | + printf ("pthread_create: %s(%d)\n", strerror (rv), rv); | ||
707 | + return 1; | ||
708 | + } | ||
709 | + } | ||
710 | + | ||
711 | + for (; counter < MAXITER; counter++) | ||
712 | + { | ||
713 | + rv = pthread_mutex_lock (&mutex); | ||
714 | + if (rv) | ||
715 | + { | ||
716 | + printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); | ||
717 | + return 1; | ||
718 | + } | ||
719 | + | ||
720 | + if (!(counter % 100)) | ||
721 | + printf ("counter: %d\n", counter); | ||
722 | + pending += 1; | ||
723 | + | ||
724 | + rv = pthread_cond_signal (&cond); | ||
725 | + if (rv) | ||
726 | + { | ||
727 | + printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv); | ||
728 | + return 1; | ||
729 | + } | ||
730 | + | ||
731 | + rv = pthread_mutex_unlock (&mutex); | ||
732 | + if (rv) | ||
733 | + { | ||
734 | + printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); | ||
735 | + return 1; | ||
736 | + } | ||
737 | + } | ||
738 | + | ||
739 | + for (i = 0; i < THREADS_NUM; i++) | ||
740 | + { | ||
741 | + void *ret; | ||
742 | + rv = pthread_join (threads[i], &ret); | ||
743 | + if (rv) | ||
744 | + { | ||
745 | + printf ("pthread_join: %s(%d)\n", strerror (rv), rv); | ||
746 | + return 1; | ||
747 | + } | ||
748 | + if (ret && *(int *)ret) | ||
749 | + { | ||
750 | + printf ("Thread %d returned with an error\n", i); | ||
751 | + return 1; | ||
752 | + } | ||
753 | + } | ||
754 | + | ||
755 | + return 0; | ||
756 | +} | ||
757 | + | ||
758 | +static int | ||
759 | +do_test (void) | ||
760 | +{ | ||
761 | + puts ("Testing pthread_cond_wait"); | ||
762 | + int ret = do_test_wait (thread_fun); | ||
763 | + if (ret) | ||
764 | + return ret; | ||
765 | + | ||
766 | + puts ("Testing pthread_cond_timedwait"); | ||
767 | + return do_test_wait (thread_fun_timed); | ||
768 | +} | ||
769 | + | ||
770 | +#define TIMEOUT 10 | ||
771 | +#define TEST_FUNCTION do_test () | ||
772 | +#include "../test-skeleton.c" | ||
773 | -- | ||
774 | 1.7.3.4 |