Deleted Added
full compact
thr_cond.c (127566) thr_cond.c (129484)
1/*
2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
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

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

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
1/*
2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
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

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

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 127566 2004-03-29 11:24:02Z mtm $
32 * $FreeBSD: head/lib/libthr/thread/thr_cond.c 129484 2004-05-20 12:06:16Z mtm $
33 */
34#include <stdlib.h>
35#include <errno.h>
36#include <string.h>
37#include <pthread.h>
38#include "thr_private.h"
39
40/*

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

195 return (cond_wait_common(cond, mutex, abstime));
196}
197
198static int
199cond_wait_common(pthread_cond_t * cond, pthread_mutex_t * mutex,
200 const struct timespec * abstime)
201{
202 int rval = 0;
33 */
34#include <stdlib.h>
35#include <errno.h>
36#include <string.h>
37#include <pthread.h>
38#include "thr_private.h"
39
40/*

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

195 return (cond_wait_common(cond, mutex, abstime));
196}
197
198static int
199cond_wait_common(pthread_cond_t * cond, pthread_mutex_t * mutex,
200 const struct timespec * abstime)
201{
202 int rval = 0;
203 int done = 0;
204 int seqno;
205 int mtxrval;
206
207
203 int mtxrval;
204
205
208 _thread_enter_cancellation_point();
209
210 if (cond == NULL)
211 return (EINVAL);
212 /*
213 * If the condition variable is statically initialized, perform dynamic
214 * initialization.
215 */
216 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0)
217 return (rval);
218
206 if (cond == NULL)
207 return (EINVAL);
208 /*
209 * If the condition variable is statically initialized, perform dynamic
210 * initialization.
211 */
212 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0)
213 return (rval);
214
215 if ((*cond)->c_type != COND_TYPE_FAST)
216 return (EINVAL);
219
220 COND_LOCK(*cond);
221
222 /*
223 * If the condvar was statically allocated, properly
224 * initialize the tail queue.
225 */
226 if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) {
227 TAILQ_INIT(&(*cond)->c_queue);
228 (*cond)->c_flags |= COND_FLAGS_INITED;
229 }
230
217
218 COND_LOCK(*cond);
219
220 /*
221 * If the condvar was statically allocated, properly
222 * initialize the tail queue.
223 */
224 if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) {
225 TAILQ_INIT(&(*cond)->c_queue);
226 (*cond)->c_flags |= COND_FLAGS_INITED;
227 }
228
231 /* Process according to condition variable type. */
229 if ((mutex == NULL) || (((*cond)->c_mutex != NULL) &&
230 ((*cond)->c_mutex != *mutex))) {
231 COND_UNLOCK(*cond);
232 return (EINVAL);
233 }
234 /* Remember the mutex */
235 (*cond)->c_mutex = *mutex;
232
236
233 switch ((*cond)->c_type) {
234 /* Fast condition variable: */
235 case COND_TYPE_FAST:
236 if ((mutex == NULL) || (((*cond)->c_mutex != NULL) &&
237 ((*cond)->c_mutex != *mutex))) {
238 COND_UNLOCK(*cond);
239 rval = EINVAL;
240 break;
241 }
242 /* Remember the mutex */
243 (*cond)->c_mutex = *mutex;
244
245 if ((rval = _mutex_cv_unlock(mutex)) != 0) {
246 if (rval == -1){
247 printf("foo");
248 fflush(stdout);
249 abort();
250 }
251
252 COND_UNLOCK(*cond);
253 break;
237 _thread_enter_cancellation_point();
238 if ((rval = _mutex_cv_unlock(mutex)) != 0) {
239 if (rval == -1){
240 printf("mutex unlock by condvar failed!");
241 fflush(stdout);
242 abort();
254 }
243 }
244 _thread_leave_cancellation_point();
245 COND_UNLOCK(*cond);
246 return (rval);
247 }
255
248
256 /*
257 * We need to protect the queue operations. It also
258 * protects c_seqno and the pthread flag fields. This is
259 * dropped before calling _thread_suspend() and reaquired
260 * when we return.
261 */
249 /*
250 * We need to protect the queue operations. It also
251 * protects the pthread flag field. This is
252 * dropped before calling _thread_suspend() and reaquired
253 * when we return.
254 */
255 PTHREAD_LOCK(curthread);
262
256
263 _thread_critical_enter(curthread);
264 /*
265 * c_seqno is protected.
266 */
267 seqno = (*cond)->c_seqno;
268
269 do {
257 /*
258 * Queue the running thread on the condition
259 * variable and wait to be signaled.
260 */
261 cond_queue_enq(*cond, curthread);
262 do {
263 PTHREAD_UNLOCK(curthread);
264 COND_UNLOCK(*cond);
265 if (curthread->cancellation == CS_PENDING) {
270 /*
266 /*
271 * Queue the running thread on the condition
272 * variable.
267 * Posix says we must lock the mutex
268 * even if we're being canceled.
273 */
269 */
274 cond_queue_enq(*cond, curthread);
275
276 if (curthread->cancelflags & PTHREAD_CANCELLING) {
277 /*
278 * POSIX Says that we must relock the mutex
279 * even if we're being canceled.
280 */
281 _thread_critical_exit(curthread);
282 COND_UNLOCK(*cond);
283 _mutex_cv_lock(mutex);
284 pthread_testcancel();
285 PANIC("Shouldn't have come back.");
286 }
287
288 PTHREAD_SET_STATE(curthread, PS_COND_WAIT);
289 _thread_critical_exit(curthread);
290 COND_UNLOCK(*cond);
291 rval = _thread_suspend(curthread, (struct timespec *)abstime);
292 if (rval != 0 && rval != ETIMEDOUT && rval != EINTR) {
293 printf("foo");
294 fflush(stdout);
295 abort();
296 }
297 COND_LOCK(*cond);
298 _thread_critical_enter(curthread);
299
300 done = (seqno != (*cond)->c_seqno);
301
270 _mutex_cv_lock(mutex);
271 _thread_leave_cancellation_point();
272 PANIC("Shouldn't have come back.");
273 }
274 rval = _thread_suspend(curthread, (struct timespec *)abstime);
275 if (rval != 0 && rval != ETIMEDOUT && rval != EINTR) {
276 printf("thread suspend returned an invalid value");
277 fflush(stdout);
278 abort();
279 }
280 COND_LOCK(*cond);
281 PTHREAD_LOCK(curthread);
282 if (rval == ETIMEDOUT) {
302 /*
283 /*
303 * If we timed out, this will remove us from the
304 * queue. Otherwise, if we were signaled it does
305 * nothing because this thread won't be on the queue.
284 * Condition may have been signaled between the
285 * time the thread timed out and locked the condvar.
286 * If it wasn't, manually remove it from the queue.
306 */
287 */
307 cond_queue_remove(*cond, curthread);
308
309 } while ((done == 0) && (rval == 0));
310 /*
311 * If we timed out someone still may have signaled us
312 * before we got a chance to run again. We check for
313 * this by looking to see if our state is RUNNING.
314 */
315 if (rval == ETIMEDOUT) {
316 if (curthread->state != PS_RUNNING) {
317 PTHREAD_SET_STATE(curthread, PS_RUNNING);
318 } else
288 if ((curthread->flags & PTHREAD_FLAGS_IN_CONDQ) == 0)
319 rval = 0;
289 rval = 0;
290 else
291 cond_queue_remove(*cond, curthread);
320 }
292 }
321 _thread_critical_exit(curthread);
322 COND_UNLOCK(*cond);
293 } while ((curthread->flags & PTHREAD_FLAGS_IN_CONDQ) != 0);
323
294
324 mtxrval = _mutex_cv_lock(mutex);
295 PTHREAD_UNLOCK(curthread);
296 COND_UNLOCK(*cond);
297 mtxrval = _mutex_cv_lock(mutex);
325
298
326 /*
327 * If the mutex failed return that error, otherwise we're
328 * returning ETIMEDOUT.
329 */
330 if (mtxrval == -1) {
331 printf("foo");
332 fflush(stdout);
333 abort();
334 }
335 if (mtxrval != 0)
336 rval = mtxrval;
337
338 break;
339
340 /* Trap invalid condition variable types: */
341 default:
342 COND_UNLOCK(*cond);
343 rval = EINVAL;
344 break;
299 /* If the mutex failed return that error. */
300 if (mtxrval == -1) {
301 printf("mutex lock from condvar failed!");
302 fflush(stdout);
303 abort();
345 }
304 }
305 if (mtxrval != 0)
306 rval = mtxrval;
346
347 _thread_leave_cancellation_point();
307
308 _thread_leave_cancellation_point();
348
349 return (rval);
350}
351
352int
353_pthread_cond_signal(pthread_cond_t * cond)
354{
355 return (cond_signal(cond, 0));
356}

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

