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