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