int fthread_cond_wait(fthread_cond_t *cond, fthread_mutex_t *mutex) { if (cond->__waitm) { /* there should only be one mutex being used for concurrent waits on a single condition variable */ if (cond->__waitm != mutex) { return EINVAL; } } else { cond->__waitm = mutex; } /* we also need to own the mutex */ int err = fthread_mutex_unlock(mutex); if (err) { return err; } /* can't destroy a mutex while it's being used in a cond_wait: * have to up the use count so any calls to destroy will fail with * EBUSY */ mutex->__usecount++; cond->__usecount++; sched_sleep_on(&cond->__waitq); fthread_mutex_lock(mutex); mutex->__usecount--; cond->__usecount--; return 0; }
/* * A thread function that uncancellably waits on wake_me_q and exist when * released. */ void *wakeme_uncancellable_test(int arg1, void *arg2) { wake_me_len++; sched_sleep_on(&wake_me_q); wake_me_len--; do_exit(arg1); return NULL; }
void check_sleep(char *str) { if (random_function() % 10 < 5) { dbg(DBG_TEST, "Thread %s goes to sleep\n", str); sched_broadcast_on(&mynode.my_queue); sched_sleep_on(&mynode.my_queue); dbg(DBG_TEST, "Thread %s awake\n", str); } }
int fthread_barrier_wait(fthread_barrier_t *barrier) { if (++barrier->__waiting == barrier->__max) { barrier->__waiting = 0; sched_broadcast_on(&barrier->__waitq); return FTHREAD_BARRIER_SERIAL_THREAD; } sched_sleep_on(&barrier->__waitq); return 0; }
static void * watch_dog(int arg1, void *arg2) { while(!sched_queue_empty(&mynode.my_queue)) { dbg(DBG_TEST, "Watch_dog wake up all sleeping thread\n"); sched_broadcast_on(&mynode.my_queue); sched_sleep_on(&mynode.my_queue); } return NULL; }
/* * This should block the current thread (by sleeping on the mutex's * wait queue) if the mutex is already taken. * * No thread should ever try to lock a mutex it already has locked. */ void kmutex_lock(kmutex_t *mtx) { /* NOT_YET_IMPLEMENTED("PROCS: kmutex_lock");*/ if(mtx->km_holder!=NULL) { sched_sleep_on(&mtx->km_waitq); } else { KASSERT(curthr!=mtx->km_holder && "the current thread already has the mutex"); mtx->km_holder=curthr; } }
/* This test checks to make sure that when you sleep * threads, and broadcast later, they are popped in the * right order */ void *broadcast_order(int arg1, void *arg2) { int local,local2; if ( kmutex_lock_cancellable(&mutex) ) { dbg_print("Mutex cancelled? %d", curproc->p_pid); do_exit(-1); } local = race2; local++; race2 = local; kmutex_unlock(&mutex); wake_me_len2++; sched_sleep_on(&wake_me_q); wake_me_len2--; if ( kmutex_lock_cancellable(&mutex) ) { dbg_print("Mutex cancelled? %d", curproc->p_pid); do_exit(-1); } local2 = race2; local2++; race2 = local2; kmutex_unlock(&mutex); dbg_print("broadcast_order: Local: %i ", local); dbg_print("Local2: %i\n", local2); KASSERT(local == local2 && "Error on broadcast_order"); do_exit(local); /*dbg_print("mutex_test: Local: %i\n", local);*/ return NULL; }