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