/** @brief Function to awaken all threads waiting on the * condition variable * * Broadcast signal to wake all threads in the waiting list. * * @param *cv the cond variable that is being broadcasted * @return Void. */ void cond_broadcast (cond_t * cv) { cond_t *node_ptr = NULL; assert (cv != NULL); /* Lock the queue */ spin_lock_request (&cv->spinlock); while (1) { /* Wake up all the thread in the queue */ node_ptr = Q_GET_FRONT (&cv->waiting_list); if (node_ptr == NULL) { lprintf ("In cond_broadcast: no threads!"); break; }else { /* Remove node from waiting list */ Q_REMOVE (&cv->waiting_list, node_ptr, cond_link); /* Make the thread runnable */ make_runnable (node_ptr->tid); /* After move the node, free space */ free (node_ptr); } } /* Unlock the thread */ spin_lock_release (&cv->spinlock); return; }
// need to have the sched lock void wakeup_sleepers(void) { struct timespec time; clock_gettime(CLOCK_REALTIME, &time); thread_t *t; while ((t = Q_GET_FRONT(&state.sleep_queue)) && time_lt(t->sleep_event.u.wakeup, time)) { Q_REMOVE(&state.sleep_queue, t, q_link); Q_INSERT_TAIL(&state.sched_queue, t, q_link); } }
/** @brief Function to wake up a thread waiting on the conditon * variable * * Wake the first thread in the waiting list of the condition * variable. * * @param *cv the cond variable we are signaling * @return void */ void cond_signal (cond_t * cv) { assert (cv != NULL); cond_t *node_ptr = NULL; int tid = DEFAULT_TID; /* Lock the queue */ spin_lock_request (&cv->spinlock); /* Get the head node(thread) in the queue */ node_ptr = Q_GET_FRONT (&cv->waiting_list); /* If there are no thread in the queue, unlock and return */ if (node_ptr == NULL) { lprintf ("No blocked threads!"); spin_lock_release (&cv->spinlock); return; } else { /* If get, remove the first node from the queue */ Q_REMOVE (&cv->waiting_list, node_ptr, cond_link); } /* Got one waitting thread from the queue, unlock the queue */ tid = node_ptr->tid; spin_lock_release (&cv->spinlock); /* Make that thread runnable */ while (make_runnable (tid) < 0) { yield (tid); } /* Free */ free (node_ptr); return; }