Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1925 - (hide 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 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