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
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31
32#include "namespace.h"
33#include <stdlib.h>
34#include <errno.h>
35#include <string.h>
36#include <pthread.h>
37#include "un-namespace.h"
38#include "thr_private.h"
39
40#define	THR_IN_CONDQ(thr)	(((thr)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
41#define	THR_CONDQ_SET(thr)	(thr)->sflags |= THR_FLAGS_IN_SYNCQ
42#define	THR_CONDQ_CLEAR(thr)	(thr)->sflags &= ~THR_FLAGS_IN_SYNCQ
43
44/*
45 * Prototypes
46 */
47static inline struct pthread	*cond_queue_deq(pthread_cond_t);
48static inline void		cond_queue_remove(pthread_cond_t, pthread_t);
49static inline void		cond_queue_enq(pthread_cond_t, pthread_t);
50static void			cond_wait_backout(void *);
51static inline void		check_continuation(struct pthread *,
52				    struct pthread_cond *, pthread_mutex_t *);
53
54int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
55int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
56		       const struct timespec *abstime);
57
58/*
59 * Double underscore versions are cancellation points.  Single underscore
60 * versions are not and are provided for libc internal usage (which
61 * shouldn't introduce cancellation points).
62 */
63__weak_reference(__pthread_cond_wait, pthread_cond_wait);
64__weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait);
65
66__weak_reference(_pthread_cond_init, pthread_cond_init);
67__weak_reference(_pthread_cond_destroy, pthread_cond_destroy);
68__weak_reference(_pthread_cond_signal, pthread_cond_signal);
69__weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast);
70
71
72int
73_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
74{
75	enum pthread_cond_type type;
76	pthread_cond_t	pcond;
77	int		flags;
78	int             rval = 0;
79
80	if (cond == NULL)
81		rval = EINVAL;
82	else {
83		/*
84		 * Check if a pointer to a condition variable attribute
85		 * structure was passed by the caller:
86		 */
87		if (cond_attr != NULL && *cond_attr != NULL) {
88			/* Default to a fast condition variable: */
89			type = (*cond_attr)->c_type;
90			flags = (*cond_attr)->c_flags;
91		} else {
92			/* Default to a fast condition variable: */
93			type = COND_TYPE_FAST;
94			flags = 0;
95		}
96
97		/* Process according to condition variable type: */
98		switch (type) {
99		/* Fast condition variable: */
100		case COND_TYPE_FAST:
101			/* Nothing to do here. */
102			break;
103
104		/* Trap invalid condition variable types: */
105		default:
106			/* Return an invalid argument error: */
107			rval = EINVAL;
108			break;
109		}
110
111		/* Check for no errors: */
112		if (rval == 0) {
113			if ((pcond = (pthread_cond_t)
114			    malloc(sizeof(struct pthread_cond))) == NULL) {
115				rval = ENOMEM;
116			} else if (_lock_init(&pcond->c_lock, LCK_ADAPTIVE,
117			    _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) {
118				free(pcond);
119				rval = ENOMEM;
120			} else {
121				/*
122				 * Initialise the condition variable
123				 * structure:
124				 */
125				TAILQ_INIT(&pcond->c_queue);
126				pcond->c_flags = COND_FLAGS_INITED;
127				pcond->c_type = type;
128				pcond->c_mutex = NULL;
129				pcond->c_seqno = 0;
130				*cond = pcond;
131			}
132		}
133	}
134	/* Return the completion status: */
135	return (rval);
136}
137
138int
139_pthread_cond_destroy(pthread_cond_t *cond)
140{
141	struct pthread_cond	*cv;
142	struct pthread		*curthread = _get_curthread();
143	int			rval = 0;
144
145	if (cond == NULL || *cond == NULL)
146		rval = EINVAL;
147	else {
148		/* Lock the condition variable structure: */
149		THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock);
150
151		/*
152		 * NULL the caller's pointer now that the condition
153		 * variable has been destroyed:
154		 */
155		cv = *cond;
156		*cond = NULL;
157
158		/* Unlock the condition variable structure: */
159		THR_LOCK_RELEASE(curthread, &cv->c_lock);
160
161		/* Free the cond lock structure: */
162		_lock_destroy(&cv->c_lock);
163
164		/*
165		 * Free the memory allocated for the condition
166		 * variable structure:
167		 */
168		free(cv);
169
170	}
171	/* Return the completion status: */
172	return (rval);
173}
174
175int
176_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
177{
178	struct pthread	*curthread = _get_curthread();
179	int	rval = 0;
180	int	done = 0;
181	int	mutex_locked = 1;
182	int	seqno;
183
184	if (cond == NULL)
185		return (EINVAL);
186
187	/*
188	 * If the condition variable is statically initialized,
189	 * perform the dynamic initialization:
190	 */
191	if (*cond == NULL &&
192	    (rval = _pthread_cond_init(cond, NULL)) != 0)
193		return (rval);
194
195	if (!_kse_isthreaded())
196		_kse_setthreaded(1);
197
198	/*
199	 * Enter a loop waiting for a condition signal or broadcast
200	 * to wake up this thread.  A loop is needed in case the waiting
201	 * thread is interrupted by a signal to execute a signal handler.
202	 * It is not (currently) possible to remain in the waiting queue
203	 * while running a handler.  Instead, the thread is interrupted
204	 * and backed out of the waiting queue prior to executing the
205	 * signal handler.
206	 */
207
208	/* Lock the condition variable structure: */
209	THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock);
210	seqno = (*cond)->c_seqno;
211	do {
212		/*
213		 * If the condvar was statically allocated, properly
214		 * initialize the tail queue.
215		 */
216		if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) {
217			TAILQ_INIT(&(*cond)->c_queue);
218			(*cond)->c_flags |= COND_FLAGS_INITED;
219		}
220
221		/* Process according to condition variable type: */
222		switch ((*cond)->c_type) {
223		/* Fast condition variable: */
224		case COND_TYPE_FAST:
225			if ((mutex == NULL) || (((*cond)->c_mutex != NULL) &&
226			    ((*cond)->c_mutex != *mutex))) {
227				/* Return invalid argument error: */
228				rval = EINVAL;
229			} else {
230				/* Reset the timeout and interrupted flags: */
231				curthread->timeout = 0;
232				curthread->interrupted = 0;
233
234				/*
235				 * Queue the running thread for the condition
236				 * variable:
237				 */
238				cond_queue_enq(*cond, curthread);
239
240				/* Wait forever: */
241				curthread->wakeup_time.tv_sec = -1;
242
243				/* Unlock the mutex: */
244				if (mutex_locked &&
245				    ((rval = _mutex_cv_unlock(mutex)) != 0)) {
246					/*
247					 * Cannot unlock the mutex, so remove
248					 * the running thread from the condition
249					 * variable queue:
250					 */
251					cond_queue_remove(*cond, curthread);
252				}
253				else {
254					/* Remember the mutex: */
255					(*cond)->c_mutex = *mutex;
256
257					/*
258					 * Don't unlock the mutex the next
259					 * time through the loop (if the
260					 * thread has to be requeued after
261					 * handling a signal).
262					 */
263					mutex_locked = 0;
264
265					/*
266					 * This thread is active and is in a
267					 * critical region (holding the cv
268					 * lock); we should be able to safely
269					 * set the state.
270					 */
271					THR_SCHED_LOCK(curthread, curthread);
272					THR_SET_STATE(curthread, PS_COND_WAIT);
273
274					/* Remember the CV: */
275					curthread->data.cond = *cond;
276					curthread->sigbackout = cond_wait_backout;
277					THR_SCHED_UNLOCK(curthread, curthread);
278
279					/* Unlock the CV structure: */
280					THR_LOCK_RELEASE(curthread,
281					    &(*cond)->c_lock);
282
283					/* Schedule the next thread: */
284					_thr_sched_switch(curthread);
285
286					/*
287					 * XXX - This really isn't a good check
288					 * since there can be more than one
289					 * thread waiting on the CV.  Signals
290					 * sent to threads waiting on mutexes
291					 * or CVs should really be deferred
292					 * until the threads are no longer
293					 * waiting, but POSIX says that signals
294					 * should be sent "as soon as possible".
295					 */
296					done = (seqno != (*cond)->c_seqno);
297					if (done && !THR_IN_CONDQ(curthread)) {
298						/*
299						 * The thread is dequeued, so
300						 * it is safe to clear these.
301						 */
302						curthread->data.cond = NULL;
303						curthread->sigbackout = NULL;
304						check_continuation(curthread,
305						    NULL, mutex);
306						return (_mutex_cv_lock(mutex));
307					}
308
309					/* Relock the CV structure: */
310					THR_LOCK_ACQUIRE(curthread,
311					    &(*cond)->c_lock);
312
313					/*
314					 * Clear these after taking the lock to
315					 * prevent a race condition where a
316					 * signal can arrive before dequeueing
317					 * the thread.
318					 */
319					curthread->data.cond = NULL;
320					curthread->sigbackout = NULL;
321					done = (seqno != (*cond)->c_seqno);
322
323					if (THR_IN_CONDQ(curthread)) {
324						cond_queue_remove(*cond,
325						    curthread);
326
327						/* Check for no more waiters: */
328						if (TAILQ_EMPTY(&(*cond)->c_queue))
329							(*cond)->c_mutex = NULL;
330					}
331				}
332			}
333			break;
334
335		/* Trap invalid condition variable types: */
336		default:
337			/* Return an invalid argument error: */
338			rval = EINVAL;
339			break;
340		}
341
342		check_continuation(curthread, *cond,
343		    mutex_locked ? NULL : mutex);
344	} while ((done == 0) && (rval == 0));
345
346	/* Unlock the condition variable structure: */
347	THR_LOCK_RELEASE(curthread, &(*cond)->c_lock);
348
349	if (mutex_locked == 0)
350		_mutex_cv_lock(mutex);
351
352	/* Return the completion status: */
353	return (rval);
354}
355
356__strong_reference(_pthread_cond_wait, _thr_cond_wait);
357
358int
359__pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
360{
361	struct pthread *curthread = _get_curthread();
362	int ret;
363
364	_thr_cancel_enter(curthread);
365	ret = _pthread_cond_wait(cond, mutex);
366	_thr_cancel_leave(curthread, 1);
367	return (ret);
368}
369
370int
371_pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
372		       const struct timespec * abstime)
373{
374	struct pthread	*curthread = _get_curthread();
375	int	rval = 0;
376	int	done = 0;
377	int	mutex_locked = 1;
378	int	seqno;
379
380	THR_ASSERT(curthread->locklevel == 0,
381	    "cv_timedwait: locklevel is not zero!");
382
383	if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
384	    abstime->tv_nsec >= 1000000000)
385		return (EINVAL);
386	/*
387	 * If the condition variable is statically initialized, perform dynamic
388	 * initialization.
389	 */
390	if (*cond == NULL && (rval = _pthread_cond_init(cond, NULL)) != 0)
391		return (rval);
392
393	if (!_kse_isthreaded())
394		_kse_setthreaded(1);
395
396	/*
397	 * Enter a loop waiting for a condition signal or broadcast
398	 * to wake up this thread.  A loop is needed in case the waiting
399	 * thread is interrupted by a signal to execute a signal handler.
400	 * It is not (currently) possible to remain in the waiting queue
401	 * while running a handler.  Instead, the thread is interrupted
402	 * and backed out of the waiting queue prior to executing the
403	 * signal handler.
404	 */
405
406	/* Lock the condition variable structure: */
407	THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock);
408	seqno = (*cond)->c_seqno;
409	do {
410		/*
411		 * If the condvar was statically allocated, properly
412		 * initialize the tail queue.
413		 */
414		if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) {
415			TAILQ_INIT(&(*cond)->c_queue);
416			(*cond)->c_flags |= COND_FLAGS_INITED;
417		}
418
419		/* Process according to condition variable type: */
420		switch ((*cond)->c_type) {
421		/* Fast condition variable: */
422		case COND_TYPE_FAST:
423			if ((mutex == NULL) || (((*cond)->c_mutex != NULL) &&
424			    ((*cond)->c_mutex != *mutex))) {
425				/* Return invalid argument error: */
426				rval = EINVAL;
427			} else {
428				/* Reset the timeout and interrupted flags: */
429				curthread->timeout = 0;
430				curthread->interrupted = 0;
431
432				/*
433				 * Queue the running thread for the condition
434				 * variable:
435				 */
436				cond_queue_enq(*cond, curthread);
437
438				/* Unlock the mutex: */
439				if (mutex_locked &&
440				   ((rval = _mutex_cv_unlock(mutex)) != 0)) {
441					/*
442					 * Cannot unlock the mutex; remove the
443					 * running thread from the condition
444					 * variable queue:
445					 */
446					cond_queue_remove(*cond, curthread);
447				} else {
448					/* Remember the mutex: */
449					(*cond)->c_mutex = *mutex;
450
451					/*
452					 * Don't unlock the mutex the next
453					 * time through the loop (if the
454					 * thread has to be requeued after
455					 * handling a signal).
456					 */
457					mutex_locked = 0;
458
459					/*
460					 * This thread is active and is in a
461					 * critical region (holding the cv
462					 * lock); we should be able to safely
463					 * set the state.
464					 */
465					THR_SCHED_LOCK(curthread, curthread);
466					/* Set the wakeup time: */
467					curthread->wakeup_time.tv_sec =
468					    abstime->tv_sec;
469					curthread->wakeup_time.tv_nsec =
470					    abstime->tv_nsec;
471					THR_SET_STATE(curthread, PS_COND_WAIT);
472
473					/* Remember the CV: */
474					curthread->data.cond = *cond;
475					curthread->sigbackout = cond_wait_backout;
476					THR_SCHED_UNLOCK(curthread, curthread);
477
478					/* Unlock the CV structure: */
479					THR_LOCK_RELEASE(curthread,
480					    &(*cond)->c_lock);
481
482					/* Schedule the next thread: */
483					_thr_sched_switch(curthread);
484
485					/*
486					 * XXX - This really isn't a good check
487					 * since there can be more than one
488					 * thread waiting on the CV.  Signals
489					 * sent to threads waiting on mutexes
490					 * or CVs should really be deferred
491					 * until the threads are no longer
492					 * waiting, but POSIX says that signals
493					 * should be sent "as soon as possible".
494					 */
495					done = (seqno != (*cond)->c_seqno);
496					if (done && !THR_IN_CONDQ(curthread)) {
497						/*
498						 * The thread is dequeued, so
499						 * it is safe to clear these.
500						 */
501						curthread->data.cond = NULL;
502						curthread->sigbackout = NULL;
503						check_continuation(curthread,
504						    NULL, mutex);
505						return (_mutex_cv_lock(mutex));
506					}
507
508					/* Relock the CV structure: */
509					THR_LOCK_ACQUIRE(curthread,
510					    &(*cond)->c_lock);
511
512					/*
513					 * Clear these after taking the lock to
514					 * prevent a race condition where a
515					 * signal can arrive before dequeueing
516					 * the thread.
517					 */
518					curthread->data.cond = NULL;
519					curthread->sigbackout = NULL;
520
521					done = (seqno != (*cond)->c_seqno);
522
523					if (THR_IN_CONDQ(curthread)) {
524						cond_queue_remove(*cond,
525						    curthread);
526
527						/* Check for no more waiters: */
528						if (TAILQ_EMPTY(&(*cond)->c_queue))
529							(*cond)->c_mutex = NULL;
530					}
531
532					if (curthread->timeout != 0) {
533						/* The wait timedout. */
534						rval = ETIMEDOUT;
535					}
536				}
537			}
538			break;
539
540		/* Trap invalid condition variable types: */
541		default:
542			/* Return an invalid argument error: */
543			rval = EINVAL;
544			break;
545		}
546
547		check_continuation(curthread, *cond,
548		    mutex_locked ? NULL : mutex);
549	} while ((done == 0) && (rval == 0));
550
551	/* Unlock the condition variable structure: */
552	THR_LOCK_RELEASE(curthread, &(*cond)->c_lock);
553
554	if (mutex_locked == 0)
555		_mutex_cv_lock(mutex);
556
557	/* Return the completion status: */
558	return (rval);
559}
560
561int
562__pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
563		       const struct timespec *abstime)
564{
565	struct pthread *curthread = _get_curthread();
566	int ret;
567
568	_thr_cancel_enter(curthread);
569	ret = _pthread_cond_timedwait(cond, mutex, abstime);
570	_thr_cancel_leave(curthread, 1);
571	return (ret);
572}
573
574
575int
576_pthread_cond_signal(pthread_cond_t * cond)
577{
578	struct pthread	*curthread = _get_curthread();
579	struct pthread	*pthread;
580	struct kse_mailbox *kmbx;
581	int		rval = 0;
582
583	THR_ASSERT(curthread->locklevel == 0,
584	    "cv_timedwait: locklevel is not zero!");
585	if (cond == NULL)
586		rval = EINVAL;
587       /*
588        * If the condition variable is statically initialized, perform dynamic
589        * initialization.
590        */
591	else if (*cond != NULL || (rval = _pthread_cond_init(cond, NULL)) == 0) {
592		/* Lock the condition variable structure: */
593		THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock);
594
595		/* Process according to condition variable type: */
596		switch ((*cond)->c_type) {
597		/* Fast condition variable: */
598		case COND_TYPE_FAST:
599			/* Increment the sequence number: */
600			(*cond)->c_seqno++;
601
602			/*
603			 * Wakeups have to be done with the CV lock held;
604			 * otherwise there is a race condition where the
605			 * thread can timeout, run on another KSE, and enter
606			 * another blocking state (including blocking on a CV).
607			 */
608			if ((pthread = TAILQ_FIRST(&(*cond)->c_queue))
609			    != NULL) {
610				THR_SCHED_LOCK(curthread, pthread);
611				cond_queue_remove(*cond, pthread);
612				pthread->sigbackout = NULL;
613				if ((pthread->kseg == curthread->kseg) &&
614				    (pthread->active_priority >
615				    curthread->active_priority))
616					curthread->critical_yield = 1;
617				kmbx = _thr_setrunnable_unlocked(pthread);
618				THR_SCHED_UNLOCK(curthread, pthread);
619				if (kmbx != NULL)
620					kse_wakeup(kmbx);
621			}
622			/* Check for no more waiters: */
623			if (TAILQ_EMPTY(&(*cond)->c_queue))
624				(*cond)->c_mutex = NULL;
625			break;
626
627		/* Trap invalid condition variable types: */
628		default:
629			/* Return an invalid argument error: */
630			rval = EINVAL;
631			break;
632		}
633
634		/* Unlock the condition variable structure: */
635		THR_LOCK_RELEASE(curthread, &(*cond)->c_lock);
636	}
637
638	/* Return the completion status: */
639	return (rval);
640}
641
642__strong_reference(_pthread_cond_signal, _thr_cond_signal);
643
644int
645_pthread_cond_broadcast(pthread_cond_t * cond)
646{
647	struct pthread	*curthread = _get_curthread();
648	struct pthread	*pthread;
649	struct kse_mailbox *kmbx;
650	int		rval = 0;
651
652	THR_ASSERT(curthread->locklevel == 0,
653	    "cv_timedwait: locklevel is not zero!");
654	if (cond == NULL)
655		rval = EINVAL;
656       /*
657        * If the condition variable is statically initialized, perform dynamic
658        * initialization.
659        */
660	else if (*cond != NULL || (rval = _pthread_cond_init(cond, NULL)) == 0) {
661		/* Lock the condition variable structure: */
662		THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock);
663
664		/* Process according to condition variable type: */
665		switch ((*cond)->c_type) {
666		/* Fast condition variable: */
667		case COND_TYPE_FAST:
668			/* Increment the sequence number: */
669			(*cond)->c_seqno++;
670
671			/*
672			 * Enter a loop to bring all threads off the
673			 * condition queue:
674			 */
675			while ((pthread = TAILQ_FIRST(&(*cond)->c_queue))
676			    != NULL) {
677				THR_SCHED_LOCK(curthread, pthread);
678				cond_queue_remove(*cond, pthread);
679				pthread->sigbackout = NULL;
680				if ((pthread->kseg == curthread->kseg) &&
681				    (pthread->active_priority >
682				    curthread->active_priority))
683					curthread->critical_yield = 1;
684				kmbx = _thr_setrunnable_unlocked(pthread);
685				THR_SCHED_UNLOCK(curthread, pthread);
686				if (kmbx != NULL)
687					kse_wakeup(kmbx);
688			}
689
690			/* There are no more waiting threads: */
691			(*cond)->c_mutex = NULL;
692			break;
693
694		/* Trap invalid condition variable types: */
695		default:
696			/* Return an invalid argument error: */
697			rval = EINVAL;
698			break;
699		}
700
701		/* Unlock the condition variable structure: */
702		THR_LOCK_RELEASE(curthread, &(*cond)->c_lock);
703	}
704
705	/* Return the completion status: */
706	return (rval);
707}
708
709__strong_reference(_pthread_cond_broadcast, _thr_cond_broadcast);
710
711static inline void
712check_continuation(struct pthread *curthread, struct pthread_cond *cond,
713    pthread_mutex_t *mutex)
714{
715	if ((curthread->interrupted != 0) &&
716	    (curthread->continuation != NULL)) {
717		if (cond != NULL)
718			/* Unlock the condition variable structure: */
719			THR_LOCK_RELEASE(curthread, &cond->c_lock);
720		/*
721		 * Note that even though this thread may have been
722		 * canceled, POSIX requires that the mutex be
723		 * reaquired prior to cancellation.
724		 */
725		if (mutex != NULL)
726			_mutex_cv_lock(mutex);
727		curthread->continuation((void *) curthread);
728		PANIC("continuation returned in pthread_cond_wait.\n");
729	}
730}
731
732static void
733cond_wait_backout(void *arg)
734{
735	struct pthread *curthread = (struct pthread *)arg;
736	pthread_cond_t	cond;
737
738	cond = curthread->data.cond;
739	if (cond != NULL) {
740		/* Lock the condition variable structure: */
741		THR_LOCK_ACQUIRE(curthread, &cond->c_lock);
742
743		/* Process according to condition variable type: */
744		switch (cond->c_type) {
745		/* Fast condition variable: */
746		case COND_TYPE_FAST:
747			cond_queue_remove(cond, curthread);
748
749			/* Check for no more waiters: */
750			if (TAILQ_EMPTY(&cond->c_queue))
751				cond->c_mutex = NULL;
752			break;
753
754		default:
755			break;
756		}
757
758		/* Unlock the condition variable structure: */
759		THR_LOCK_RELEASE(curthread, &cond->c_lock);
760	}
761	/* No need to call this again. */
762	curthread->sigbackout = NULL;
763}
764
765/*
766 * Dequeue a waiting thread from the head of a condition queue in
767 * descending priority order.
768 */
769static inline struct pthread *
770cond_queue_deq(pthread_cond_t cond)
771{
772	struct pthread	*pthread;
773
774	while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) {
775		TAILQ_REMOVE(&cond->c_queue, pthread, sqe);
776		THR_CONDQ_CLEAR(pthread);
777		if ((pthread->timeout == 0) && (pthread->interrupted == 0))
778			/*
779			 * Only exit the loop when we find a thread
780			 * that hasn't timed out or been canceled;
781			 * those threads are already running and don't
782			 * need their run state changed.
783			 */
784			break;
785	}
786
787	return (pthread);
788}
789
790/*
791 * Remove a waiting thread from a condition queue in descending priority
792 * order.
793 */
794static inline void
795cond_queue_remove(pthread_cond_t cond, struct pthread *pthread)
796{
797	/*
798	 * Because pthread_cond_timedwait() can timeout as well
799	 * as be signaled by another thread, it is necessary to
800	 * guard against removing the thread from the queue if
801	 * it isn't in the queue.
802	 */
803	if (THR_IN_CONDQ(pthread)) {
804		TAILQ_REMOVE(&cond->c_queue, pthread, sqe);
805		THR_CONDQ_CLEAR(pthread);
806	}
807}
808
809/*
810 * Enqueue a waiting thread to a condition queue in descending priority
811 * order.
812 */
813static inline void
814cond_queue_enq(pthread_cond_t cond, struct pthread *pthread)
815{
816	struct pthread *tid = TAILQ_LAST(&cond->c_queue, cond_head);
817
818	THR_ASSERT(!THR_IN_SYNCQ(pthread),
819	    "cond_queue_enq: thread already queued!");
820
821	/*
822	 * For the common case of all threads having equal priority,
823	 * we perform a quick check against the priority of the thread
824	 * at the tail of the queue.
825	 */
826	if ((tid == NULL) || (pthread->active_priority <= tid->active_priority))
827		TAILQ_INSERT_TAIL(&cond->c_queue, pthread, sqe);
828	else {
829		tid = TAILQ_FIRST(&cond->c_queue);
830		while (pthread->active_priority <= tid->active_priority)
831			tid = TAILQ_NEXT(tid, sqe);
832		TAILQ_INSERT_BEFORE(tid, pthread, sqe);
833	}
834	THR_CONDQ_SET(pthread);
835	pthread->data.cond = cond;
836}
837