1 | /* Copyright (C) 2002-2016 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <errno.h> |
20 | #include <shlib-compat.h> |
21 | #include "pthreadP.h" |
22 | #include <stap-probe.h> |
23 | |
24 | |
25 | int |
26 | __pthread_cond_destroy (pthread_cond_t *cond) |
27 | { |
28 | int pshared = (cond->__data.__mutex == (void *) ~0l) |
29 | ? LLL_SHARED : LLL_PRIVATE; |
30 | |
31 | LIBC_PROBE (cond_destroy, 1, cond); |
32 | |
33 | /* Make sure we are alone. */ |
34 | lll_lock (cond->__data.__lock, pshared); |
35 | |
36 | if (cond->__data.__total_seq > cond->__data.__wakeup_seq) |
37 | { |
38 | /* If there are still some waiters which have not been |
39 | woken up, this is an application bug. */ |
40 | lll_unlock (cond->__data.__lock, pshared); |
41 | return EBUSY; |
42 | } |
43 | |
44 | /* Tell pthread_cond_*wait that this condvar is being destroyed. */ |
45 | cond->__data.__total_seq = -1ULL; |
46 | |
47 | /* If there are waiters which have been already signalled or |
48 | broadcasted, but still are using the pthread_cond_t structure, |
49 | pthread_cond_destroy needs to wait for them. */ |
50 | unsigned int nwaiters = cond->__data.__nwaiters; |
51 | |
52 | if (nwaiters >= (1 << COND_NWAITERS_SHIFT)) |
53 | { |
54 | /* Wake everybody on the associated mutex in case there are |
55 | threads that have been requeued to it. |
56 | Without this, pthread_cond_destroy could block potentially |
57 | for a long time or forever, as it would depend on other |
58 | thread's using the mutex. |
59 | When all threads waiting on the mutex are woken up, pthread_cond_wait |
60 | only waits for threads to acquire and release the internal |
61 | condvar lock. */ |
62 | if (cond->__data.__mutex != NULL |
63 | && cond->__data.__mutex != (void *) ~0l) |
64 | { |
65 | pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; |
66 | lll_futex_wake (&mut->__data.__lock, INT_MAX, |
67 | PTHREAD_MUTEX_PSHARED (mut)); |
68 | } |
69 | |
70 | do |
71 | { |
72 | lll_unlock (cond->__data.__lock, pshared); |
73 | |
74 | lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared); |
75 | |
76 | lll_lock (cond->__data.__lock, pshared); |
77 | |
78 | nwaiters = cond->__data.__nwaiters; |
79 | } |
80 | while (nwaiters >= (1 << COND_NWAITERS_SHIFT)); |
81 | } |
82 | |
83 | return 0; |
84 | } |
85 | versioned_symbol (libpthread, __pthread_cond_destroy, |
86 | pthread_cond_destroy, GLIBC_2_3_2); |
87 | |