Contents of /trunk/glibc/patches/glibc-2.16.0-unlock-mutex.patch
Parent Directory | Revision Log
Revision 1925 -
(show 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 | --- 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 |