Magellan Linux

Contents of /trunk/glibc/patches/glibc-2.16.0-unlock-mutex.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1925 - (show annotations) (download)
Sun Oct 28 19:05:24 2012 UTC (11 years, 6 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