|
|
| 17 |
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
17 |
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 18 |
02111-1307 USA. */ |
18 |
02111-1307 USA. */ |
| 19 |
|
19 |
|
|
|
20 |
#include <assert.h> |
| 20 |
#include <endian.h> |
21 |
#include <endian.h> |
| 21 |
#include <errno.h> |
22 |
#include <errno.h> |
| 22 |
#include <sysdep.h> |
23 |
#include <sysdep.h> |
| 23 |
#include <lowlevellock.h> |
24 |
#include <lowlevellock.h> |
|
|
25 |
#include <not-cancel.h> |
| 24 |
#include <pthread.h> |
26 |
#include <pthread.h> |
| 25 |
#include <pthreadP.h> |
27 |
#include <pthreadP.h> |
| 26 |
|
28 |
|
| 27 |
#include <shlib-compat.h> |
29 |
#include <shlib-compat.h> |
| 28 |
|
30 |
|
|
|
31 |
#include "cond-lock.h" |
| 32 |
|
| 29 |
|
33 |
|
| 30 |
struct _condvar_cleanup_buffer |
34 |
struct _condvar_cleanup_buffer |
| 31 |
{ |
35 |
{ |
|
Lines 38-53
struct _condvar_cleanup_buffer
|
Link Here
|
|---|
|
| 38 |
|
42 |
|
| 39 |
void |
43 |
void |
| 40 |
__attribute__ ((visibility ("hidden"))) |
44 |
__attribute__ ((visibility ("hidden"))) |
|
|
45 |
lll_pi_lock(int *futexp, int private) |
| 46 |
{ |
| 47 |
pid_t id = THREAD_GETMEM (THREAD_SELF, tid); |
| 48 |
int newval = id; |
| 49 |
int ret; |
| 50 |
|
| 51 |
newval |= FUTEX_WAITERS; |
| 52 |
ret = atomic_compare_and_exchange_val_acq (futexp, newval, 0); |
| 53 |
|
| 54 |
if (ret != 0) |
| 55 |
{ |
| 56 |
/* The mutex is locked. The kernel will now take care of |
| 57 |
everything. */ |
| 58 |
INTERNAL_SYSCALL_DECL (__err); |
| 59 |
int e = INTERNAL_SYSCALL (futex, __err, 4, futexp, |
| 60 |
__lll_private_flag (FUTEX_LOCK_PI, private), |
| 61 |
1, 0); |
| 62 |
} |
| 63 |
} |
| 64 |
|
| 65 |
|
| 66 |
void |
| 67 |
__attribute__ ((visibility ("hidden"))) |
| 68 |
lll_pi_unlock(int *futexp, int private) |
| 69 |
{ |
| 70 |
|
| 71 |
if ((*futexp & FUTEX_WAITERS) != 0 |
| 72 |
|| atomic_compare_and_exchange_bool_acq (futexp, 0, |
| 73 |
THREAD_GETMEM (THREAD_SELF, |
| 74 |
tid))) |
| 75 |
{ |
| 76 |
INTERNAL_SYSCALL_DECL (__err); |
| 77 |
INTERNAL_SYSCALL (futex, __err, 2, futexp, |
| 78 |
__lll_private_flag (FUTEX_UNLOCK_PI, private)); |
| 79 |
} |
| 80 |
} |
| 81 |
|
| 82 |
|
| 83 |
void |
| 84 |
__attribute__ ((visibility ("hidden"))) |
| 41 |
__condvar_cleanup (void *arg) |
85 |
__condvar_cleanup (void *arg) |
| 42 |
{ |
86 |
{ |
| 43 |
struct _condvar_cleanup_buffer *cbuffer = |
87 |
struct _condvar_cleanup_buffer *cbuffer = |
| 44 |
(struct _condvar_cleanup_buffer *) arg; |
88 |
(struct _condvar_cleanup_buffer *) arg; |
| 45 |
unsigned int destroying; |
89 |
unsigned int destroying; |
| 46 |
int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l) |
90 |
int pshared = (cbuffer->mutex == (void *) ~0l) ? LLL_SHARED : LLL_PRIVATE; |
| 47 |
? LLL_SHARED : LLL_PRIVATE; |
|
|
| 48 |
|
91 |
|
| 49 |
/* We are going to modify shared data. */ |
92 |
/* We are going to modify shared data. */ |
| 50 |
lll_lock (cbuffer->cond->__data.__lock, pshared); |
93 |
cond_lock(cbuffer->cond, pshared); |
| 51 |
|
94 |
|
| 52 |
if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) |
95 |
if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) |
| 53 |
{ |
96 |
{ |
|
Lines 78-84
__condvar_cleanup (void *arg)
|
Link Here
|
|---|
|
| 78 |
} |
121 |
} |
| 79 |
|
122 |
|
| 80 |
/* We are done. */ |
123 |
/* We are done. */ |
| 81 |
lll_unlock (cbuffer->cond->__data.__lock, pshared); |
124 |
cond_unlock(cbuffer->cond, pshared); |
| 82 |
|
125 |
|
| 83 |
/* Wake everybody to make sure no condvar signal gets lost. */ |
126 |
/* Wake everybody to make sure no condvar signal gets lost. */ |
| 84 |
if (! destroying) |
127 |
if (! destroying) |
|
Lines 97-114
__pthread_cond_wait (cond, mutex)
|
Link Here
|
|---|
|
| 97 |
{ |
140 |
{ |
| 98 |
struct _pthread_cleanup_buffer buffer; |
141 |
struct _pthread_cleanup_buffer buffer; |
| 99 |
struct _condvar_cleanup_buffer cbuffer; |
142 |
struct _condvar_cleanup_buffer cbuffer; |
| 100 |
int err; |
|
|
| 101 |
int pshared = (cond->__data.__mutex == (void *) ~0l) |
143 |
int pshared = (cond->__data.__mutex == (void *) ~0l) |
| 102 |
? LLL_SHARED : LLL_PRIVATE; |
144 |
? LLL_SHARED : LLL_PRIVATE; |
|
|
145 |
int pi_requeued; |
| 146 |
int err; |
| 103 |
|
147 |
|
| 104 |
/* Make sure we are along. */ |
148 |
/* Make sure we are along. */ |
| 105 |
lll_lock (cond->__data.__lock, pshared); |
149 |
cond_lock(cond, pshared); |
| 106 |
|
150 |
|
| 107 |
/* Now we can release the mutex. */ |
151 |
/* Now we can release the mutex. */ |
| 108 |
err = __pthread_mutex_unlock_usercnt (mutex, 0); |
152 |
err = __pthread_mutex_unlock_usercnt (mutex, 0); |
| 109 |
if (__builtin_expect (err, 0)) |
153 |
if (__builtin_expect (err, 0)) |
| 110 |
{ |
154 |
{ |
| 111 |
lll_unlock (cond->__data.__lock, pshared); |
155 |
cond_unlock(cond, pshared); |
| 112 |
return err; |
156 |
return err; |
| 113 |
} |
157 |
} |
| 114 |
|
158 |
|
|
Lines 142-162
__pthread_cond_wait (cond, mutex)
|
Link Here
|
|---|
|
| 142 |
do |
186 |
do |
| 143 |
{ |
187 |
{ |
| 144 |
unsigned int futex_val = cond->__data.__futex; |
188 |
unsigned int futex_val = cond->__data.__futex; |
|
|
189 |
pi_requeued = 0; |
| 145 |
|
190 |
|
| 146 |
/* Prepare to wait. Release the condvar futex. */ |
191 |
/* Prepare to wait. Release the condvar futex. */ |
| 147 |
lll_unlock (cond->__data.__lock, pshared); |
192 |
cond_unlock(cond, pshared); |
| 148 |
|
193 |
|
| 149 |
/* Enable asynchronous cancellation. Required by the standard. */ |
194 |
/* Enable asynchronous cancellation. Required by the standard. */ |
| 150 |
cbuffer.oldtype = __pthread_enable_asynccancel (); |
195 |
cbuffer.oldtype = __pthread_enable_asynccancel (); |
| 151 |
|
196 |
|
|
|
197 |
if (mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) |
| 198 |
{ |
| 199 |
/* Try requeueing to the PI mutex, if no support in the kernel |
| 200 |
try the non-requeue syscall. */ |
| 201 |
err = lll_futex_wait_requeue_pi (cond, futex_val, |
| 202 |
&mutex->__data.__lock, pshared); |
| 203 |
if (__builtin_expect (!err, 1)) |
| 204 |
pi_requeued = 1; |
| 205 |
if (__builtin_expect (err != -ENOSYS, 0)) |
| 206 |
goto woken; |
| 207 |
} |
| 208 |
|
| 152 |
/* Wait until woken by signal or broadcast. */ |
209 |
/* Wait until woken by signal or broadcast. */ |
| 153 |
lll_futex_wait (&cond->__data.__futex, futex_val, pshared); |
210 |
lll_futex_wait (&cond->__data.__futex, futex_val, pshared); |
| 154 |
|
211 |
|
|
|
212 |
woken: |
| 155 |
/* Disable asynchronous cancellation. */ |
213 |
/* Disable asynchronous cancellation. */ |
| 156 |
__pthread_disable_asynccancel (cbuffer.oldtype); |
214 |
__pthread_disable_asynccancel (cbuffer.oldtype); |
| 157 |
|
215 |
|
| 158 |
/* We are going to look at shared data again, so get the lock. */ |
216 |
/* We are going to look at shared data again, so get the lock. */ |
| 159 |
lll_lock (cond->__data.__lock, pshared); |
217 |
cond_lock(cond, pshared); |
| 160 |
|
218 |
|
| 161 |
/* If a broadcast happened, we are done. */ |
219 |
/* If a broadcast happened, we are done. */ |
| 162 |
if (cbuffer.bc_seq != cond->__data.__broadcast_seq) |
220 |
if (cbuffer.bc_seq != cond->__data.__broadcast_seq) |
|
Lines 182-194
__pthread_cond_wait (cond, mutex)
|
Link Here
|
|---|
|
| 182 |
lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); |
240 |
lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); |
| 183 |
|
241 |
|
| 184 |
/* We are done with the condvar. */ |
242 |
/* We are done with the condvar. */ |
| 185 |
lll_unlock (cond->__data.__lock, pshared); |
243 |
cond_unlock(cond, pshared); |
| 186 |
|
244 |
|
| 187 |
/* The cancellation handling is back to normal, remove the handler. */ |
245 |
/* The cancellation handling is back to normal, remove the handler. */ |
| 188 |
__pthread_cleanup_pop (&buffer, 0); |
246 |
__pthread_cleanup_pop (&buffer, 0); |
| 189 |
|
247 |
|
| 190 |
/* Get the mutex before returning. */ |
248 |
/* Get the mutex before returning. If the requeue_pi call above was successful, |
| 191 |
return __pthread_mutex_cond_lock (mutex); |
249 |
the lock is already held in the kernel, so just return 0 to application. */ |
|
|
250 |
if (pi_requeued) |
| 251 |
{ |
| 252 |
__pthread_mutex_cond_lock_adjust (mutex); |
| 253 |
return 0; |
| 254 |
} |
| 255 |
else |
| 256 |
return __pthread_mutex_cond_lock (mutex); |
| 192 |
} |
257 |
} |
| 193 |
|
258 |
|
| 194 |
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, |
259 |
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, |