thr_cond.c revision 112918
1112918Sjeff/* 2112918Sjeff * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 3112918Sjeff * All rights reserved. 4112918Sjeff * 5112918Sjeff * Redistribution and use in source and binary forms, with or without 6112918Sjeff * modification, are permitted provided that the following conditions 7112918Sjeff * are met: 8112918Sjeff * 1. Redistributions of source code must retain the above copyright 9112918Sjeff * notice, this list of conditions and the following disclaimer. 10112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11112918Sjeff * notice, this list of conditions and the following disclaimer in the 12112918Sjeff * documentation and/or other materials provided with the distribution. 13112918Sjeff * 3. All advertising materials mentioning features or use of this software 14112918Sjeff * must display the following acknowledgement: 15112918Sjeff * This product includes software developed by John Birrell. 16112918Sjeff * 4. Neither the name of the author nor the names of any co-contributors 17112918Sjeff * may be used to endorse or promote products derived from this software 18112918Sjeff * without specific prior written permission. 19112918Sjeff * 20112918Sjeff * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23112918Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30112918Sjeff * SUCH DAMAGE. 31112918Sjeff * 32112918Sjeff * $FreeBSD: head/lib/libthr/thread/thr_cond.c 112918 2003-04-01 03:46:29Z jeff $ 33112918Sjeff */ 34112918Sjeff#include <stdlib.h> 35112918Sjeff#include <errno.h> 36112918Sjeff#include <string.h> 37112918Sjeff#include <pthread.h> 38112918Sjeff#include "thr_private.h" 39112918Sjeff 40112918Sjeff/* 41112918Sjeff * Prototypes 42112918Sjeff */ 43112918Sjeffstatic pthread_t cond_queue_deq(pthread_cond_t); 44112918Sjeffstatic void cond_queue_remove(pthread_cond_t, pthread_t); 45112918Sjeffstatic void cond_queue_enq(pthread_cond_t, pthread_t); 46112918Sjeff 47112918Sjeff__weak_reference(_pthread_cond_init, pthread_cond_init); 48112918Sjeff__weak_reference(_pthread_cond_destroy, pthread_cond_destroy); 49112918Sjeff__weak_reference(_pthread_cond_wait, pthread_cond_wait); 50112918Sjeff__weak_reference(_pthread_cond_timedwait, pthread_cond_timedwait); 51112918Sjeff__weak_reference(_pthread_cond_signal, pthread_cond_signal); 52112918Sjeff__weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast); 53112918Sjeff 54112918Sjeff#define COND_LOCK(c) \ 55112918Sjeffdo { \ 56112918Sjeff if (umtx_lock(&(c)->c_lock, curthread->thr_id)) \ 57112918Sjeff abort(); \ 58112918Sjeff} while (0) 59112918Sjeff 60112918Sjeff#define COND_UNLOCK(c) \ 61112918Sjeffdo { \ 62112918Sjeff if (umtx_unlock(&(c)->c_lock, curthread->thr_id)) \ 63112918Sjeff abort(); \ 64112918Sjeff} while (0) 65112918Sjeff 66112918Sjeff 67112918Sjeff/* Reinitialize a condition variable to defaults. */ 68112918Sjeffint 69112918Sjeff_cond_reinit(pthread_cond_t *cond) 70112918Sjeff{ 71112918Sjeff if (cond == NULL) 72112918Sjeff return (EINVAL); 73112918Sjeff 74112918Sjeff if (*cond == NULL) 75112918Sjeff return (pthread_cond_init(cond, NULL)); 76112918Sjeff 77112918Sjeff /* 78112918Sjeff * Initialize the condition variable structure: 79112918Sjeff */ 80112918Sjeff TAILQ_INIT(&(*cond)->c_queue); 81112918Sjeff (*cond)->c_flags = COND_FLAGS_INITED; 82112918Sjeff (*cond)->c_type = COND_TYPE_FAST; 83112918Sjeff (*cond)->c_mutex = NULL; 84112918Sjeff (*cond)->c_seqno = 0; 85112918Sjeff bzero(&(*cond)->c_lock, sizeof((*cond)->c_lock)); 86112918Sjeff 87112918Sjeff return (0); 88112918Sjeff} 89112918Sjeff 90112918Sjeffint 91112918Sjeff_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) 92112918Sjeff{ 93112918Sjeff enum pthread_cond_type type; 94112918Sjeff pthread_cond_t pcond; 95112918Sjeff 96112918Sjeff if (cond == NULL) 97112918Sjeff return (EINVAL); 98112918Sjeff 99112918Sjeff /* 100112918Sjeff * Check if a pointer to a condition variable attribute 101112918Sjeff * structure was passed by the caller: 102112918Sjeff */ 103112918Sjeff if (cond_attr != NULL && *cond_attr != NULL) 104112918Sjeff type = (*cond_attr)->c_type; 105112918Sjeff else 106112918Sjeff /* Default to a fast condition variable: */ 107112918Sjeff type = COND_TYPE_FAST; 108112918Sjeff 109112918Sjeff /* Process according to condition variable type: */ 110112918Sjeff switch (type) { 111112918Sjeff case COND_TYPE_FAST: 112112918Sjeff break; 113112918Sjeff default: 114112918Sjeff return (EINVAL); 115112918Sjeff break; 116112918Sjeff } 117112918Sjeff 118112918Sjeff if ((pcond = (pthread_cond_t) 119112918Sjeff malloc(sizeof(struct pthread_cond))) == NULL) 120112918Sjeff return (ENOMEM); 121112918Sjeff /* 122112918Sjeff * Initialise the condition variable 123112918Sjeff * structure: 124112918Sjeff */ 125112918Sjeff TAILQ_INIT(&pcond->c_queue); 126112918Sjeff pcond->c_flags |= COND_FLAGS_INITED; 127112918Sjeff pcond->c_type = type; 128112918Sjeff pcond->c_mutex = NULL; 129112918Sjeff pcond->c_seqno = 0; 130112918Sjeff bzero(&pcond->c_lock, sizeof(pcond->c_lock)); 131112918Sjeff 132112918Sjeff *cond = pcond; 133112918Sjeff 134112918Sjeff return (0); 135112918Sjeff} 136112918Sjeff 137112918Sjeffint 138112918Sjeff_pthread_cond_destroy(pthread_cond_t *cond) 139112918Sjeff{ 140112918Sjeff struct pthread *curthread = _get_curthread(); 141112918Sjeff 142112918Sjeff if (cond == NULL || *cond == NULL) 143112918Sjeff return (EINVAL); 144112918Sjeff 145112918Sjeff COND_LOCK(*cond); 146112918Sjeff 147112918Sjeff /* 148112918Sjeff * Free the memory allocated for the condition 149112918Sjeff * variable structure: 150112918Sjeff */ 151112918Sjeff free(*cond); 152112918Sjeff 153112918Sjeff /* 154112918Sjeff * NULL the caller's pointer now that the condition 155112918Sjeff * variable has been destroyed: 156112918Sjeff */ 157112918Sjeff *cond = NULL; 158112918Sjeff 159112918Sjeff return (0); 160112918Sjeff} 161112918Sjeff 162112918Sjeffint 163112918Sjeff_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) 164112918Sjeff{ 165112918Sjeff int rval; 166112918Sjeff struct timespec abstime = { 0, 0 }; 167112918Sjeff 168112918Sjeff /* 169112918Sjeff * XXXTHR This is a hack. Make a pthread_cond_common function that 170112918Sjeff * accepts NULL so we don't change posix semantics for timedwait. 171112918Sjeff */ 172112918Sjeff rval = pthread_cond_timedwait(cond, mutex, &abstime); 173112918Sjeff 174112918Sjeff /* This should never happen. */ 175112918Sjeff if (rval == ETIMEDOUT) 176112918Sjeff abort(); 177112918Sjeff 178112918Sjeff return (rval); 179112918Sjeff} 180112918Sjeff 181112918Sjeffint 182112918Sjeff_pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, 183112918Sjeff const struct timespec * abstime) 184112918Sjeff{ 185112918Sjeff struct pthread *curthread = _get_curthread(); 186112918Sjeff struct timespec *time; 187112918Sjeff int rval = 0; 188112918Sjeff int done = 0; 189112918Sjeff int seqno; 190112918Sjeff int mtxrval; 191112918Sjeff 192112918Sjeff 193112918Sjeff _thread_enter_cancellation_point(); 194112918Sjeff 195112918Sjeff if (abstime == NULL || abstime->tv_nsec >= 1000000000) 196112918Sjeff return (EINVAL); 197112918Sjeff 198112918Sjeff if (abstime->tv_sec == 0 && abstime->tv_nsec == 0) 199112918Sjeff time = NULL; 200112918Sjeff else 201112918Sjeff time = abstime; 202112918Sjeff /* 203112918Sjeff * If the condition variable is statically initialized, perform dynamic 204112918Sjeff * initialization. 205112918Sjeff */ 206112918Sjeff if (*cond == NULL && (rval = pthread_cond_init(cond, NULL)) != 0) 207112918Sjeff return (rval); 208112918Sjeff 209112918Sjeff 210112918Sjeff COND_LOCK(*cond); 211112918Sjeff 212112918Sjeff /* 213112918Sjeff * If the condvar was statically allocated, properly 214112918Sjeff * initialize the tail queue. 215112918Sjeff */ 216112918Sjeff if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { 217112918Sjeff TAILQ_INIT(&(*cond)->c_queue); 218112918Sjeff (*cond)->c_flags |= COND_FLAGS_INITED; 219112918Sjeff } 220112918Sjeff 221112918Sjeff /* Process according to condition variable type. */ 222112918Sjeff 223112918Sjeff switch ((*cond)->c_type) { 224112918Sjeff /* Fast condition variable: */ 225112918Sjeff case COND_TYPE_FAST: 226112918Sjeff if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && 227112918Sjeff ((*cond)->c_mutex != *mutex))) { 228112918Sjeff COND_UNLOCK(*cond); 229112918Sjeff rval = EINVAL; 230112918Sjeff break; 231112918Sjeff } 232112918Sjeff /* Remember the mutex */ 233112918Sjeff (*cond)->c_mutex = *mutex; 234112918Sjeff 235112918Sjeff if ((rval = _mutex_cv_unlock(mutex)) != 0) { 236112918Sjeff if (rval == -1){ 237112918Sjeff printf("foo"); 238112918Sjeff fflush(stdout); 239112918Sjeff abort(); 240112918Sjeff } 241112918Sjeff 242112918Sjeff COND_UNLOCK(*cond); 243112918Sjeff break; 244112918Sjeff } 245112918Sjeff COND_UNLOCK(*cond); 246112918Sjeff 247112918Sjeff /* 248112918Sjeff * We need giant for the queue operations. It also 249112918Sjeff * protects seqno and the pthread flag fields. This is 250112918Sjeff * dropped and reacquired in _thread_suspend(). 251112918Sjeff */ 252112918Sjeff 253112918Sjeff GIANT_LOCK(curthread); 254112918Sjeff /* 255112918Sjeff * c_seqno is protected by giant. 256112918Sjeff */ 257112918Sjeff seqno = (*cond)->c_seqno; 258112918Sjeff 259112918Sjeff do { 260112918Sjeff /* 261112918Sjeff * Queue the running thread on the condition 262112918Sjeff * variable. 263112918Sjeff */ 264112918Sjeff cond_queue_enq(*cond, curthread); 265112918Sjeff 266112918Sjeff if (curthread->cancelflags & PTHREAD_CANCELLING) { 267112918Sjeff /* 268112918Sjeff * POSIX Says that we must relock the mutex 269112918Sjeff * even if we're being canceled. 270112918Sjeff */ 271112918Sjeff GIANT_UNLOCK(curthread); 272112918Sjeff _mutex_cv_lock(mutex); 273112918Sjeff pthread_testcancel(); 274112918Sjeff PANIC("Shouldn't have come back."); 275112918Sjeff } 276112918Sjeff 277112918Sjeff PTHREAD_SET_STATE(curthread, PS_COND_WAIT); 278112918Sjeff rval = _thread_suspend(curthread, time); 279112918Sjeff if (rval == -1) { 280112918Sjeff printf("foo"); 281112918Sjeff fflush(stdout); 282112918Sjeff abort(); 283112918Sjeff } 284112918Sjeff 285112918Sjeff done = (seqno != (*cond)->c_seqno); 286112918Sjeff 287112918Sjeff cond_queue_remove(*cond, curthread); 288112918Sjeff 289112918Sjeff } while ((done == 0) && (rval == 0)); 290112918Sjeff /* 291112918Sjeff * If we timed out someone still may have signaled us 292112918Sjeff * before we got a chance to run again. We check for 293112918Sjeff * this by looking to see if our state is RUNNING. 294112918Sjeff */ 295112918Sjeff if (rval == EAGAIN) { 296112918Sjeff if (curthread->state != PS_RUNNING) { 297112918Sjeff PTHREAD_SET_STATE(curthread, PS_RUNNING); 298112918Sjeff rval = ETIMEDOUT; 299112918Sjeff } else 300112918Sjeff rval = 0; 301112918Sjeff } 302112918Sjeff GIANT_UNLOCK(curthread); 303112918Sjeff 304112918Sjeff mtxrval = _mutex_cv_lock(mutex); 305112918Sjeff 306112918Sjeff /* 307112918Sjeff * If the mutex failed return that error, otherwise we're 308112918Sjeff * returning ETIMEDOUT. 309112918Sjeff */ 310112918Sjeff if (mtxrval == -1) { 311112918Sjeff printf("foo"); 312112918Sjeff fflush(stdout); 313112918Sjeff abort(); 314112918Sjeff } 315112918Sjeff if (mtxrval != 0) 316112918Sjeff rval = mtxrval; 317112918Sjeff 318112918Sjeff break; 319112918Sjeff 320112918Sjeff /* Trap invalid condition variable types: */ 321112918Sjeff default: 322112918Sjeff COND_UNLOCK(*cond); 323112918Sjeff rval = EINVAL; 324112918Sjeff break; 325112918Sjeff } 326112918Sjeff 327112918Sjeff /* 328112918Sjeff * See if we have to cancel before we retry. We could be 329112918Sjeff * canceled with the mutex held here! 330112918Sjeff */ 331112918Sjeff pthread_testcancel(); 332112918Sjeff 333112918Sjeff _thread_leave_cancellation_point(); 334112918Sjeff 335112918Sjeff return (rval); 336112918Sjeff} 337112918Sjeff 338112918Sjeffint 339112918Sjeff_pthread_cond_signal(pthread_cond_t * cond) 340112918Sjeff{ 341112918Sjeff struct pthread *curthread = _get_curthread(); 342112918Sjeff int rval = 0; 343112918Sjeff pthread_t pthread; 344112918Sjeff 345112918Sjeff if (cond == NULL) 346112918Sjeff return (EINVAL); 347112918Sjeff /* 348112918Sjeff * If the condition variable is statically initialized, perform dynamic 349112918Sjeff * initialization. 350112918Sjeff */ 351112918Sjeff if (*cond == NULL && (rval = pthread_cond_init(cond, NULL)) != 0) 352112918Sjeff return (rval); 353112918Sjeff 354112918Sjeff 355112918Sjeff COND_LOCK(*cond); 356112918Sjeff 357112918Sjeff /* Process according to condition variable type: */ 358112918Sjeff switch ((*cond)->c_type) { 359112918Sjeff /* Fast condition variable: */ 360112918Sjeff case COND_TYPE_FAST: 361112918Sjeff GIANT_LOCK(curthread); 362112918Sjeff (*cond)->c_seqno++; 363112918Sjeff 364112918Sjeff if ((pthread = cond_queue_deq(*cond)) != NULL) { 365112918Sjeff /* 366112918Sjeff * Wake up the signaled thread: 367112918Sjeff */ 368112918Sjeff PTHREAD_NEW_STATE(pthread, PS_RUNNING); 369112918Sjeff } 370112918Sjeff 371112918Sjeff GIANT_UNLOCK(curthread); 372112918Sjeff break; 373112918Sjeff 374112918Sjeff /* Trap invalid condition variable types: */ 375112918Sjeff default: 376112918Sjeff rval = EINVAL; 377112918Sjeff break; 378112918Sjeff } 379112918Sjeff 380112918Sjeff 381112918Sjeff COND_UNLOCK(*cond); 382112918Sjeff 383112918Sjeff return (rval); 384112918Sjeff} 385112918Sjeff 386112918Sjeffint 387112918Sjeff_pthread_cond_broadcast(pthread_cond_t * cond) 388112918Sjeff{ 389112918Sjeff struct pthread *curthread = _get_curthread(); 390112918Sjeff int rval = 0; 391112918Sjeff pthread_t pthread; 392112918Sjeff 393112918Sjeff if (cond == NULL) 394112918Sjeff return (EINVAL); 395112918Sjeff /* 396112918Sjeff * If the condition variable is statically initialized, perform dynamic 397112918Sjeff * initialization. 398112918Sjeff */ 399112918Sjeff if (*cond == NULL && (rval = pthread_cond_init(cond, NULL)) != 0) 400112918Sjeff return (rval); 401112918Sjeff 402112918Sjeff COND_LOCK(*cond); 403112918Sjeff 404112918Sjeff /* Process according to condition variable type: */ 405112918Sjeff switch ((*cond)->c_type) { 406112918Sjeff /* Fast condition variable: */ 407112918Sjeff case COND_TYPE_FAST: 408112918Sjeff GIANT_LOCK(curthread); 409112918Sjeff (*cond)->c_seqno++; 410112918Sjeff 411112918Sjeff /* 412112918Sjeff * Enter a loop to bring all threads off the 413112918Sjeff * condition queue: 414112918Sjeff */ 415112918Sjeff while ((pthread = cond_queue_deq(*cond)) != NULL) { 416112918Sjeff /* 417112918Sjeff * Wake up the signaled thread: 418112918Sjeff */ 419112918Sjeff PTHREAD_NEW_STATE(pthread, PS_RUNNING); 420112918Sjeff } 421112918Sjeff GIANT_UNLOCK(curthread); 422112918Sjeff 423112918Sjeff /* There are no more waiting threads: */ 424112918Sjeff (*cond)->c_mutex = NULL; 425112918Sjeff 426112918Sjeff break; 427112918Sjeff 428112918Sjeff /* Trap invalid condition variable types: */ 429112918Sjeff default: 430112918Sjeff rval = EINVAL; 431112918Sjeff break; 432112918Sjeff } 433112918Sjeff 434112918Sjeff COND_UNLOCK(*cond); 435112918Sjeff 436112918Sjeff 437112918Sjeff return (rval); 438112918Sjeff} 439112918Sjeff 440112918Sjeffvoid 441112918Sjeff_cond_wait_backout(pthread_t pthread) 442112918Sjeff{ 443112918Sjeff struct pthread *curthread = _get_curthread(); 444112918Sjeff pthread_cond_t cond; 445112918Sjeff 446112918Sjeff cond = pthread->data.cond; 447112918Sjeff if (cond == NULL) 448112918Sjeff return; 449112918Sjeff 450112918Sjeff COND_LOCK(cond); 451112918Sjeff 452112918Sjeff /* Process according to condition variable type: */ 453112918Sjeff switch (cond->c_type) { 454112918Sjeff /* Fast condition variable: */ 455112918Sjeff case COND_TYPE_FAST: 456112918Sjeff GIANT_LOCK(curthread); 457112918Sjeff 458112918Sjeff cond_queue_remove(cond, pthread); 459112918Sjeff 460112918Sjeff GIANT_UNLOCK(curthread); 461112918Sjeff break; 462112918Sjeff 463112918Sjeff default: 464112918Sjeff break; 465112918Sjeff } 466112918Sjeff 467112918Sjeff COND_UNLOCK(cond); 468112918Sjeff} 469112918Sjeff 470112918Sjeff/* 471112918Sjeff * Dequeue a waiting thread from the head of a condition queue in 472112918Sjeff * descending priority order. 473112918Sjeff */ 474112918Sjeffstatic pthread_t 475112918Sjeffcond_queue_deq(pthread_cond_t cond) 476112918Sjeff{ 477112918Sjeff pthread_t pthread; 478112918Sjeff 479112918Sjeff while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { 480112918Sjeff TAILQ_REMOVE(&cond->c_queue, pthread, sqe); 481112918Sjeff cond_queue_remove(cond, pthread); 482112918Sjeff if ((pthread->cancelflags & PTHREAD_CANCELLING) == 0 && 483112918Sjeff pthread->state == PS_COND_WAIT) 484112918Sjeff /* 485112918Sjeff * Only exit the loop when we find a thread 486112918Sjeff * that hasn't timed out or been canceled; 487112918Sjeff * those threads are already running and don't 488112918Sjeff * need their run state changed. 489112918Sjeff */ 490112918Sjeff break; 491112918Sjeff } 492112918Sjeff 493112918Sjeff return(pthread); 494112918Sjeff} 495112918Sjeff 496112918Sjeff/* 497112918Sjeff * Remove a waiting thread from a condition queue in descending priority 498112918Sjeff * order. 499112918Sjeff */ 500112918Sjeffstatic void 501112918Sjeffcond_queue_remove(pthread_cond_t cond, pthread_t pthread) 502112918Sjeff{ 503112918Sjeff /* 504112918Sjeff * Because pthread_cond_timedwait() can timeout as well 505112918Sjeff * as be signaled by another thread, it is necessary to 506112918Sjeff * guard against removing the thread from the queue if 507112918Sjeff * it isn't in the queue. 508112918Sjeff */ 509112918Sjeff if (pthread->flags & PTHREAD_FLAGS_IN_CONDQ) { 510112918Sjeff TAILQ_REMOVE(&cond->c_queue, pthread, sqe); 511112918Sjeff pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; 512112918Sjeff } 513112918Sjeff /* Check for no more waiters. */ 514112918Sjeff if (TAILQ_FIRST(&cond->c_queue) == NULL) 515112918Sjeff cond->c_mutex = NULL; 516112918Sjeff} 517112918Sjeff 518112918Sjeff/* 519112918Sjeff * Enqueue a waiting thread to a condition queue in descending priority 520112918Sjeff * order. 521112918Sjeff */ 522112918Sjeffstatic void 523112918Sjeffcond_queue_enq(pthread_cond_t cond, pthread_t pthread) 524112918Sjeff{ 525112918Sjeff pthread_t tid = TAILQ_LAST(&cond->c_queue, cond_head); 526112918Sjeff 527112918Sjeff PTHREAD_ASSERT_NOT_IN_SYNCQ(pthread); 528112918Sjeff 529112918Sjeff /* 530112918Sjeff * For the common case of all threads having equal priority, 531112918Sjeff * we perform a quick check against the priority of the thread 532112918Sjeff * at the tail of the queue. 533112918Sjeff */ 534112918Sjeff if ((tid == NULL) || (pthread->active_priority <= tid->active_priority)) 535112918Sjeff TAILQ_INSERT_TAIL(&cond->c_queue, pthread, sqe); 536112918Sjeff else { 537112918Sjeff tid = TAILQ_FIRST(&cond->c_queue); 538112918Sjeff while (pthread->active_priority <= tid->active_priority) 539112918Sjeff tid = TAILQ_NEXT(tid, sqe); 540112918Sjeff TAILQ_INSERT_BEFORE(tid, pthread, sqe); 541112918Sjeff } 542112918Sjeff pthread->flags |= PTHREAD_FLAGS_IN_CONDQ; 543112918Sjeff pthread->data.cond = cond; 544112918Sjeff} 545