]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libc_r/uthread/uthread_cond.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libc_r / uthread / uthread_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. 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 #include <stdlib.h>
32 #include <errno.h>
33 #include <string.h>
34 #include "namespace.h"
35 #include <pthread.h>
36 #include "un-namespace.h"
37 #include "pthread_private.h"
38
39 /*
40  * Prototypes
41  */
42 static inline pthread_t cond_queue_deq(pthread_cond_t);
43 static inline void      cond_queue_remove(pthread_cond_t, pthread_t);
44 static inline void      cond_queue_enq(pthread_cond_t, pthread_t);
45 int                     __pthread_cond_timedwait(pthread_cond_t *,
46                                 pthread_mutex_t *, const struct timespec *);
47 int                     __pthread_cond_wait(pthread_cond_t *,
48                                 pthread_mutex_t *);
49
50
51 /*
52  * Double underscore versions are cancellation points.  Single underscore
53  * versions are not and are provided for libc internal usage (which
54  * shouldn't introduce cancellation points).
55  */
56 __weak_reference(__pthread_cond_wait, pthread_cond_wait);
57 __weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait);
58
59 __weak_reference(_pthread_cond_init, pthread_cond_init);
60 __weak_reference(_pthread_cond_destroy, pthread_cond_destroy);
61 __weak_reference(_pthread_cond_signal, pthread_cond_signal);
62 __weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast);
63
64
65 /*
66  * Reinitialize a private condition variable; this is only used for
67  * internal condition variables.  Currently, there is no difference.
68  */
69 int
70 _cond_reinit(pthread_cond_t *cond)
71 {
72         int ret = 0;
73
74         if (cond == NULL)
75                 ret = EINVAL;
76         else if (*cond == NULL)
77                 ret = _pthread_cond_init(cond, NULL);
78         else {
79                 /*
80                  * Initialize the condition variable structure:
81                  */
82                 TAILQ_INIT(&(*cond)->c_queue);
83                 (*cond)->c_flags = COND_FLAGS_INITED;
84                 (*cond)->c_type = COND_TYPE_FAST;
85                 (*cond)->c_mutex = NULL;
86                 (*cond)->c_seqno = 0;
87                 memset(&(*cond)->lock, 0, sizeof((*cond)->lock));
88         }
89         return (ret);
90 }
91
92 int
93 _pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
94 {
95         enum pthread_cond_type type;
96         pthread_cond_t  pcond;
97         int             rval = 0;
98
99         if (cond == NULL)
100                 rval = EINVAL;
101         else {
102                 /*
103                  * Check if a pointer to a condition variable attribute
104                  * structure was passed by the caller: 
105                  */
106                 if (cond_attr != NULL && *cond_attr != NULL) {
107                         /* Default to a fast condition variable: */
108                         type = (*cond_attr)->c_type;
109                 } else {
110                         /* Default to a fast condition variable: */
111                         type = COND_TYPE_FAST;
112                 }
113
114                 /* Process according to condition variable type: */
115                 switch (type) {
116                 /* Fast condition variable: */
117                 case COND_TYPE_FAST:
118                         /* Nothing to do here. */
119                         break;
120
121                 /* Trap invalid condition variable types: */
122                 default:
123                         /* Return an invalid argument error: */
124                         rval = EINVAL;
125                         break;
126                 }
127
128                 /* Check for no errors: */
129                 if (rval == 0) {
130                         if ((pcond = (pthread_cond_t)
131                             malloc(sizeof(struct pthread_cond))) == NULL) {
132                                 rval = ENOMEM;
133                         } else {
134                                 /*
135                                  * Initialise the condition variable
136                                  * structure:
137                                  */
138                                 TAILQ_INIT(&pcond->c_queue);
139                                 pcond->c_flags |= COND_FLAGS_INITED;
140                                 pcond->c_type = type;
141                                 pcond->c_mutex = NULL;
142                                 pcond->c_seqno = 0;
143                                 memset(&pcond->lock,0,sizeof(pcond->lock));
144                                 *cond = pcond;
145                         }
146                 }
147         }
148         /* Return the completion status: */
149         return (rval);
150 }
151
152 int
153 _pthread_cond_destroy(pthread_cond_t *cond)
154 {
155         int             rval = 0;
156
157         if (cond == NULL || *cond == NULL)
158                 rval = EINVAL;
159         else {
160                 /* Lock the condition variable structure: */
161                 _SPINLOCK(&(*cond)->lock);
162
163                 /*
164                  * Free the memory allocated for the condition
165                  * variable structure:
166                  */
167                 free(*cond);
168
169                 /*
170                  * NULL the caller's pointer now that the condition
171                  * variable has been destroyed:
172                  */
173                 *cond = NULL;
174         }
175         /* Return the completion status: */
176         return (rval);
177 }
178
179 int
180 _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
181 {
182         struct pthread  *curthread = _get_curthread();
183         int     rval = 0;
184         int     done = 0;
185         int     interrupted = 0;
186         int     seqno;
187
188         if (cond == NULL)
189                 return (EINVAL);
190
191         /*
192          * If the condition variable is statically initialized,
193          * perform the dynamic initialization:
194          */
195         if (*cond == NULL &&
196             (rval = _pthread_cond_init(cond, NULL)) != 0)
197                 return (rval);
198
199         /*
200          * Enter a loop waiting for a condition signal or broadcast
201          * to wake up this thread.  A loop is needed in case the waiting
202          * thread is interrupted by a signal to execute a signal handler.
203          * It is not (currently) possible to remain in the waiting queue
204          * while running a handler.  Instead, the thread is interrupted
205          * and backed out of the waiting queue prior to executing the
206          * signal handler.
207          */
208         do {
209                 /* Lock the condition variable structure: */
210                 _SPINLOCK(&(*cond)->lock);
211
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                                 /* Unlock the condition variable structure: */
228                                 _SPINUNLOCK(&(*cond)->lock);
229
230                                 /* Return invalid argument error: */
231                                 rval = EINVAL;
232                         } else {
233                                 /* Reset the timeout and interrupted flags: */
234                                 curthread->timeout = 0;
235                                 curthread->interrupted = 0;
236
237                                 /*
238                                  * Queue the running thread for the condition
239                                  * variable:
240                                  */
241                                 cond_queue_enq(*cond, curthread);
242
243                                 /* Remember the mutex and sequence number: */
244                                 (*cond)->c_mutex = *mutex;
245                                 seqno = (*cond)->c_seqno;
246
247                                 /* Wait forever: */
248                                 curthread->wakeup_time.tv_sec = -1;
249
250                                 /* Unlock the mutex: */
251                                 if ((rval = _mutex_cv_unlock(mutex)) != 0) {
252                                         /*
253                                          * Cannot unlock the mutex, so remove
254                                          * the running thread from the condition
255                                          * variable queue:
256                                          */
257                                         cond_queue_remove(*cond, curthread);
258
259                                         /* Check for no more waiters: */
260                                         if (TAILQ_FIRST(&(*cond)->c_queue) ==
261                                             NULL)
262                                                 (*cond)->c_mutex = NULL;
263
264                                         /* Unlock the condition variable structure: */
265                                         _SPINUNLOCK(&(*cond)->lock);
266                                 } else {
267                                         /*
268                                          * Schedule the next thread and unlock
269                                          * the condition variable structure:
270                                          */
271                                         _thread_kern_sched_state_unlock(PS_COND_WAIT,
272                                             &(*cond)->lock, __FILE__, __LINE__);
273
274                                         done = (seqno != (*cond)->c_seqno);
275
276                                         interrupted = curthread->interrupted;
277
278                                         /*
279                                          * Check if the wait was interrupted
280                                          * (canceled) or needs to be resumed
281                                          * after handling a signal.
282                                          */
283                                         if (interrupted != 0) {
284                                                 /*
285                                                  * Lock the mutex and ignore any
286                                                  * errors.  Note that even
287                                                  * though this thread may have
288                                                  * been canceled, POSIX requires
289                                                  * that the mutex be reaquired
290                                                  * prior to cancellation.
291                                                  */
292                                                 (void)_mutex_cv_lock(mutex);
293                                         } else {
294                                                 /*
295                                                  * Lock the condition variable
296                                                  * while removing the thread.
297                                                  */
298                                                 _SPINLOCK(&(*cond)->lock);
299
300                                                 cond_queue_remove(*cond,
301                                                     curthread);
302
303                                                 /* Check for no more waiters: */
304                                                 if (TAILQ_FIRST(&(*cond)->c_queue) == NULL)
305                                                         (*cond)->c_mutex = NULL;
306
307                                                 _SPINUNLOCK(&(*cond)->lock);
308
309                                                 /* Lock the mutex: */
310                                                 rval = _mutex_cv_lock(mutex);
311                                         }
312                                 }
313                         }
314                         break;
315
316                 /* Trap invalid condition variable types: */
317                 default:
318                         /* Unlock the condition variable structure: */
319                         _SPINUNLOCK(&(*cond)->lock);
320
321                         /* Return an invalid argument error: */
322                         rval = EINVAL;
323                         break;
324                 }
325
326                 if ((interrupted != 0) && (curthread->continuation != NULL))
327                         curthread->continuation((void *) curthread);
328         } while ((done == 0) && (rval == 0));
329
330         /* Return the completion status: */
331         return (rval);
332 }
333
334 int
335 __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
336 {
337         int ret;
338
339         _thread_enter_cancellation_point();
340         ret = _pthread_cond_wait(cond, mutex);
341         _thread_leave_cancellation_point();
342         return (ret);
343 }
344
345 int
346 _pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
347                        const struct timespec *abstime)
348 {
349         struct pthread  *curthread = _get_curthread();
350         int     rval = 0;
351         int     done = 0;
352         int     interrupted = 0;
353         int     seqno;
354
355         if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
356             abstime->tv_nsec >= 1000000000)
357                 return (EINVAL);
358         /*
359          * If the condition variable is statically initialized, perform dynamic
360          * initialization.
361          */
362         if (*cond == NULL && (rval = _pthread_cond_init(cond, NULL)) != 0)
363                 return (rval);
364
365         /*
366          * Enter a loop waiting for a condition signal or broadcast
367          * to wake up this thread.  A loop is needed in case the waiting
368          * thread is interrupted by a signal to execute a signal handler.
369          * It is not (currently) possible to remain in the waiting queue
370          * while running a handler.  Instead, the thread is interrupted
371          * and backed out of the waiting queue prior to executing the
372          * signal handler.
373          */
374         do {
375                 /* Lock the condition variable structure: */
376                 _SPINLOCK(&(*cond)->lock);
377
378                 /*
379                  * If the condvar was statically allocated, properly
380                  * initialize the tail queue.
381                  */
382                 if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) {
383                         TAILQ_INIT(&(*cond)->c_queue);
384                         (*cond)->c_flags |= COND_FLAGS_INITED;
385                 }
386
387                 /* Process according to condition variable type: */
388                 switch ((*cond)->c_type) {
389                 /* Fast condition variable: */
390                 case COND_TYPE_FAST:
391                         if ((mutex == NULL) || (((*cond)->c_mutex != NULL) &&
392                             ((*cond)->c_mutex != *mutex))) {
393                                 /* Return invalid argument error: */
394                                 rval = EINVAL;
395
396                                 /* Unlock the condition variable structure: */
397                                 _SPINUNLOCK(&(*cond)->lock);
398                         } else {
399                                 /* Set the wakeup time: */
400                                 curthread->wakeup_time.tv_sec =
401                                     abstime->tv_sec;
402                                 curthread->wakeup_time.tv_nsec =
403                                     abstime->tv_nsec;
404
405                                 /* Reset the timeout and interrupted flags: */
406                                 curthread->timeout = 0;
407                                 curthread->interrupted = 0;
408
409                                 /*
410                                  * Queue the running thread for the condition
411                                  * variable:
412                                  */
413                                 cond_queue_enq(*cond, curthread);
414
415                                 /* Remember the mutex and sequence number: */
416                                 (*cond)->c_mutex = *mutex;
417                                 seqno = (*cond)->c_seqno;
418
419                                 /* Unlock the mutex: */
420                                 if ((rval = _mutex_cv_unlock(mutex)) != 0) {
421                                         /*
422                                          * Cannot unlock the mutex, so remove
423                                          * the running thread from the condition
424                                          * variable queue: 
425                                          */
426                                         cond_queue_remove(*cond, curthread);
427
428                                         /* Check for no more waiters: */
429                                         if (TAILQ_FIRST(&(*cond)->c_queue) == NULL)
430                                                 (*cond)->c_mutex = NULL;
431
432                                         /* Unlock the condition variable structure: */
433                                         _SPINUNLOCK(&(*cond)->lock);
434                                 } else {
435                                         /*
436                                          * Schedule the next thread and unlock
437                                          * the condition variable structure:
438                                          */
439                                         _thread_kern_sched_state_unlock(PS_COND_WAIT,
440                                              &(*cond)->lock, __FILE__, __LINE__);
441
442                                         done = (seqno != (*cond)->c_seqno);
443
444                                         interrupted = curthread->interrupted;
445
446                                         /*
447                                          * Check if the wait was interrupted
448                                          * (canceled) or needs to be resumed
449                                          * after handling a signal.
450                                          */
451                                         if (interrupted != 0) {
452                                                 /*
453                                                  * Lock the mutex and ignore any
454                                                  * errors.  Note that even
455                                                  * though this thread may have
456                                                  * been canceled, POSIX requires
457                                                  * that the mutex be reaquired
458                                                  * prior to cancellation.
459                                                  */
460                                                 (void)_mutex_cv_lock(mutex);
461                                         } else {
462                                                 /*
463                                                  * Lock the condition variable
464                                                  * while removing the thread.
465                                                  */
466                                                 _SPINLOCK(&(*cond)->lock);
467
468                                                 cond_queue_remove(*cond,
469                                                     curthread);
470
471                                                 /* Check for no more waiters: */
472                                                 if (TAILQ_FIRST(&(*cond)->c_queue) == NULL)
473                                                         (*cond)->c_mutex = NULL;
474
475                                                 _SPINUNLOCK(&(*cond)->lock);
476
477                                                 /* Lock the mutex: */
478                                                 rval = _mutex_cv_lock(mutex);
479
480                                                 /*
481                                                  * Return ETIMEDOUT if the wait
482                                                  * timed out and there wasn't an
483                                                  * error locking the mutex:
484                                                  */
485                                                 if ((curthread->timeout != 0)
486                                                     && rval == 0)
487                                                         rval = ETIMEDOUT;
488
489                                         }
490                                 }
491                         }
492                         break;
493
494                 /* Trap invalid condition variable types: */
495                 default:
496                         /* Unlock the condition variable structure: */
497                         _SPINUNLOCK(&(*cond)->lock);
498
499                         /* Return an invalid argument error: */
500                         rval = EINVAL;
501                         break;
502                 }
503
504                 if ((interrupted != 0) && (curthread->continuation != NULL))
505                         curthread->continuation((void *) curthread);
506         } while ((done == 0) && (rval == 0));
507
508         /* Return the completion status: */
509         return (rval);
510 }
511
512 int
513 __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
514                        const struct timespec *abstime)
515 {
516         int ret;
517
518         _thread_enter_cancellation_point();
519         ret = _pthread_cond_timedwait(cond, mutex, abstime);
520         _thread_enter_cancellation_point();
521         return (ret);
522 }
523
524 int
525 _pthread_cond_signal(pthread_cond_t *cond)
526 {
527         int             rval = 0;
528         pthread_t       pthread;
529
530         if (cond == NULL)
531                 rval = EINVAL;
532        /*
533         * If the condition variable is statically initialized, perform dynamic
534         * initialization.
535         */
536         else if (*cond != NULL ||
537             (rval = _pthread_cond_init(cond, NULL)) == 0) {
538                 /*
539                  * Defer signals to protect the scheduling queues
540                  * from access by the signal handler:
541                  */
542                 _thread_kern_sig_defer();
543
544                 /* Lock the condition variable structure: */
545                 _SPINLOCK(&(*cond)->lock);
546
547                 /* Process according to condition variable type: */
548                 switch ((*cond)->c_type) {
549                 /* Fast condition variable: */
550                 case COND_TYPE_FAST:
551                         /* Increment the sequence number: */
552                         (*cond)->c_seqno++;
553
554                         if ((pthread = cond_queue_deq(*cond)) != NULL) {
555                                 /*
556                                  * Wake up the signaled thread:
557                                  */
558                                 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
559                         }
560
561                         /* Check for no more waiters: */
562                         if (TAILQ_FIRST(&(*cond)->c_queue) == NULL)
563                                 (*cond)->c_mutex = NULL;
564                         break;
565
566                 /* Trap invalid condition variable types: */
567                 default:
568                         /* Return an invalid argument error: */
569                         rval = EINVAL;
570                         break;
571                 }
572
573                 /* Unlock the condition variable structure: */
574                 _SPINUNLOCK(&(*cond)->lock);
575
576                 /*
577                  * Undefer and handle pending signals, yielding if
578                  * necessary:
579                  */
580                 _thread_kern_sig_undefer();
581         }
582
583         /* Return the completion status: */
584         return (rval);
585 }
586
587 int
588 _pthread_cond_broadcast(pthread_cond_t *cond)
589 {
590         int             rval = 0;
591         pthread_t       pthread;
592
593         if (cond == NULL)
594                 rval = EINVAL;
595        /*
596         * If the condition variable is statically initialized, perform dynamic
597         * initialization.
598         */
599         else if (*cond != NULL ||
600             (rval = _pthread_cond_init(cond, NULL)) == 0) {
601                 /*
602                  * Defer signals to protect the scheduling queues
603                  * from access by the signal handler:
604                  */
605                 _thread_kern_sig_defer();
606
607                 /* Lock the condition variable structure: */
608                 _SPINLOCK(&(*cond)->lock);
609
610                 /* Process according to condition variable type: */
611                 switch ((*cond)->c_type) {
612                 /* Fast condition variable: */
613                 case COND_TYPE_FAST:
614                         /* Increment the sequence number: */
615                         (*cond)->c_seqno++;
616
617                         /*
618                          * Enter a loop to bring all threads off the
619                          * condition queue:
620                          */
621                         while ((pthread = cond_queue_deq(*cond)) != NULL) {
622                                 /*
623                                  * Wake up the signaled thread:
624                                  */
625                                 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
626                         }
627
628                         /* There are no more waiting threads: */
629                         (*cond)->c_mutex = NULL;
630                         break;
631         
632                 /* Trap invalid condition variable types: */
633                 default:
634                         /* Return an invalid argument error: */
635                         rval = EINVAL;
636                         break;
637                 }
638
639                 /* Unlock the condition variable structure: */
640                 _SPINUNLOCK(&(*cond)->lock);
641
642                 /*
643                  * Undefer and handle pending signals, yielding if
644                  * necessary:
645                  */
646                 _thread_kern_sig_undefer();
647         }
648
649         /* Return the completion status: */
650         return (rval);
651 }
652
653 void
654 _cond_wait_backout(pthread_t pthread)
655 {
656         pthread_cond_t  cond;
657
658         cond = pthread->data.cond;
659         if (cond != NULL) {
660                 /*
661                  * Defer signals to protect the scheduling queues
662                  * from access by the signal handler:
663                  */
664                 _thread_kern_sig_defer();
665
666                 /* Lock the condition variable structure: */
667                 _SPINLOCK(&cond->lock);
668
669                 /* Process according to condition variable type: */
670                 switch (cond->c_type) {
671                 /* Fast condition variable: */
672                 case COND_TYPE_FAST:
673                         cond_queue_remove(cond, pthread);
674
675                         /* Check for no more waiters: */
676                         if (TAILQ_FIRST(&cond->c_queue) == NULL)
677                                 cond->c_mutex = NULL;
678                         break;
679
680                 default:
681                         break;
682                 }
683
684                 /* Unlock the condition variable structure: */
685                 _SPINUNLOCK(&cond->lock);
686
687                 /*
688                  * Undefer and handle pending signals, yielding if
689                  * necessary:
690                  */
691                 _thread_kern_sig_undefer();
692         }
693 }
694
695 /*
696  * Dequeue a waiting thread from the head of a condition queue in
697  * descending priority order.
698  */
699 static inline pthread_t
700 cond_queue_deq(pthread_cond_t cond)
701 {
702         pthread_t pthread;
703
704         while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) {
705                 TAILQ_REMOVE(&cond->c_queue, pthread, sqe);
706                 pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ;
707                 if ((pthread->timeout == 0) && (pthread->interrupted == 0))
708                         /*
709                          * Only exit the loop when we find a thread
710                          * that hasn't timed out or been canceled;
711                          * those threads are already running and don't
712                          * need their run state changed.
713                          */
714                         break;
715         }
716
717         return(pthread);
718 }
719
720 /*
721  * Remove a waiting thread from a condition queue in descending priority
722  * order.
723  */
724 static inline void
725 cond_queue_remove(pthread_cond_t cond, pthread_t pthread)
726 {
727         /*
728          * Because pthread_cond_timedwait() can timeout as well
729          * as be signaled by another thread, it is necessary to
730          * guard against removing the thread from the queue if
731          * it isn't in the queue.
732          */
733         if (pthread->flags & PTHREAD_FLAGS_IN_CONDQ) {
734                 TAILQ_REMOVE(&cond->c_queue, pthread, sqe);
735                 pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ;
736         }
737 }
738
739 /*
740  * Enqueue a waiting thread to a condition queue in descending priority
741  * order.
742  */
743 static inline void
744 cond_queue_enq(pthread_cond_t cond, pthread_t pthread)
745 {
746         pthread_t tid = TAILQ_LAST(&cond->c_queue, cond_head);
747
748         PTHREAD_ASSERT_NOT_IN_SYNCQ(pthread);
749
750         /*
751          * For the common case of all threads having equal priority,
752          * we perform a quick check against the priority of the thread
753          * at the tail of the queue.
754          */
755         if ((tid == NULL) || (pthread->active_priority <= tid->active_priority))
756                 TAILQ_INSERT_TAIL(&cond->c_queue, pthread, sqe);
757         else {
758                 tid = TAILQ_FIRST(&cond->c_queue);
759                 while (pthread->active_priority <= tid->active_priority)
760                         tid = TAILQ_NEXT(tid, sqe);
761                 TAILQ_INSERT_BEFORE(tid, pthread, sqe);
762         }
763         pthread->flags |= PTHREAD_FLAGS_IN_CONDQ;
764         pthread->data.cond = cond;
765 }