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