Deleted Added
full compact
thr_cond.c (164583) thr_cond.c (164877)
1/*
2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
1/*
2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 164583 2006-11-24 09:57:38Z davidxu $
26 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 164877 2006-12-04 14:20:41Z davidxu $
27 */
28
29#include "namespace.h"
30#include <stdlib.h>
31#include <errno.h>
32#include <string.h>
33#include <pthread.h>
34#include <limits.h>

--- 27 unchanged lines hidden (view full) ---

62
63static int
64cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
65{
66 pthread_cond_t pcond;
67 int rval = 0;
68
69 if ((pcond = (pthread_cond_t)
27 */
28
29#include "namespace.h"
30#include <stdlib.h>
31#include <errno.h>
32#include <string.h>
33#include <pthread.h>
34#include <limits.h>

--- 27 unchanged lines hidden (view full) ---

62
63static int
64cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
65{
66 pthread_cond_t pcond;
67 int rval = 0;
68
69 if ((pcond = (pthread_cond_t)
70 malloc(sizeof(struct pthread_cond))) == NULL) {
70 calloc(1, sizeof(struct pthread_cond))) == NULL) {
71 rval = ENOMEM;
72 } else {
73 /*
74 * Initialise the condition variable structure:
75 */
71 rval = ENOMEM;
72 } else {
73 /*
74 * Initialise the condition variable structure:
75 */
76 _thr_umutex_init(&pcond->c_lock);
77 pcond->c_seqno = 0;
78 pcond->c_waiters = 0;
79 pcond->c_wakeups = 0;
80 if (cond_attr == NULL || *cond_attr == NULL) {
81 pcond->c_pshared = 0;
82 pcond->c_clockid = CLOCK_REALTIME;
83 } else {
84 pcond->c_pshared = (*cond_attr)->c_pshared;
85 pcond->c_clockid = (*cond_attr)->c_clockid;
86 }
76 if (cond_attr == NULL || *cond_attr == NULL) {
77 pcond->c_pshared = 0;
78 pcond->c_clockid = CLOCK_REALTIME;
79 } else {
80 pcond->c_pshared = (*cond_attr)->c_pshared;
81 pcond->c_clockid = (*cond_attr)->c_clockid;
82 }
83 _thr_umutex_init(&pcond->c_lock);
87 *cond = pcond;
88 }
89 /* Return the completion status: */
90 return (rval);
91}
92
93static int
94init_static(struct pthread *thread, pthread_cond_t *cond)

--- 18 unchanged lines hidden (view full) ---

113
114 *cond = NULL;
115 return (cond_init(cond, cond_attr));
116}
117
118int
119_pthread_cond_destroy(pthread_cond_t *cond)
120{
84 *cond = pcond;
85 }
86 /* Return the completion status: */
87 return (rval);
88}
89
90static int
91init_static(struct pthread *thread, pthread_cond_t *cond)

--- 18 unchanged lines hidden (view full) ---

