1*433d6423SLionel Sambuc #include <minix/mthread.h> 2*433d6423SLionel Sambuc #include "global.h" 3*433d6423SLionel Sambuc #include "proto.h" 4*433d6423SLionel Sambuc 5*433d6423SLionel Sambuc #ifdef MTHREAD_STRICT 6*433d6423SLionel Sambuc static struct __mthread_cond *vc_front, *vc_rear; 7*433d6423SLionel Sambuc static void mthread_cond_add(mthread_cond_t *c); 8*433d6423SLionel Sambuc static void mthread_cond_remove(mthread_cond_t *c); 9*433d6423SLionel Sambuc static int mthread_cond_valid(mthread_cond_t *c); 10*433d6423SLionel Sambuc #else 11*433d6423SLionel Sambuc # define mthread_cond_add(c) ((*c)->mc_magic = MTHREAD_INIT_MAGIC) 12*433d6423SLionel Sambuc # define mthread_cond_remove(c) ((*c)->mc_magic = MTHREAD_NOT_INUSE) 13*433d6423SLionel Sambuc # define mthread_cond_valid(c) ((*c)->mc_magic == MTHREAD_INIT_MAGIC) 14*433d6423SLionel Sambuc #endif 15*433d6423SLionel Sambuc #define MAIN_COND mainthread.m_cond 16*433d6423SLionel Sambuc 17*433d6423SLionel Sambuc /*===========================================================================* 18*433d6423SLionel Sambuc * mthread_init_valid_conditions * 19*433d6423SLionel Sambuc *===========================================================================*/ mthread_init_valid_conditions(void)20*433d6423SLionel Sambucvoid mthread_init_valid_conditions(void) 21*433d6423SLionel Sambuc { 22*433d6423SLionel Sambuc #ifdef MTHREAD_STRICT 23*433d6423SLionel Sambuc /* Initialize condition variable list */ 24*433d6423SLionel Sambuc vc_front = vc_rear = NULL; 25*433d6423SLionel Sambuc #endif 26*433d6423SLionel Sambuc } 27*433d6423SLionel Sambuc 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc /*===========================================================================* 30*433d6423SLionel Sambuc * mthread_cond_add * 31*433d6423SLionel Sambuc *===========================================================================*/ 32*433d6423SLionel Sambuc #ifdef MTHREAD_STRICT mthread_cond_add(c)33*433d6423SLionel Sambucstatic void mthread_cond_add(c) 34*433d6423SLionel Sambuc mthread_cond_t *c; 35*433d6423SLionel Sambuc { 36*433d6423SLionel Sambuc /* Add condition to list of valid, initialized conditions */ 37*433d6423SLionel Sambuc 38*433d6423SLionel Sambuc if (vc_front == NULL) { /* Empty list */ 39*433d6423SLionel Sambuc vc_front = *c; 40*433d6423SLionel Sambuc (*c)->mc_prev = NULL; 41*433d6423SLionel Sambuc } else { 42*433d6423SLionel Sambuc vc_rear->mc_next = *c; 43*433d6423SLionel Sambuc (*c)->mc_prev = vc_rear; 44*433d6423SLionel Sambuc } 45*433d6423SLionel Sambuc 46*433d6423SLionel Sambuc (*c)->mc_next = NULL; 47*433d6423SLionel Sambuc vc_rear = *c; 48*433d6423SLionel Sambuc } 49*433d6423SLionel Sambuc #endif 50*433d6423SLionel Sambuc 51*433d6423SLionel Sambuc /*===========================================================================* 52*433d6423SLionel Sambuc * mthread_cond_broadcast * 53*433d6423SLionel Sambuc *===========================================================================*/ mthread_cond_broadcast(cond)54*433d6423SLionel Sambucint mthread_cond_broadcast(cond) 55*433d6423SLionel Sambuc mthread_cond_t *cond; 56*433d6423SLionel Sambuc { 57*433d6423SLionel Sambuc /* Signal all threads waiting for condition 'cond'. */ 58*433d6423SLionel Sambuc mthread_thread_t t; 59*433d6423SLionel Sambuc mthread_tcb_t *tcb; 60*433d6423SLionel Sambuc 61*433d6423SLionel Sambuc if (cond == NULL) 62*433d6423SLionel Sambuc return(EINVAL); 63*433d6423SLionel Sambuc else if (!mthread_cond_valid(cond)) 64*433d6423SLionel Sambuc return(EINVAL); 65*433d6423SLionel Sambuc 66*433d6423SLionel Sambuc tcb = mthread_find_tcb(MAIN_THREAD); 67*433d6423SLionel Sambuc if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond) 68*433d6423SLionel Sambuc mthread_unsuspend(MAIN_THREAD); 69*433d6423SLionel Sambuc 70*433d6423SLionel Sambuc for (t = (mthread_thread_t) 0; t < no_threads; t++) { 71*433d6423SLionel Sambuc tcb = mthread_find_tcb(t); 72*433d6423SLionel Sambuc if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond) 73*433d6423SLionel Sambuc mthread_unsuspend(t); 74*433d6423SLionel Sambuc } 75*433d6423SLionel Sambuc 76*433d6423SLionel Sambuc return(0); 77*433d6423SLionel Sambuc } 78*433d6423SLionel Sambuc 79*433d6423SLionel Sambuc 80*433d6423SLionel Sambuc /*===========================================================================* 81*433d6423SLionel Sambuc * mthread_cond_destroy * 82*433d6423SLionel Sambuc *===========================================================================*/ mthread_cond_destroy(cond)83*433d6423SLionel Sambucint mthread_cond_destroy(cond) 84*433d6423SLionel Sambuc mthread_cond_t *cond; 85*433d6423SLionel Sambuc { 86*433d6423SLionel Sambuc /* Destroy a condition variable. Make sure it's not in use */ 87*433d6423SLionel Sambuc mthread_thread_t t; 88*433d6423SLionel Sambuc mthread_tcb_t *tcb; 89*433d6423SLionel Sambuc 90*433d6423SLionel Sambuc if (cond == NULL) 91*433d6423SLionel Sambuc return(EINVAL); 92*433d6423SLionel Sambuc else if (!mthread_cond_valid(cond)) 93*433d6423SLionel Sambuc return(EINVAL); 94*433d6423SLionel Sambuc 95*433d6423SLionel Sambuc /* Is another thread currently using this condition variable? */ 96*433d6423SLionel Sambuc tcb = mthread_find_tcb(MAIN_THREAD); 97*433d6423SLionel Sambuc if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond) 98*433d6423SLionel Sambuc return(EBUSY); 99*433d6423SLionel Sambuc 100*433d6423SLionel Sambuc for (t = (mthread_thread_t) 0; t < no_threads; t++) { 101*433d6423SLionel Sambuc tcb = mthread_find_tcb(t); 102*433d6423SLionel Sambuc if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond) 103*433d6423SLionel Sambuc return(EBUSY); 104*433d6423SLionel Sambuc } 105*433d6423SLionel Sambuc 106*433d6423SLionel Sambuc /* Not in use; invalidate it. */ 107*433d6423SLionel Sambuc mthread_cond_remove(cond); 108*433d6423SLionel Sambuc free(*cond); 109*433d6423SLionel Sambuc *cond = NULL; 110*433d6423SLionel Sambuc 111*433d6423SLionel Sambuc return(0); 112*433d6423SLionel Sambuc } 113*433d6423SLionel Sambuc 114*433d6423SLionel Sambuc 115*433d6423SLionel Sambuc /*===========================================================================* 116*433d6423SLionel Sambuc * mthread_cond_init * 117*433d6423SLionel Sambuc *===========================================================================*/ mthread_cond_init(cond,cattr)118*433d6423SLionel Sambucint mthread_cond_init(cond, cattr) 119*433d6423SLionel Sambuc mthread_cond_t *cond; 120*433d6423SLionel Sambuc mthread_condattr_t *cattr; 121*433d6423SLionel Sambuc { 122*433d6423SLionel Sambuc /* Initialize condition variable to a known state. cattr is ignored */ 123*433d6423SLionel Sambuc struct __mthread_cond *c; 124*433d6423SLionel Sambuc 125*433d6423SLionel Sambuc if (cond == NULL) 126*433d6423SLionel Sambuc return(EINVAL); 127*433d6423SLionel Sambuc else if (cattr != NULL) 128*433d6423SLionel Sambuc return(ENOSYS); 129*433d6423SLionel Sambuc 130*433d6423SLionel Sambuc #ifdef MTHREAD_STRICT 131*433d6423SLionel Sambuc else if (mthread_cond_valid(cond)) 132*433d6423SLionel Sambuc /* Already initialized */ 133*433d6423SLionel Sambuc return(EBUSY); 134*433d6423SLionel Sambuc #endif 135*433d6423SLionel Sambuc else if ((c = malloc(sizeof(struct __mthread_cond))) == NULL) 136*433d6423SLionel Sambuc return(ENOMEM); 137*433d6423SLionel Sambuc 138*433d6423SLionel Sambuc c->mc_mutex = NULL; 139*433d6423SLionel Sambuc *cond = (mthread_cond_t) c; 140*433d6423SLionel Sambuc mthread_cond_add(cond); 141*433d6423SLionel Sambuc 142*433d6423SLionel Sambuc return(0); 143*433d6423SLionel Sambuc } 144*433d6423SLionel Sambuc 145*433d6423SLionel Sambuc 146*433d6423SLionel Sambuc /*===========================================================================* 147*433d6423SLionel Sambuc * mthread_cond_remove * 148*433d6423SLionel Sambuc *===========================================================================*/ 149*433d6423SLionel Sambuc #ifdef MTHREAD_STRICT mthread_cond_remove(c)150*433d6423SLionel Sambucstatic void mthread_cond_remove(c) 151*433d6423SLionel Sambuc mthread_cond_t *c; 152*433d6423SLionel Sambuc { 153*433d6423SLionel Sambuc /* Remove condition from list of valid, initialized conditions */ 154*433d6423SLionel Sambuc 155*433d6423SLionel Sambuc if ((*c)->mc_prev == NULL) 156*433d6423SLionel Sambuc vc_front = (*c)->mc_next; 157*433d6423SLionel Sambuc else 158*433d6423SLionel Sambuc (*c)->mc_prev->mc_next = (*c)->mc_next; 159*433d6423SLionel Sambuc 160*433d6423SLionel Sambuc if ((*c)->mc_next == NULL) 161*433d6423SLionel Sambuc vc_rear = (*c)->mc_prev; 162*433d6423SLionel Sambuc else 163*433d6423SLionel Sambuc (*c)->mc_next->mc_prev = (*c)->mc_prev; 164*433d6423SLionel Sambuc 165*433d6423SLionel Sambuc } 166*433d6423SLionel Sambuc #endif 167*433d6423SLionel Sambuc 168*433d6423SLionel Sambuc /*===========================================================================* 169*433d6423SLionel Sambuc * mthread_cond_signal * 170*433d6423SLionel Sambuc *===========================================================================*/ mthread_cond_signal(cond)171*433d6423SLionel Sambucint mthread_cond_signal(cond) 172*433d6423SLionel Sambuc mthread_cond_t *cond; 173*433d6423SLionel Sambuc { 174*433d6423SLionel Sambuc /* Signal a thread that condition 'cond' was met. Just a single thread. */ 175*433d6423SLionel Sambuc mthread_thread_t t; 176*433d6423SLionel Sambuc mthread_tcb_t *tcb; 177*433d6423SLionel Sambuc 178*433d6423SLionel Sambuc if (cond == NULL) 179*433d6423SLionel Sambuc return(EINVAL); 180*433d6423SLionel Sambuc else if (!mthread_cond_valid(cond)) 181*433d6423SLionel Sambuc return(EINVAL); 182*433d6423SLionel Sambuc 183*433d6423SLionel Sambuc tcb = mthread_find_tcb(MAIN_THREAD); 184*433d6423SLionel Sambuc if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond) 185*433d6423SLionel Sambuc mthread_unsuspend(MAIN_THREAD); 186*433d6423SLionel Sambuc 187*433d6423SLionel Sambuc for (t = (mthread_thread_t) 0; t < no_threads; t++) { 188*433d6423SLionel Sambuc tcb = mthread_find_tcb(t); 189*433d6423SLionel Sambuc if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){ 190*433d6423SLionel Sambuc mthread_unsuspend(t); 191*433d6423SLionel Sambuc break; 192*433d6423SLionel Sambuc } 193*433d6423SLionel Sambuc } 194*433d6423SLionel Sambuc 195*433d6423SLionel Sambuc return(0); 196*433d6423SLionel Sambuc } 197*433d6423SLionel Sambuc 198*433d6423SLionel Sambuc 199*433d6423SLionel Sambuc /*===========================================================================* 200*433d6423SLionel Sambuc * mthread_cond_valid * 201*433d6423SLionel Sambuc *===========================================================================*/ 202*433d6423SLionel Sambuc #ifdef MTHREAD_STRICT mthread_cond_valid(c)203*433d6423SLionel Sambucstatic int mthread_cond_valid(c) 204*433d6423SLionel Sambuc mthread_cond_t *c; 205*433d6423SLionel Sambuc { 206*433d6423SLionel Sambuc /* Check to see if cond is on the list of valid conditions */ 207*433d6423SLionel Sambuc struct __mthread_cond *loopitem; 208*433d6423SLionel Sambuc 209*433d6423SLionel Sambuc loopitem = vc_front; 210*433d6423SLionel Sambuc 211*433d6423SLionel Sambuc while (loopitem != NULL) { 212*433d6423SLionel Sambuc if (loopitem == *c) 213*433d6423SLionel Sambuc return(1); 214*433d6423SLionel Sambuc 215*433d6423SLionel Sambuc loopitem = loopitem->mc_next; 216*433d6423SLionel Sambuc } 217*433d6423SLionel Sambuc 218*433d6423SLionel Sambuc return(0); 219*433d6423SLionel Sambuc } 220*433d6423SLionel Sambuc #endif 221*433d6423SLionel Sambuc 222*433d6423SLionel Sambuc /*===========================================================================* 223*433d6423SLionel Sambuc * mthread_cond_verify * 224*433d6423SLionel Sambuc *===========================================================================*/ 225*433d6423SLionel Sambuc #ifdef MDEBUG mthread_cond_verify(void)226*433d6423SLionel Sambucint mthread_cond_verify(void) 227*433d6423SLionel Sambuc { 228*433d6423SLionel Sambuc /* Return true in case no condition variables are in use. */ 229*433d6423SLionel Sambuc 230*433d6423SLionel Sambuc return(vc_front == NULL); 231*433d6423SLionel Sambuc } 232*433d6423SLionel Sambuc #endif 233*433d6423SLionel Sambuc 234*433d6423SLionel Sambuc 235*433d6423SLionel Sambuc /*===========================================================================* 236*433d6423SLionel Sambuc * mthread_cond_wait * 237*433d6423SLionel Sambuc *===========================================================================*/ mthread_cond_wait(cond,mutex)238*433d6423SLionel Sambucint mthread_cond_wait(cond, mutex) 239*433d6423SLionel Sambuc mthread_cond_t *cond; 240*433d6423SLionel Sambuc mthread_mutex_t *mutex; 241*433d6423SLionel Sambuc { 242*433d6423SLionel Sambuc /* Wait for a condition to be signaled */ 243*433d6423SLionel Sambuc mthread_tcb_t *tcb; 244*433d6423SLionel Sambuc struct __mthread_cond *c; 245*433d6423SLionel Sambuc struct __mthread_mutex *m; 246*433d6423SLionel Sambuc 247*433d6423SLionel Sambuc if (cond == NULL || mutex == NULL) 248*433d6423SLionel Sambuc return(EINVAL); 249*433d6423SLionel Sambuc 250*433d6423SLionel Sambuc c = (struct __mthread_cond *) *cond; 251*433d6423SLionel Sambuc m = (struct __mthread_mutex *) *mutex; 252*433d6423SLionel Sambuc 253*433d6423SLionel Sambuc if (!mthread_cond_valid(cond) || !mthread_mutex_valid(mutex)) 254*433d6423SLionel Sambuc return(EINVAL); 255*433d6423SLionel Sambuc 256*433d6423SLionel Sambuc c->mc_mutex = m; /* Remember we're using this mutex in a cond_wait */ 257*433d6423SLionel Sambuc if (mthread_mutex_unlock(mutex) != 0) /* Fails when we're not the owner */ 258*433d6423SLionel Sambuc return(-1); 259*433d6423SLionel Sambuc 260*433d6423SLionel Sambuc tcb = mthread_find_tcb(current_thread); 261*433d6423SLionel Sambuc tcb->m_cond = c; /* Register condition variable. */ 262*433d6423SLionel Sambuc mthread_suspend(MS_CONDITION); 263*433d6423SLionel Sambuc 264*433d6423SLionel Sambuc /* When execution returns here, the condition was met. Lock mutex again. */ 265*433d6423SLionel Sambuc c->mc_mutex = NULL; /* Forget about this mutex */ 266*433d6423SLionel Sambuc tcb->m_cond = NULL; /* ... and condition var */ 267*433d6423SLionel Sambuc if (mthread_mutex_lock(mutex) != 0) 268*433d6423SLionel Sambuc return(-1); 269*433d6423SLionel Sambuc 270*433d6423SLionel Sambuc return(0); 271*433d6423SLionel Sambuc } 272*433d6423SLionel Sambuc 273*433d6423SLionel Sambuc /* pthread compatibility layer. */ 274*433d6423SLionel Sambuc __weak_alias(pthread_cond_init, mthread_cond_init) 275*433d6423SLionel Sambuc 276