]>
Commit | Line | Data |
---|---|---|
bb330e25 AF |
1 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.fixed/nptl/Makefile |
2 | --- glibc-2.12-2-gc4ccff1/nptl/Makefile 2013-07-09 10:18:22.267421846 +0530 | |
3 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/Makefile 2013-07-09 10:16:22.043427519 +0530 | |
4 | @@ -207,7 +207,8 @@ tests = tst-typesizes \ | |
5 | tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ | |
6 | tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ | |
7 | tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ | |
8 | - tst-cond20 tst-cond21 tst-cond22 tst-cond23 \ | |
9 | + tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 tst-cond25 \ | |
10 | + tst-cond-except \ | |
11 | tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ | |
12 | tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ | |
13 | tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ | |
14 | @@ -275,6 +276,8 @@ gen-as-const-headers = pthread-errnos.sy | |
15 | ||
16 | LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst | |
17 | ||
18 | +LDFLAGS-tst-cond24 = -lrt | |
19 | +LDFLAGS-tst-cond25 = -lrt | |
20 | ||
21 | include ../Makeconfig | |
22 | ||
23 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S | |
24 | --- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2010-05-04 16:57:23.000000000 +0530 | |
25 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2013-07-09 10:16:22.044427519 +0530 | |
26 | @@ -203,9 +203,11 @@ __pthread_cond_timedwait: | |
27 | 42: leal (%ebp), %esi | |
28 | movl 28(%esp), %edx | |
29 | addl $cond_futex, %ebx | |
30 | +.Ladd_cond_futex_pi: | |
31 | movl $SYS_futex, %eax | |
32 | ENTER_KERNEL | |
33 | subl $cond_futex, %ebx | |
34 | +.Lsub_cond_futex_pi: | |
35 | movl %eax, %esi | |
36 | /* Set the pi-requeued flag only if the kernel has returned 0. The | |
37 | kernel does not hold the mutex on ETIMEDOUT or any other error. */ | |
38 | @@ -213,8 +215,23 @@ __pthread_cond_timedwait: | |
39 | sete 24(%esp) | |
40 | je 41f | |
41 | ||
42 | - /* Normal and PI futexes dont mix. Use normal futex functions only | |
43 | - if the kernel does not support the PI futex functions. */ | |
44 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | |
45 | + successfully, it has already locked the mutex for us and the | |
46 | + pi_flag (24(%esp)) is set to denote that fact. However, if another | |
47 | + thread changed the futex value before we entered the wait, the | |
48 | + syscall may return an EAGAIN and the mutex is not locked. We go | |
49 | + ahead with a success anyway since later we look at the pi_flag to | |
50 | + decide if we got the mutex or not. The sequence numbers then make | |
51 | + sure that only one of the threads actually wake up. We retry using | |
52 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | |
53 | + and PI futexes don't mix. | |
54 | + | |
55 | + Note that we don't check for EAGAIN specifically; we assume that the | |
56 | + only other error the futex function could return is EAGAIN (barring | |
57 | + the ETIMEOUT of course, for the timeout case in futex) since | |
58 | + anything else would mean an error in our function. It is too | |
59 | + expensive to do that check for every call (which is quite common in | |
60 | + case of a large number of threads), so it has been skipped. */ | |
61 | cmpl $-ENOSYS, %eax | |
62 | jne 41f | |
63 | xorl %ecx, %ecx | |
64 | @@ -274,9 +291,24 @@ __pthread_cond_timedwait: | |
65 | jne 9f | |
66 | ||
67 | 15: cmpl $-ETIMEDOUT, %esi | |
68 | - jne 8b | |
69 | + je 28f | |
70 | ||
71 | - addl $1, wakeup_seq(%ebx) | |
72 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | |
73 | + release the mutex we had acquired and go back. */ | |
74 | + movl 24(%esp), %edx | |
75 | + test %edx, %edx | |
76 | + jz 8b | |
77 | + | |
78 | + /* Adjust the mutex values first and then unlock it. The unlock | |
79 | + should always succeed or else the kernel did not lock the mutex | |
80 | + correctly. */ | |
81 | + movl dep_mutex(%ebx), %eax | |
82 | + call __pthread_mutex_cond_lock_adjust | |
83 | + xorl %edx, %edx | |
84 | + call __pthread_mutex_unlock_usercnt | |
85 | + jmp 8b | |
86 | + | |
87 | +28: addl $1, wakeup_seq(%ebx) | |
88 | adcl $0, wakeup_seq+4(%ebx) | |
89 | addl $1, cond_futex(%ebx) | |
90 | movl $ETIMEDOUT, %esi | |
91 | @@ -644,10 +676,27 @@ __condvar_tw_cleanup: | |
92 | movl $0x7fffffff, %edx | |
93 | ENTER_KERNEL | |
94 | ||
95 | + /* Lock the mutex only if we don't own it already. This only happens | |
96 | + in case of PI mutexes, if we got cancelled after a successful | |
97 | + return of the futex syscall and before disabling async | |
98 | + cancellation. */ | |
99 | 5: movl 24+FRAME_SIZE(%esp), %eax | |
100 | - call __pthread_mutex_cond_lock | |
101 | + movl MUTEX_KIND(%eax), %ebx | |
102 | + andl $(ROBUST_BIT|PI_BIT), %ebx | |
103 | + cmpl $PI_BIT, %ebx | |
104 | + jne 8f | |
105 | + | |
106 | + movl (%eax), %ebx | |
107 | + andl $TID_MASK, %ebx | |
108 | + cmpl %ebx, %gs:TID | |
109 | + jne 8f | |
110 | + /* We managed to get the lock. Fix it up before returning. */ | |
111 | + call __pthread_mutex_cond_lock_adjust | |
112 | + jmp 9f | |
113 | + | |
114 | +8: call __pthread_mutex_cond_lock | |
115 | ||
116 | - movl %esi, (%esp) | |
117 | +9: movl %esi, (%esp) | |
118 | .LcallUR: | |
119 | call _Unwind_Resume | |
120 | hlt | |
121 | @@ -665,7 +714,15 @@ __condvar_tw_cleanup: | |
122 | .uleb128 .Lcstend-.Lcstbegin | |
123 | .Lcstbegin: | |
124 | .long .LcleanupSTART-.LSTARTCODE | |
125 | - .long .Ladd_cond_futex-.LcleanupSTART | |
126 | + .long .Ladd_cond_futex_pi-.LcleanupSTART | |
127 | + .long __condvar_tw_cleanup-.LSTARTCODE | |
128 | + .uleb128 0 | |
129 | + .long .Ladd_cond_futex_pi-.LSTARTCODE | |
130 | + .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi | |
131 | + .long __condvar_tw_cleanup2-.LSTARTCODE | |
132 | + .uleb128 0 | |
133 | + .long .Lsub_cond_futex_pi-.LSTARTCODE | |
134 | + .long .Ladd_cond_futex-.Lsub_cond_futex_pi | |
135 | .long __condvar_tw_cleanup-.LSTARTCODE | |
136 | .uleb128 0 | |
137 | .long .Ladd_cond_futex-.LSTARTCODE | |
138 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S | |
139 | --- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2010-05-04 16:57:23.000000000 +0530 | |
140 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2013-07-09 10:16:22.046427519 +0530 | |
141 | @@ -138,17 +138,33 @@ __pthread_cond_wait: | |
142 | movl %ebp, %edx | |
143 | xorl %esi, %esi | |
144 | addl $cond_futex, %ebx | |
145 | +.Ladd_cond_futex_pi: | |
146 | movl $SYS_futex, %eax | |
147 | ENTER_KERNEL | |
148 | subl $cond_futex, %ebx | |
149 | +.Lsub_cond_futex_pi: | |
150 | /* Set the pi-requeued flag only if the kernel has returned 0. The | |
151 | kernel does not hold the mutex on error. */ | |
152 | cmpl $0, %eax | |
153 | sete 16(%esp) | |
154 | je 19f | |
155 | ||
156 | - /* Normal and PI futexes dont mix. Use normal futex functions only | |
157 | - if the kernel does not support the PI futex functions. */ | |
158 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | |
159 | + successfully, it has already locked the mutex for us and the | |
160 | + pi_flag (16(%esp)) is set to denote that fact. However, if another | |
161 | + thread changed the futex value before we entered the wait, the | |
162 | + syscall may return an EAGAIN and the mutex is not locked. We go | |
163 | + ahead with a success anyway since later we look at the pi_flag to | |
164 | + decide if we got the mutex or not. The sequence numbers then make | |
165 | + sure that only one of the threads actually wake up. We retry using | |
166 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | |
167 | + and PI futexes don't mix. | |
168 | + | |
169 | + Note that we don't check for EAGAIN specifically; we assume that the | |
170 | + only other error the futex function could return is EAGAIN since | |
171 | + anything else would mean an error in our function. It is too | |
172 | + expensive to do that check for every call (which is quite common in | |
173 | + case of a large number of threads), so it has been skipped. */ | |
174 | cmpl $-ENOSYS, %eax | |
175 | jne 19f | |
176 | xorl %ecx, %ecx | |
177 | @@ -198,12 +214,12 @@ __pthread_cond_wait: | |
178 | cmpl 8(%esp), %edx | |
179 | jne 7f | |
180 | cmpl 4(%esp), %edi | |
181 | - je 8b | |
182 | + je 22f | |
183 | ||
184 | 7: cmpl %ecx, %edx | |
185 | jne 9f | |
186 | cmp %eax, %edi | |
187 | - je 8b | |
188 | + je 22f | |
189 | ||
190 | 9: addl $1, woken_seq(%ebx) | |
191 | adcl $0, woken_seq+4(%ebx) | |
192 | @@ -279,6 +295,22 @@ __pthread_cond_wait: | |
193 | jmp 20b | |
194 | ||
195 | cfi_adjust_cfa_offset(-FRAME_SIZE); | |
196 | + | |
197 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | |
198 | + release the mutex we had acquired and go back. */ | |
199 | +22: movl 16(%esp), %edx | |
200 | + test %edx, %edx | |
201 | + jz 8b | |
202 | + | |
203 | + /* Adjust the mutex values first and then unlock it. The unlock | |
204 | + should always succeed or else the kernel did not lock the mutex | |
205 | + correctly. */ | |
206 | + movl dep_mutex(%ebx), %eax | |
207 | + call __pthread_mutex_cond_lock_adjust | |
208 | + xorl %edx, %edx | |
209 | + call __pthread_mutex_unlock_usercnt | |
210 | + jmp 8b | |
211 | + | |
212 | /* Initial locking failed. */ | |
213 | 1: | |
214 | #if cond_lock == 0 | |
215 | @@ -391,6 +423,7 @@ __pthread_cond_wait: | |
216 | #endif | |
217 | call __lll_unlock_wake | |
218 | jmp 11b | |
219 | + | |
220 | .size __pthread_cond_wait, .-__pthread_cond_wait | |
221 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | |
222 | GLIBC_2_3_2) | |
223 | @@ -531,10 +564,27 @@ __condvar_w_cleanup: | |
224 | movl $0x7fffffff, %edx | |
225 | ENTER_KERNEL | |
226 | ||
227 | + /* Lock the mutex only if we don't own it already. This only happens | |
228 | + in case of PI mutexes, if we got cancelled after a successful | |
229 | + return of the futex syscall and before disabling async | |
230 | + cancellation. */ | |
231 | 5: movl 24+FRAME_SIZE(%esp), %eax | |
232 | - call __pthread_mutex_cond_lock | |
233 | + movl MUTEX_KIND(%eax), %ebx | |
234 | + andl $(ROBUST_BIT|PI_BIT), %ebx | |
235 | + cmpl $PI_BIT, %ebx | |
236 | + jne 8f | |
237 | + | |
238 | + movl (%eax), %ebx | |
239 | + andl $TID_MASK, %ebx | |
240 | + cmpl %ebx, %gs:TID | |
241 | + jne 8f | |
242 | + /* We managed to get the lock. Fix it up before returning. */ | |
243 | + call __pthread_mutex_cond_lock_adjust | |
244 | + jmp 9f | |
245 | ||
246 | - movl %esi, (%esp) | |
247 | +8: call __pthread_mutex_cond_lock | |
248 | + | |
249 | +9: movl %esi, (%esp) | |
250 | .LcallUR: | |
251 | call _Unwind_Resume | |
252 | hlt | |
253 | @@ -552,7 +602,15 @@ __condvar_w_cleanup: | |
254 | .uleb128 .Lcstend-.Lcstbegin | |
255 | .Lcstbegin: | |
256 | .long .LcleanupSTART-.LSTARTCODE | |
257 | - .long .Ladd_cond_futex-.LcleanupSTART | |
258 | + .long .Ladd_cond_futex_pi-.LcleanupSTART | |
259 | + .long __condvar_w_cleanup-.LSTARTCODE | |
260 | + .uleb128 0 | |
261 | + .long .Ladd_cond_futex_pi-.LSTARTCODE | |
262 | + .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi | |
263 | + .long __condvar_w_cleanup2-.LSTARTCODE | |
264 | + .uleb128 0 | |
265 | + .long .Lsub_cond_futex_pi-.LSTARTCODE | |
266 | + .long .Ladd_cond_futex-.Lsub_cond_futex_pi | |
267 | .long __condvar_w_cleanup-.LSTARTCODE | |
268 | .uleb128 0 | |
269 | .long .Ladd_cond_futex-.LSTARTCODE | |
270 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym | |
271 | --- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym 2010-05-04 16:57:23.000000000 +0530 | |
272 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym 2013-07-09 10:16:22.047427519 +0530 | |
273 | @@ -6,3 +6,4 @@ MUTEX_KIND offsetof (pthread_mutex_t, __ | |
274 | ROBUST_BIT PTHREAD_MUTEX_ROBUST_NORMAL_NP | |
275 | PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP | |
276 | PS_BIT PTHREAD_MUTEX_PSHARED_BIT | |
277 | +TID_MASK FUTEX_TID_MASK | |
278 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S | |
279 | --- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2013-07-09 10:18:22.506421835 +0530 | |
280 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2013-07-09 10:16:22.048427519 +0530 | |
281 | @@ -104,6 +104,8 @@ __pthread_cond_timedwait: | |
282 | movq %rsi, dep_mutex(%rdi) | |
283 | ||
284 | 22: | |
285 | + xorb %r15b, %r15b | |
286 | + | |
287 | #ifndef __ASSUME_FUTEX_CLOCK_REALTIME | |
288 | # ifdef PIC | |
289 | cmpl $0, __have_futex_clock_realtime(%rip) | |
290 | @@ -189,18 +191,39 @@ __pthread_cond_timedwait: | |
291 | movl $SYS_futex, %eax | |
292 | syscall | |
293 | ||
294 | - movl $1, %r15d | |
295 | + cmpl $0, %eax | |
296 | + sete %r15b | |
297 | + | |
298 | #ifdef __ASSUME_REQUEUE_PI | |
299 | jmp 62f | |
300 | #else | |
301 | - cmpq $-4095, %rax | |
302 | - jnae 62f | |
303 | + je 62f | |
304 | + | |
305 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | |
306 | + successfully, it has already locked the mutex for us and the | |
307 | + pi_flag (%r15b) is set to denote that fact. However, if another | |
308 | + thread changed the futex value before we entered the wait, the | |
309 | + syscall may return an EAGAIN and the mutex is not locked. We go | |
310 | + ahead with a success anyway since later we look at the pi_flag to | |
311 | + decide if we got the mutex or not. The sequence numbers then make | |
312 | + sure that only one of the threads actually wake up. We retry using | |
313 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | |
314 | + and PI futexes don't mix. | |
315 | + | |
316 | + Note that we don't check for EAGAIN specifically; we assume that the | |
317 | + only other error the futex function could return is EAGAIN (barring | |
318 | + the ETIMEOUT of course, for the timeout case in futex) since | |
319 | + anything else would mean an error in our function. It is too | |
320 | + expensive to do that check for every call (which is quite common in | |
321 | + case of a large number of threads), so it has been skipped. */ | |
322 | + cmpl $-ENOSYS, %eax | |
323 | + jne 62f | |
324 | ||
325 | subq $cond_futex, %rdi | |
326 | #endif | |
327 | ||
328 | 61: movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi | |
329 | -60: xorl %r15d, %r15d | |
330 | +60: xorb %r15b, %r15b | |
331 | xorl %eax, %eax | |
332 | /* The following only works like this because we only support | |
333 | two clocks, represented using a single bit. */ | |
334 | @@ -247,7 +270,23 @@ __pthread_cond_timedwait: | |
335 | ja 39f | |
336 | ||
337 | 45: cmpq $-ETIMEDOUT, %r14 | |
338 | - jne 38b | |
339 | + je 99f | |
340 | + | |
341 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | |
342 | + release the mutex we had acquired and go back. */ | |
343 | + test %r15b, %r15b | |
344 | + jz 38b | |
345 | + | |
346 | + /* Adjust the mutex values first and then unlock it. The unlock | |
347 | + should always succeed or else the kernel did not lock the | |
348 | + mutex correctly. */ | |
349 | + movq %r8, %rdi | |
350 | + callq __pthread_mutex_cond_lock_adjust | |
351 | + xorl %esi, %esi | |
352 | + callq __pthread_mutex_unlock_usercnt | |
353 | + /* Reload cond_var. */ | |
354 | + movq 8(%rsp), %rdi | |
355 | + jmp 38b | |
356 | ||
357 | 99: incq wakeup_seq(%rdi) | |
358 | incl cond_futex(%rdi) | |
359 | @@ -297,7 +336,7 @@ __pthread_cond_timedwait: | |
360 | /* If requeue_pi is used the kernel performs the locking of the | |
361 | mutex. */ | |
362 | 41: movq 16(%rsp), %rdi | |
363 | - testl %r15d, %r15d | |
364 | + testb %r15b, %r15b | |
365 | jnz 64f | |
366 | ||
367 | callq __pthread_mutex_cond_lock | |
368 | @@ -405,8 +444,6 @@ __pthread_cond_timedwait: | |
369 | ||
370 | #ifndef __ASSUME_FUTEX_CLOCK_REALTIME | |
371 | .Lreltmo: | |
372 | - xorl %r15d, %r15d | |
373 | - | |
374 | /* Get internal lock. */ | |
375 | movl $1, %esi | |
376 | xorl %eax, %eax | |
377 | @@ -765,10 +802,27 @@ __condvar_cleanup2: | |
378 | movl $SYS_futex, %eax | |
379 | syscall | |
380 | ||
381 | + /* Lock the mutex only if we don't own it already. This only happens | |
382 | + in case of PI mutexes, if we got cancelled after a successful | |
383 | + return of the futex syscall and before disabling async | |
384 | + cancellation. */ | |
385 | 5: movq 16(%rsp), %rdi | |
386 | - callq __pthread_mutex_cond_lock | |
387 | + movl MUTEX_KIND(%rdi), %eax | |
388 | + andl $(ROBUST_BIT|PI_BIT), %eax | |
389 | + cmpl $PI_BIT, %eax | |
390 | + jne 7f | |
391 | + | |
392 | + movl (%rdi), %eax | |
393 | + andl $TID_MASK, %eax | |
394 | + cmpl %eax, %fs:TID | |
395 | + jne 7f | |
396 | + /* We managed to get the lock. Fix it up before returning. */ | |
397 | + callq __pthread_mutex_cond_lock_adjust | |
398 | + jmp 8f | |
399 | + | |
400 | +7: callq __pthread_mutex_cond_lock | |
401 | ||
402 | - movq 24(%rsp), %rdi | |
403 | +8: movq 24(%rsp), %rdi | |
404 | movq FRAME_SIZE(%rsp), %r15 | |
405 | movq FRAME_SIZE+8(%rsp), %r14 | |
406 | movq FRAME_SIZE+16(%rsp), %r13 | |
407 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S | |
408 | --- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2013-07-09 10:18:22.507421834 +0530 | |
409 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2013-07-09 10:16:22.048427519 +0530 | |
410 | @@ -23,6 +23,7 @@ | |
411 | #include <lowlevelcond.h> | |
412 | #include <tcb-offsets.h> | |
413 | #include <pthread-pi-defines.h> | |
414 | +#include <pthread-errnos.h> | |
415 | ||
416 | #include <kernel-features.h> | |
417 | ||
418 | @@ -137,12 +138,32 @@ __pthread_cond_wait: | |
419 | movl $SYS_futex, %eax | |
420 | syscall | |
421 | ||
422 | - movl $1, %r8d | |
423 | + cmpl $0, %eax | |
424 | + sete %r8b | |
425 | + | |
426 | #ifdef __ASSUME_REQUEUE_PI | |
427 | jmp 62f | |
428 | #else | |
429 | - cmpq $-4095, %rax | |
430 | - jnae 62f | |
431 | + je 62f | |
432 | + | |
433 | + /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns | |
434 | + successfully, it has already locked the mutex for us and the | |
435 | + pi_flag (%r8b) is set to denote that fact. However, if another | |
436 | + thread changed the futex value before we entered the wait, the | |
437 | + syscall may return an EAGAIN and the mutex is not locked. We go | |
438 | + ahead with a success anyway since later we look at the pi_flag to | |
439 | + decide if we got the mutex or not. The sequence numbers then make | |
440 | + sure that only one of the threads actually wake up. We retry using | |
441 | + normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | |
442 | + and PI futexes don't mix. | |
443 | + | |
444 | + Note that we don't check for EAGAIN specifically; we assume that the | |
445 | + only other error the futex function could return is EAGAIN since | |
446 | + anything else would mean an error in our function. It is too | |
447 | + expensive to do that check for every call (which is quite common in | |
448 | + case of a large number of threads), so it has been skipped. */ | |
449 | + cmpl $-ENOSYS, %eax | |
450 | + jne 62f | |
451 | ||
452 | # ifndef __ASSUME_PRIVATE_FUTEX | |
453 | movl $FUTEX_WAIT, %esi | |
454 | @@ -155,7 +176,7 @@ __pthread_cond_wait: | |
455 | #else | |
456 | orl %fs:PRIVATE_FUTEX, %esi | |
457 | #endif | |
458 | -60: xorl %r8d, %r8d | |
459 | +60: xorb %r8b, %r8b | |
460 | movl $SYS_futex, %eax | |
461 | syscall | |
462 | ||
463 | @@ -185,10 +206,10 @@ __pthread_cond_wait: | |
464 | jne 16f | |
465 | ||
466 | cmpq 24(%rsp), %r9 | |
467 | - jbe 8b | |
468 | + jbe 19f | |
469 | ||
470 | cmpq %rax, %r9 | |
471 | - jna 8b | |
472 | + jna 19f | |
473 | ||
474 | incq woken_seq(%rdi) | |
475 | ||
476 | @@ -230,7 +251,7 @@ __pthread_cond_wait: | |
477 | /* If requeue_pi is used the kernel performs the locking of the | |
478 | mutex. */ | |
479 | 11: movq 16(%rsp), %rdi | |
480 | - testl %r8d, %r8d | |
481 | + testb %r8b, %r8b | |
482 | jnz 18f | |
483 | ||
484 | callq __pthread_mutex_cond_lock | |
485 | @@ -247,6 +268,23 @@ __pthread_cond_wait: | |
486 | xorl %eax, %eax | |
487 | jmp 14b | |
488 | ||
489 | + /* We need to go back to futex_wait. If we're using requeue_pi, then | |
490 | + release the mutex we had acquired and go back. */ | |
491 | +19: testb %r8b, %r8b | |
492 | + jz 8b | |
493 | + | |
494 | + /* Adjust the mutex values first and then unlock it. The unlock | |
495 | + should always succeed or else the kernel did not lock the mutex | |
496 | + correctly. */ | |
497 | + movq 16(%rsp), %rdi | |
498 | + callq __pthread_mutex_cond_lock_adjust | |
499 | + movq %rdi, %r8 | |
500 | + xorl %esi, %esi | |
501 | + callq __pthread_mutex_unlock_usercnt | |
502 | + /* Reload cond_var. */ | |
503 | + movq 8(%rsp), %rdi | |
504 | + jmp 8b | |
505 | + | |
506 | /* Initial locking failed. */ | |
507 | 1: | |
508 | #if cond_lock != 0 | |
509 | @@ -324,6 +362,7 @@ __pthread_cond_wait: | |
510 | ||
511 | 13: movq %r10, %rax | |
512 | jmp 14b | |
513 | + | |
514 | .size __pthread_cond_wait, .-__pthread_cond_wait | |
515 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | |
516 | GLIBC_2_3_2) | |
517 | @@ -454,10 +493,28 @@ __condvar_cleanup1: | |
518 | movl $SYS_futex, %eax | |
519 | syscall | |
520 | ||
521 | + /* Lock the mutex only if we don't own it already. This only happens | |
522 | + in case of PI mutexes, if we got cancelled after a successful | |
523 | + return of the futex syscall and before disabling async | |
524 | + cancellation. */ | |
525 | 5: movq 16(%rsp), %rdi | |
526 | - callq __pthread_mutex_cond_lock | |
527 | + movl MUTEX_KIND(%rdi), %eax | |
528 | + andl $(ROBUST_BIT|PI_BIT), %eax | |
529 | + cmpl $PI_BIT, %eax | |
530 | + jne 7f | |
531 | + | |
532 | + movl (%rdi), %eax | |
533 | + andl $TID_MASK, %eax | |
534 | + cmpl %eax, %fs:TID | |
535 | + jne 7f | |
536 | + /* We managed to get the lock. Fix it up before returning. */ | |
537 | + callq __pthread_mutex_cond_lock_adjust | |
538 | + jmp 8f | |
539 | + | |
540 | ||
541 | - movq 24(%rsp), %rdi | |
542 | +7: callq __pthread_mutex_cond_lock | |
543 | + | |
544 | +8: movq 24(%rsp), %rdi | |
545 | .LcallUR: | |
546 | call _Unwind_Resume@PLT | |
547 | hlt | |
548 | @@ -476,11 +533,11 @@ __condvar_cleanup1: | |
549 | .uleb128 .LcleanupSTART-.LSTARTCODE | |
550 | .uleb128 .LcleanupEND-.LcleanupSTART | |
551 | .uleb128 __condvar_cleanup1-.LSTARTCODE | |
552 | - .uleb128 0 | |
553 | + .uleb128 0 | |
554 | .uleb128 .LcallUR-.LSTARTCODE | |
555 | .uleb128 .LENDCODE-.LcallUR | |
556 | .uleb128 0 | |
557 | - .uleb128 0 | |
558 | + .uleb128 0 | |
559 | .Lcstend: | |
560 | ||
561 | ||
562 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-cond24.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond24.c | |
563 | --- glibc-2.12-2-gc4ccff1/nptl/tst-cond24.c 1970-01-01 05:30:00.000000000 +0530 | |
564 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond24.c 2013-07-09 10:19:10.008419593 +0530 | |
565 | @@ -0,0 +1,249 @@ | |
566 | +/* Verify that condition variables synchronized by PI mutexes don't hang. | |
567 | + Copyright (C) 2012-2013 Free Software Foundation, Inc. | |
568 | + This file is part of the GNU C Library. | |
569 | + | |
570 | + The GNU C Library is free software; you can redistribute it and/or | |
571 | + modify it under the terms of the GNU Lesser General Public | |
572 | + License as published by the Free Software Foundation; either | |
573 | + version 2.1 of the License, or (at your option) any later version. | |
574 | + | |
575 | + The GNU C Library is distributed in the hope that it will be useful, | |
576 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
577 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
578 | + Lesser General Public License for more details. | |
579 | + | |
580 | + You should have received a copy of the GNU Lesser General Public | |
581 | + License along with the GNU C Library; if not, see | |
582 | + <http://www.gnu.org/licenses/>. */ | |
583 | + | |
584 | +#include <pthread.h> | |
585 | +#include <stdio.h> | |
586 | +#include <stdlib.h> | |
587 | +#include <string.h> | |
588 | +#include <errno.h> | |
589 | +#include <sys/types.h> | |
590 | +#include <sys/syscall.h> | |
591 | +#include <unistd.h> | |
592 | +#include <sys/time.h> | |
593 | +#include <time.h> | |
594 | + | |
595 | +#define THREADS_NUM 5 | |
596 | +#define MAXITER 50000 | |
597 | + | |
598 | +static pthread_mutex_t mutex; | |
599 | +static pthread_mutexattr_t mutex_attr; | |
600 | +static pthread_cond_t cond; | |
601 | +static pthread_t threads[THREADS_NUM]; | |
602 | +static int pending = 0; | |
603 | + | |
604 | +typedef void * (*threadfunc) (void *); | |
605 | + | |
606 | +void * | |
607 | +thread_fun_timed (void *arg) | |
608 | +{ | |
609 | + int *ret = arg; | |
610 | + int rv, i; | |
611 | + | |
612 | + printf ("Started thread_fun_timed[%d]\n", *ret); | |
613 | + | |
614 | + for (i = 0; i < MAXITER / THREADS_NUM; i++) | |
615 | + { | |
616 | + rv = pthread_mutex_lock (&mutex); | |
617 | + if (rv) | |
618 | + { | |
619 | + printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); | |
620 | + *ret = 1; | |
621 | + goto out; | |
622 | + } | |
623 | + | |
624 | + while (!pending) | |
625 | + { | |
626 | + struct timespec ts; | |
627 | + clock_gettime(CLOCK_REALTIME, &ts); | |
628 | + ts.tv_sec += 20; | |
629 | + rv = pthread_cond_timedwait (&cond, &mutex, &ts); | |
630 | + | |
631 | + /* There should be no timeout either. */ | |
632 | + if (rv) | |
633 | + { | |
634 | + printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv); | |
635 | + *ret = 1; | |
636 | + goto out; | |
637 | + } | |
638 | + } | |
639 | + | |
640 | + pending--; | |
641 | + | |
642 | + rv = pthread_mutex_unlock (&mutex); | |
643 | + if (rv) | |
644 | + { | |
645 | + printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); | |
646 | + *ret = 1; | |
647 | + goto out; | |
648 | + } | |
649 | + } | |
650 | + | |
651 | + *ret = 0; | |
652 | + | |
653 | +out: | |
654 | + return ret; | |
655 | +} | |
656 | + | |
657 | +void * | |
658 | +thread_fun (void *arg) | |
659 | +{ | |
660 | + int *ret = arg; | |
661 | + int rv, i; | |
662 | + | |
663 | + printf ("Started thread_fun[%d]\n", *ret); | |
664 | + | |
665 | + for (i = 0; i < MAXITER / THREADS_NUM; i++) | |
666 | + { | |
667 | + rv = pthread_mutex_lock (&mutex); | |
668 | + if (rv) | |
669 | + { | |
670 | + printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); | |
671 | + *ret = 1; | |
672 | + goto out; | |
673 | + } | |
674 | + | |
675 | + while (!pending) | |
676 | + { | |
677 | + rv = pthread_cond_wait (&cond, &mutex); | |
678 | + | |
679 | + if (rv) | |
680 | + { | |
681 | + printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv); | |
682 | + *ret = 1; | |
683 | + goto out; | |
684 | + } | |
685 | + } | |
686 | + | |
687 | + pending--; | |
688 | + | |
689 | + rv = pthread_mutex_unlock (&mutex); | |
690 | + if (rv) | |
691 | + { | |
692 | + printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); | |
693 | + *ret = 1; | |
694 | + goto out; | |
695 | + } | |
696 | + } | |
697 | + | |
698 | + *ret = 0; | |
699 | + | |
700 | +out: | |
701 | + return ret; | |
702 | +} | |
703 | + | |
704 | +static int | |
705 | +do_test_wait (threadfunc f) | |
706 | +{ | |
707 | + int i; | |
708 | + int rv; | |
709 | + int counter = 0; | |
710 | + int retval[THREADS_NUM]; | |
711 | + | |
712 | + puts ("Starting test"); | |
713 | + | |
714 | + rv = pthread_mutexattr_init (&mutex_attr); | |
715 | + if (rv) | |
716 | + { | |
717 | + printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv); | |
718 | + return 1; | |
719 | + } | |
720 | + | |
721 | + rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT); | |
722 | + if (rv) | |
723 | + { | |
724 | + printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv); | |
725 | + return 1; | |
726 | + } | |
727 | + | |
728 | + rv = pthread_mutex_init (&mutex, &mutex_attr); | |
729 | + if (rv) | |
730 | + { | |
731 | + printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv); | |
732 | + return 1; | |
733 | + } | |
734 | + | |
735 | + rv = pthread_cond_init (&cond, NULL); | |
736 | + if (rv) | |
737 | + { | |
738 | + printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv); | |
739 | + return 1; | |
740 | + } | |
741 | + | |
742 | + for (i = 0; i < THREADS_NUM; i++) | |
743 | + { | |
744 | + retval[i] = i; | |
745 | + rv = pthread_create (&threads[i], NULL, f, &retval[i]); | |
746 | + if (rv) | |
747 | + { | |
748 | + printf ("pthread_create: %s(%d)\n", strerror (rv), rv); | |
749 | + return 1; | |
750 | + } | |
751 | + } | |
752 | + | |
753 | + for (; counter < MAXITER; counter++) | |
754 | + { | |
755 | + rv = pthread_mutex_lock (&mutex); | |
756 | + if (rv) | |
757 | + { | |
758 | + printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); | |
759 | + return 1; | |
760 | + } | |
761 | + | |
762 | + if (!(counter % 100)) | |
763 | + printf ("counter: %d\n", counter); | |
764 | + pending += 1; | |
765 | + | |
766 | + rv = pthread_cond_signal (&cond); | |
767 | + if (rv) | |
768 | + { | |
769 | + printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv); | |
770 | + return 1; | |
771 | + } | |
772 | + | |
773 | + rv = pthread_mutex_unlock (&mutex); | |
774 | + if (rv) | |
775 | + { | |
776 | + printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); | |
777 | + return 1; | |
778 | + } | |
779 | + } | |
780 | + | |
781 | + for (i = 0; i < THREADS_NUM; i++) | |
782 | + { | |
783 | + void *ret; | |
784 | + rv = pthread_join (threads[i], &ret); | |
785 | + if (rv) | |
786 | + { | |
787 | + printf ("pthread_join: %s(%d)\n", strerror (rv), rv); | |
788 | + return 1; | |
789 | + } | |
790 | + if (ret && *(int *)ret) | |
791 | + { | |
792 | + printf ("Thread %d returned with an error\n", i); | |
793 | + return 1; | |
794 | + } | |
795 | + } | |
796 | + | |
797 | + return 0; | |
798 | +} | |
799 | + | |
800 | +static int | |
801 | +do_test (void) | |
802 | +{ | |
803 | + puts ("Testing pthread_cond_wait"); | |
804 | + int ret = do_test_wait (thread_fun); | |
805 | + if (ret) | |
806 | + return ret; | |
807 | + | |
808 | + puts ("Testing pthread_cond_timedwait"); | |
809 | + return do_test_wait (thread_fun_timed); | |
810 | +} | |
811 | + | |
812 | +#define TIMEOUT 20 | |
813 | +#define TEST_FUNCTION do_test () | |
814 | +#include "../test-skeleton.c" | |
815 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-cond25.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond25.c | |
816 | --- glibc-2.12-2-gc4ccff1/nptl/tst-cond25.c 1970-01-01 05:30:00.000000000 +0530 | |
817 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond25.c 2013-07-09 10:19:15.472419335 +0530 | |
818 | @@ -0,0 +1,281 @@ | |
819 | +/* Verify that condition variables synchronized by PI mutexes don't hang on | |
820 | + on cancellation. | |
821 | + Copyright (C) 2012-2013 Free Software Foundation, Inc. | |
822 | + This file is part of the GNU C Library. | |
823 | + | |
824 | + The GNU C Library is free software; you can redistribute it and/or | |
825 | + modify it under the terms of the GNU Lesser General Public | |
826 | + License as published by the Free Software Foundation; either | |
827 | + version 2.1 of the License, or (at your option) any later version. | |
828 | + | |
829 | + The GNU C Library is distributed in the hope that it will be useful, | |
830 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
831 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
832 | + Lesser General Public License for more details. | |
833 | + | |
834 | + You should have received a copy of the GNU Lesser General Public | |
835 | + License along with the GNU C Library; if not, see | |
836 | + <http://www.gnu.org/licenses/>. */ | |
837 | + | |
838 | +#include <pthread.h> | |
839 | +#include <stdio.h> | |
840 | +#include <stdlib.h> | |
841 | +#include <stdint.h> | |
842 | +#include <string.h> | |
843 | +#include <errno.h> | |
844 | +#include <sys/types.h> | |
845 | +#include <sys/syscall.h> | |
846 | +#include <unistd.h> | |
847 | +#include <sys/time.h> | |
848 | +#include <time.h> | |
849 | + | |
850 | +#define NUM 5 | |
851 | +#define ITERS 10000 | |
852 | +#define COUNT 100 | |
853 | + | |
854 | +typedef void *(*thr_func) (void *); | |
855 | + | |
856 | +pthread_mutex_t mutex; | |
857 | +pthread_cond_t cond; | |
858 | + | |
859 | +void cleanup (void *u) | |
860 | +{ | |
861 | + /* pthread_cond_wait should always return with the mutex locked. */ | |
862 | + if (pthread_mutex_unlock (&mutex)) | |
863 | + abort (); | |
864 | +} | |
865 | + | |
866 | +void * | |
867 | +signaller (void *u) | |
868 | +{ | |
869 | + int i, ret = 0; | |
870 | + void *tret = NULL; | |
871 | + | |
872 | + for (i = 0; i < ITERS; i++) | |
873 | + { | |
874 | + if ((ret = pthread_mutex_lock (&mutex)) != 0) | |
875 | + { | |
876 | + tret = (void *)1; | |
877 | + printf ("signaller:mutex_lock failed: %s\n", strerror (ret)); | |
878 | + goto out; | |
879 | + } | |
880 | + if ((ret = pthread_cond_signal (&cond)) != 0) | |
881 | + { | |
882 | + tret = (void *)1; | |
883 | + printf ("signaller:signal failed: %s\n", strerror (ret)); | |
884 | + goto unlock_out; | |
885 | + } | |
886 | + if ((ret = pthread_mutex_unlock (&mutex)) != 0) | |
887 | + { | |
888 | + tret = (void *)1; | |
889 | + printf ("signaller:mutex_unlock failed: %s\n", strerror (ret)); | |
890 | + goto out; | |
891 | + } | |
892 | + pthread_testcancel (); | |
893 | + } | |
894 | + | |
895 | +out: | |
896 | + return tret; | |
897 | + | |
898 | +unlock_out: | |
899 | + if ((ret = pthread_mutex_unlock (&mutex)) != 0) | |
900 | + printf ("signaller:mutex_unlock[2] failed: %s\n", strerror (ret)); | |
901 | + goto out; | |
902 | +} | |
903 | + | |
904 | +void * | |
905 | +waiter (void *u) | |
906 | +{ | |
907 | + int i, ret = 0; | |
908 | + void *tret = NULL; | |
909 | + int seq = (uintptr_t) u; | |
910 | + | |
911 | + for (i = 0; i < ITERS / NUM; i++) | |
912 | + { | |
913 | + if ((ret = pthread_mutex_lock (&mutex)) != 0) | |
914 | + { | |
915 | + tret = (void *) (uintptr_t) 1; | |
916 | + printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret)); | |
917 | + goto out; | |
918 | + } | |
919 | + pthread_cleanup_push (cleanup, NULL); | |
920 | + | |
921 | + if ((ret = pthread_cond_wait (&cond, &mutex)) != 0) | |
922 | + { | |
923 | + tret = (void *) (uintptr_t) 1; | |
924 | + printf ("waiter[%u]:wait failed: %s\n", seq, strerror (ret)); | |
925 | + goto unlock_out; | |
926 | + } | |
927 | + | |
928 | + if ((ret = pthread_mutex_unlock (&mutex)) != 0) | |
929 | + { | |
930 | + tret = (void *) (uintptr_t) 1; | |
931 | + printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret)); | |
932 | + goto out; | |
933 | + } | |
934 | + pthread_cleanup_pop (0); | |
935 | + } | |
936 | + | |
937 | +out: | |
938 | + puts ("waiter tests done"); | |
939 | + return tret; | |
940 | + | |
941 | +unlock_out: | |
942 | + if ((ret = pthread_mutex_unlock (&mutex)) != 0) | |
943 | + printf ("waiter:mutex_unlock[2] failed: %s\n", strerror (ret)); | |
944 | + goto out; | |
945 | +} | |
946 | + | |
947 | +void * | |
948 | +timed_waiter (void *u) | |
949 | +{ | |
950 | + int i, ret; | |
951 | + void *tret = NULL; | |
952 | + int seq = (uintptr_t) u; | |
953 | + | |
954 | + for (i = 0; i < ITERS / NUM; i++) | |
955 | + { | |
956 | + struct timespec ts; | |
957 | + | |
958 | + if ((ret = clock_gettime(CLOCK_REALTIME, &ts)) != 0) | |
959 | + { | |
960 | + tret = (void *) (uintptr_t) 1; | |
961 | + printf ("%u:clock_gettime failed: %s\n", seq, strerror (errno)); | |
962 | + goto out; | |
963 | + } | |
964 | + ts.tv_sec += 20; | |
965 | + | |
966 | + if ((ret = pthread_mutex_lock (&mutex)) != 0) | |
967 | + { | |
968 | + tret = (void *) (uintptr_t) 1; | |
969 | + printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret)); | |
970 | + goto out; | |
971 | + } | |
972 | + pthread_cleanup_push (cleanup, NULL); | |
973 | + | |
974 | + /* We should not time out either. */ | |
975 | + if ((ret = pthread_cond_timedwait (&cond, &mutex, &ts)) != 0) | |
976 | + { | |
977 | + tret = (void *) (uintptr_t) 1; | |
978 | + printf ("waiter[%u]:timedwait failed: %s\n", seq, strerror (ret)); | |
979 | + goto unlock_out; | |
980 | + } | |
981 | + if ((ret = pthread_mutex_unlock (&mutex)) != 0) | |
982 | + { | |
983 | + tret = (void *) (uintptr_t) 1; | |
984 | + printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret)); | |
985 | + goto out; | |
986 | + } | |
987 | + pthread_cleanup_pop (0); | |
988 | + } | |
989 | + | |
990 | +out: | |
991 | + puts ("timed_waiter tests done"); | |
992 | + return tret; | |
993 | + | |
994 | +unlock_out: | |
995 | + if ((ret = pthread_mutex_unlock (&mutex)) != 0) | |
996 | + printf ("waiter[%u]:mutex_unlock[2] failed: %s\n", seq, strerror (ret)); | |
997 | + goto out; | |
998 | +} | |
999 | + | |
1000 | +int | |
1001 | +do_test_wait (thr_func f) | |
1002 | +{ | |
1003 | + pthread_t w[NUM]; | |
1004 | + pthread_t s; | |
1005 | + pthread_mutexattr_t attr; | |
1006 | + int i, j, ret = 0; | |
1007 | + void *thr_ret; | |
1008 | + | |
1009 | + for (i = 0; i < COUNT; i++) | |
1010 | + { | |
1011 | + if ((ret = pthread_mutexattr_init (&attr)) != 0) | |
1012 | + { | |
1013 | + printf ("mutexattr_init failed: %s\n", strerror (ret)); | |
1014 | + goto out; | |
1015 | + } | |
1016 | + | |
1017 | + if ((ret = pthread_mutexattr_setprotocol (&attr, | |
1018 | + PTHREAD_PRIO_INHERIT)) != 0) | |
1019 | + { | |
1020 | + printf ("mutexattr_setprotocol failed: %s\n", strerror (ret)); | |
1021 | + goto out; | |
1022 | + } | |
1023 | + | |
1024 | + if ((ret = pthread_cond_init (&cond, NULL)) != 0) | |
1025 | + { | |
1026 | + printf ("cond_init failed: %s\n", strerror (ret)); | |
1027 | + goto out; | |
1028 | + } | |
1029 | + | |
1030 | + if ((ret = pthread_mutex_init (&mutex, &attr)) != 0) | |
1031 | + { | |
1032 | + printf ("mutex_init failed: %s\n", strerror (ret)); | |
1033 | + goto out; | |
1034 | + } | |
1035 | + | |
1036 | + for (j = 0; j < NUM; j++) | |
1037 | + if ((ret = pthread_create (&w[j], NULL, | |
1038 | + f, (void *) (uintptr_t) j)) != 0) | |
1039 | + { | |
1040 | + printf ("waiter[%d]: create failed: %s\n", j, strerror (ret)); | |
1041 | + goto out; | |
1042 | + } | |
1043 | + | |
1044 | + if ((ret = pthread_create (&s, NULL, signaller, NULL)) != 0) | |
1045 | + { | |
1046 | + printf ("signaller: create failed: %s\n", strerror (ret)); | |
1047 | + goto out; | |
1048 | + } | |
1049 | + | |
1050 | + for (j = 0; j < NUM; j++) | |
1051 | + { | |
1052 | + pthread_cancel (w[j]); | |
1053 | + | |
1054 | + if ((ret = pthread_join (w[j], &thr_ret)) != 0) | |
1055 | + { | |
1056 | + printf ("waiter[%d]: join failed: %s\n", j, strerror (ret)); | |
1057 | + goto out; | |
1058 | + } | |
1059 | + | |
1060 | + if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED) | |
1061 | + { | |
1062 | + ret = 1; | |
1063 | + goto out; | |
1064 | + } | |
1065 | + } | |
1066 | + | |
1067 | + /* The signalling thread could have ended before it was cancelled. */ | |
1068 | + pthread_cancel (s); | |
1069 | + | |
1070 | + if ((ret = pthread_join (s, &thr_ret)) != 0) | |
1071 | + { | |
1072 | + printf ("signaller: join failed: %s\n", strerror (ret)); | |
1073 | + goto out; | |
1074 | + } | |
1075 | + | |
1076 | + if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED) | |
1077 | + { | |
1078 | + ret = 1; | |
1079 | + goto out; | |
1080 | + } | |
1081 | + } | |
1082 | + | |
1083 | +out: | |
1084 | + return ret; | |
1085 | +} | |
1086 | + | |
1087 | +int | |
1088 | +do_test (int argc, char **argv) | |
1089 | +{ | |
1090 | + int ret = do_test_wait (waiter); | |
1091 | + | |
1092 | + if (ret) | |
1093 | + return ret; | |
1094 | + | |
1095 | + return do_test_wait (timed_waiter); | |
1096 | +} | |
1097 | + | |
1098 | +#define TIMEOUT 5 | |
1099 | +#include "../test-skeleton.c" | |
1100 | diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-cond-except.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond-except.c | |
1101 | --- glibc-2.12-2-gc4ccff1/nptl/tst-cond-except.c 1970-01-01 05:30:00.000000000 +0530 | |
1102 | +++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond-except.c 2013-07-09 10:19:01.334420002 +0530 | |
1103 | @@ -0,0 +1,110 @@ | |
1104 | +/* Verify that exception table for pthread_cond_wait is correct. | |
1105 | + Copyright (C) 2012-2013 Free Software Foundation, Inc. | |
1106 | + This file is part of the GNU C Library. | |
1107 | + | |
1108 | + The GNU C Library is free software; you can redistribute it and/or | |
1109 | + modify it under the terms of the GNU Lesser General Public | |
1110 | + License as published by the Free Software Foundation; either | |
1111 | + version 2.1 of the License, or (at your option) any later version. | |
1112 | + | |
1113 | + The GNU C Library is distributed in the hope that it will be useful, | |
1114 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1115 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1116 | + Lesser General Public License for more details. | |
1117 | + | |
1118 | + You should have received a copy of the GNU Lesser General Public | |
1119 | + License along with the GNU C Library; if not, see | |
1120 | + <http://www.gnu.org/licenses/>. */ | |
1121 | + | |
1122 | +#include <pthread.h> | |
1123 | +#include <stdio.h> | |
1124 | +#include <stdint.h> | |
1125 | +#include <string.h> | |
1126 | +#include <unistd.h> | |
1127 | + | |
1128 | +pthread_mutex_t mutex; | |
1129 | +pthread_cond_t cond; | |
1130 | + | |
1131 | +#define CHECK_RETURN_VAL_OR_FAIL(ret,str) \ | |
1132 | + ({ if ((ret) != 0) \ | |
1133 | + { \ | |
1134 | + printf ("%s failed: %s\n", (str), strerror (ret)); \ | |
1135 | + ret = 1; \ | |
1136 | + goto out; \ | |
1137 | + } \ | |
1138 | + }) | |
1139 | + | |
1140 | + | |
1141 | +void | |
1142 | +clean (void *arg) | |
1143 | +{ | |
1144 | + puts ("clean: Unlocking mutex..."); | |
1145 | + pthread_mutex_unlock ((pthread_mutex_t *) arg); | |
1146 | + puts ("clean: Mutex unlocked..."); | |
1147 | +} | |
1148 | + | |
1149 | +void * | |
1150 | +thr (void *arg) | |
1151 | +{ | |
1152 | + int ret = 0; | |
1153 | + pthread_mutexattr_t mutexAttr; | |
1154 | + ret = pthread_mutexattr_init (&mutexAttr); | |
1155 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_init"); | |
1156 | + | |
1157 | + ret = pthread_mutexattr_setprotocol (&mutexAttr, PTHREAD_PRIO_INHERIT); | |
1158 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_setprotocol"); | |
1159 | + | |
1160 | + ret = pthread_mutex_init (&mutex, &mutexAttr); | |
1161 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_init"); | |
1162 | + | |
1163 | + ret = pthread_cond_init (&cond, 0); | |
1164 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_init"); | |
1165 | + | |
1166 | + puts ("th: Init done, entering wait..."); | |
1167 | + | |
1168 | + pthread_cleanup_push (clean, (void *) &mutex); | |
1169 | + ret = pthread_mutex_lock (&mutex); | |
1170 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_lock"); | |
1171 | + while (1) | |
1172 | + { | |
1173 | + ret = pthread_cond_wait (&cond, &mutex); | |
1174 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_wait"); | |
1175 | + } | |
1176 | + pthread_cleanup_pop (1); | |
1177 | + | |
1178 | +out: | |
1179 | + return (void *) (uintptr_t) ret; | |
1180 | +} | |
1181 | + | |
1182 | +int | |
1183 | +do_test (void) | |
1184 | +{ | |
1185 | + pthread_t thread; | |
1186 | + int ret = 0; | |
1187 | + void *thr_ret = 0; | |
1188 | + ret = pthread_create (&thread, 0, thr, &thr_ret); | |
1189 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_create"); | |
1190 | + | |
1191 | + puts ("main: Thread created, waiting a bit..."); | |
1192 | + sleep (2); | |
1193 | + | |
1194 | + puts ("main: Cancelling thread..."); | |
1195 | + ret = pthread_cancel (thread); | |
1196 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cancel"); | |
1197 | + | |
1198 | + puts ("main: Joining th..."); | |
1199 | + ret = pthread_join (thread, NULL); | |
1200 | + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_join"); | |
1201 | + | |
1202 | + if (thr_ret != NULL) | |
1203 | + return 1; | |
1204 | + | |
1205 | + puts ("main: Joined thread, done!"); | |
1206 | + | |
1207 | +out: | |
1208 | + return ret; | |
1209 | +} | |
1210 | + | |
1211 | +#define TEST_FUNCTION do_test () | |
1212 | +#define TIMEOUT 5 | |
1213 | +#include "../test-skeleton.c" |