110
111 *cond = NULL;
112 return (cond_init(cond, cond_attr));
113}
114
115int
116_pthread_cond_destroy(pthread_cond_t *cond)
117{
121 struct pthread_cond *cv;
122 struct pthread *curthread = _get_curthread();
118 struct pthread *curthread = _get_curthread();
119 struct pthread_cond *cv;
123 int rval = 0;
124
125 if (*cond == NULL)
126 rval = EINVAL;
127 else {
120 int rval = 0;
121
122 if (*cond == NULL)
123 rval = EINVAL;
124 else {
125 cv = *cond;
126 THR_UMUTEX_LOCK(curthread, &cv->c_lock);
128 /* Lock the condition variable structure: */
127 /* Lock the condition variable structure: */
129 THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock);
130 if ((*cond)->c_waiters + (*cond)->c_wakeups != 0) {
131 THR_LOCK_RELEASE(curthread, &(*cond)->c_lock);
128 if (cv->c_kerncv.c_has_waiters) {
129 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
132 return (EBUSY);
133 }
130 return (EBUSY);
131 }
134
135 /*
136 * NULL the caller's pointer now that the condition
137 * variable has been destroyed:
138 */
132 /*
133 * NULL the caller's pointer now that the condition
134 * variable has been destroyed:
135 */
139 cv = *cond;
140 *cond = NULL;
136 *cond = NULL;
137 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
141
138
142 /* Unlock the condition variable structure: */
143 THR_LOCK_RELEASE(curthread, &cv->c_lock);
144
145 /* Free the cond lock structure: */
146
147 /*
148 * Free the memory allocated for the condition
149 * variable structure:
150 */
151 free(cv);
152
153 }
154 /* Return the completion status: */
155 return (rval);
156}
157
158struct cond_cancel_info
159{
160 pthread_mutex_t *mutex;
161 pthread_cond_t *cond;
139 /*
140 * Free the memory allocated for the condition
141 * variable structure:
142 */
143 free(cv);
144
145 }
146 /* Return the completion status: */
147 return (rval);
148}
149
150struct cond_cancel_info
151{
152 pthread_mutex_t *mutex;
153 pthread_cond_t *cond;
162 long seqno;
163 int count;
164};
165
166static void
167cond_cancel_handler(void *arg)
168{
169 struct pthread *curthread = _get_curthread();
170 struct cond_cancel_info *info = (struct cond_cancel_info *)arg;
154 int count;
155};
156
157static void
158cond_cancel_handler(void *arg)
159{
160 struct pthread *curthread = _get_curthread();
161 struct cond_cancel_info *info = (struct cond_cancel_info *)arg;
171 pthread_cond_t cv;
162 pthread_cond_t cv;
172
173 cv = *(info->cond);
163
164 cv = *(info->cond);
174 THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
175 if (cv->c_seqno != info->seqno && cv->c_wakeups != 0) {
176 if (cv->c_waiters > 0) {
177 cv->c_seqno++;
178 _thr_umtx_wake(&cv->c_seqno, 1);
179 } else
180 cv->c_wakeups--;
181 } else {
182 cv->c_waiters--;
183 }
184 THR_LOCK_RELEASE(curthread, &cv->c_lock);
185
165 if ((cv->c_lock.m_owner & ~UMUTEX_CONTESTED) == TID(curthread))
166 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
186 _mutex_cv_lock(info->mutex, info->count);
187}
188
189static int
190cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
191 const struct timespec *abstime, int cancel)
192{
193 struct pthread *curthread = _get_curthread();
194 struct timespec ts, ts2, *tsp;
195 struct cond_cancel_info info;
196 pthread_cond_t cv;
167 _mutex_cv_lock(info->mutex, info->count);
168}
169
170static int
171cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
172 const struct timespec *abstime, int cancel)
173{
174 struct pthread *curthread = _get_curthread();
175 struct timespec ts, ts2, *tsp;
176 struct cond_cancel_info info;
177 pthread_cond_t cv;
197 long seq, oldseq;
198 int ret = 0;
199
200 /*
201 * If the condition variable is statically initialized,
202 * perform the dynamic initialization:
203 */
204 if (__predict_false(*cond == NULL &&
205 (ret = init_static(curthread, cond)) != 0))
206 return (ret);
207
208 cv = *cond;
178 int ret = 0;
179
180 /*
181 * If the condition variable is statically initialized,
182 * perform the dynamic initialization:
183 */
184 if (__predict_false(*cond == NULL &&
185 (ret = init_static(curthread, cond)) != 0))
186 return (ret);
187
188 cv = *cond;
209 THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
189 THR_UMUTEX_LOCK(curthread, &cv->c_lock);
210 ret = _mutex_cv_unlock(mutex, &info.count);
211 if (ret) {
190 ret = _mutex_cv_unlock(mutex, &info.count);
191 if (ret) {
212 THR_LOCK_RELEASE(curthread, &cv->c_lock);
192 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
213 return (ret);
214 }
193 return (ret);
194 }
215 oldseq = seq = cv->c_seqno;
195
216 info.mutex = mutex;
217 info.cond = cond;
196 info.mutex = mutex;
197 info.cond = cond;
218 info.seqno = oldseq;
219
198
220 cv->c_waiters++;
221 do {
222 THR_LOCK_RELEASE(curthread, &cv->c_lock);
199 if (abstime != NULL) {
200 clock_gettime(cv->c_clockid, &ts);
201 TIMESPEC_SUB(&ts2, abstime, &ts);
202 tsp = &ts2;
203 } else
204 tsp = NULL;
223
205
224 if (abstime != NULL) {
225 clock_gettime(cv->c_clockid, &ts);
226 TIMESPEC_SUB(&ts2, abstime, &ts);
227 tsp = &ts2;
228 } else
229 tsp = NULL;
230
231 if (cancel) {
232 THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info);
233 _thr_cancel_enter(curthread);
234 ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp);
235 _thr_cancel_leave(curthread);
236 THR_CLEANUP_POP(curthread, 0);
237 } else {
238 ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp);
239 }
240
241 THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
242 seq = cv->c_seqno;
243 if (abstime != NULL && ret == ETIMEDOUT)
244 break;
245
246 /*
247 * loop if we have never been told to wake up
248 * or we lost a race.
249 */
250 } while (seq == oldseq || cv->c_wakeups == 0);
251
252 if (seq != oldseq && cv->c_wakeups != 0) {
253 cv->c_wakeups--;
254 ret = 0;
206 if (cancel) {
207 THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info);
208 _thr_cancel_enter_defer(curthread);
209 ret = _thr_ucond_wait(&cv->c_kerncv, &cv->c_lock, tsp, 1);
210 _thr_cancel_leave_defer(curthread, ret);
211 THR_CLEANUP_POP(curthread, 0);
255 } else {
212 } else {
256 cv->c_waiters--;
213 ret = _thr_ucond_wait(&cv->c_kerncv, &cv->c_lock, tsp, 0);
257 }
214 }
258 THR_LOCK_RELEASE(curthread, &cv->c_lock);
215 if (ret == EINTR)
216 ret = 0;
259 _mutex_cv_lock(mutex, info.count);
260 return (ret);
261}
262
263int
264_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
265{
266

--- 31 unchanged lines hidden (view full) ---

298 return (cond_wait_common(cond, mutex, abstime, 1));
299}
300
301static int
302cond_signal_common(pthread_cond_t *cond, int broadcast)
303{
304 struct pthread *curthread = _get_curthread();
305 pthread_cond_t cv;
217 _mutex_cv_lock(mutex, info.count);
218 return (ret);
219}
220
221int
222_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
223{
224

--- 31 unchanged lines hidden (view full) ---

256 return (cond_wait_common(cond, mutex, abstime, 1));
257}
258
259static int
260cond_signal_common(pthread_cond_t *cond, int broadcast)
261{
262 struct pthread *curthread = _get_curthread();
263 pthread_cond_t cv;
306 int ret = 0, oldwaiters;
264 int ret = 0;
307
308 /*
309 * If the condition variable is statically initialized, perform dynamic
310 * initialization.
311 */
312 if (__predict_false(*cond == NULL &&
313 (ret = init_static(curthread, cond)) != 0))
314 return (ret);
315
316 cv = *cond;
265
266 /*
267 * If the condition variable is statically initialized, perform dynamic
268 * initialization.
269 */
270 if (__predict_false(*cond == NULL &&
271 (ret = init_static(curthread, cond)) != 0))
272 return (ret);
273
274 cv = *cond;
317 /* Lock the condition variable structure. */
318 THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
319 if (cv->c_waiters) {
320 if (!broadcast) {
321 cv->c_wakeups++;
322 cv->c_waiters--;
323 cv->c_seqno++;
324 _thr_umtx_wake(&cv->c_seqno, 1);
325 } else {
326 oldwaiters = cv->c_waiters;
327 cv->c_wakeups += cv->c_waiters;
328 cv->c_waiters = 0;
329 cv->c_seqno++;
330 _thr_umtx_wake(&cv->c_seqno, oldwaiters);
331 }
275 THR_UMUTEX_LOCK(curthread, &cv->c_lock);
276 if (cv->c_kerncv.c_has_waiters) {
277 if (!broadcast)
278 ret = _thr_ucond_signal(&cv->c_kerncv);
279 else
280 ret = _thr_ucond_broadcast(&cv->c_kerncv);
332 }
281 }
333 THR_LOCK_RELEASE(curthread, &cv->c_lock);
282 THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
334 return (ret);
335}
336
337int
338_pthread_cond_signal(pthread_cond_t * cond)
339{
340
341 return (cond_signal_common(cond, 0));
342}
343
344int
345_pthread_cond_broadcast(pthread_cond_t * cond)
346{
347
348 return (cond_signal_common(cond, 1));
349}
283 return (ret);
284}
285
286int
287_pthread_cond_signal(pthread_cond_t * cond)
288{
289
290 return (cond_signal_common(cond, 0));
291}
292
293int
294_pthread_cond_broadcast(pthread_cond_t * cond)
295{
296
297 return (cond_signal_common(cond, 1));
298}