371 return (EINVAL);
372 /*
373 * If the condition variable is statically initialized, perform dynamic
374 * initialization.
375 */
376 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0)
377 return (rval);
378
309 return (rval);
310}
311
312int
313_pthread_cond_signal(pthread_cond_t * cond)
314{
315 return (cond_signal(cond, 0));
316}

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

331 return (EINVAL);
332 /*
333 * If the condition variable is statically initialized, perform dynamic
334 * initialization.
335 */
336 if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0)
337 return (rval);
338
339 if ((*cond)->c_type != COND_TYPE_FAST)
340 return (EINVAL);
379 COND_LOCK(*cond);
380
341 COND_LOCK(*cond);
342
381 /* Process according to condition variable type: */
382 switch ((*cond)->c_type) {
383 /* Fast condition variable: */
384 case COND_TYPE_FAST:
385 (*cond)->c_seqno++;
386
343 /*
344 * Enter a loop to bring all (or only one) threads off the
345 * condition queue:
346 */
347 do {
387 /*
348 /*
388 * Enter a loop to bring all (or only one) threads off the
389 * condition queue:
349 * Wake up the signaled thread. It will be returned
350 * to us locked.
390 */
351 */
391 do {
392 /*
393 * Wake up the signaled thread. It will be returned
394 * to us locked, and with signals disabled.
395 */
396 if ((pthread = cond_queue_deq(*cond)) != NULL) {
397 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
398 _thread_critical_exit(pthread);
399 }
400 } while (broadcast && pthread != NULL);
352 if ((pthread = cond_queue_deq(*cond)) != NULL) {
353 PTHREAD_WAKE(pthread);
354 PTHREAD_UNLOCK(pthread);
355 }
356 } while (broadcast && pthread != NULL);
401
357
402 break;
403
404 /* Trap invalid condition variable types: */
405 default:
406 rval = EINVAL;
407 break;
408 }
409
410 COND_UNLOCK(*cond);
358 COND_UNLOCK(*cond);
411
412
413 return (rval);
414}
415
416void
417_cond_wait_backout(pthread_t pthread)
418{
419 pthread_cond_t cond;
420

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

438 * descending priority order.
439 */
440static pthread_t
441cond_queue_deq(pthread_cond_t cond)
442{
443 pthread_t pthread;
444
445 while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) {
359 return (rval);
360}
361
362void
363_cond_wait_backout(pthread_t pthread)
364{
365 pthread_cond_t cond;
366

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

384 * descending priority order.
385 */
386static pthread_t
387cond_queue_deq(pthread_cond_t cond)
388{
389 pthread_t pthread;
390
391 while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) {
446 _thread_critical_enter(pthread);
447 TAILQ_REMOVE(&cond->c_queue, pthread, sqe);
392 PTHREAD_LOCK(pthread);
448 cond_queue_remove(cond, pthread);
393 cond_queue_remove(cond, pthread);
449 if ((pthread->cancelflags & PTHREAD_CANCELLING) == 0 &&
450 pthread->state == PS_COND_WAIT)
451 /*
452 * Only exit the loop when we find a thread
453 * that hasn't timed out or been canceled;
454 * those threads are already running and don't
455 * need their run state changed.
456 */
394
395 /*
396 * Only exit the loop when we find a thread
397 * that hasn't been canceled.
398 */
399 if (pthread->cancellation == CS_NULL)
457 break;
458 else
400 break;
401 else
459 _thread_critical_exit(pthread);
402 PTHREAD_UNLOCK(pthread);
460 }
461
462 return(pthread);
463}
464
465/*
466 * Remove a waiting thread from a condition queue in descending priority
467 * order.

--- 66 unchanged lines hidden ---
403 }
404
405 return(pthread);
406}
407
408/*
409 * Remove a waiting thread from a condition queue in descending priority
410 * order.

--- 66 unchanged lines hidden ---