/* * Since we are modifying the run queue, we _MUST_ set the IPL to high * so that no interrupts happen at an inopportune moment. * Remember to restore the original IPL before you return from this * function. Otherwise, we will not get any interrupts after returning * from this function. * * Using intr_disable/intr_enable would be equally as effective as * modifying the IPL in this case. However, in some cases, we may want * more fine grained control, making modifying the IPL more * suitable. We modify the IPL here for consistency. */ void sched_make_runnable(kthread_t *thr) { uint8_t prev_ipl = intr_getipl(); intr_setipl(IPL_HIGH); thr->kt_state = KT_RUN; ktqueue_enqueue(&kt_runq, thr); intr_setipl(prev_ipl); /*NOT_YET_IMPLEMENTED("PROCS: sched_make_runnable");*/ }
/* * Since we are modifying the run queue, we _MUST_ set the IPL to high * so that no interrupts happen at an inopportune moment. * Remember to restore the original IPL before you return from this * function. Otherwise, we will not get any interrupts after returning * from this function. * * Using intr_disable/intr_enable would be equally as effective as * modifying the IPL in this case. However, in some cases, we may want * more fine grained control, making modifying the IPL more * suitable. We modify the IPL here for consistency. */ void sched_make_runnable(kthread_t *thr) { /*----Kernel1:PROCS:sched_make_runnable:Begins---*/ KASSERT(thr != NULL); uint8_t old_ipl = apic_getipl(); apic_setipl(IPL_HIGH); KASSERT(&kt_runq != thr->kt_wchan && "thread already on the runq"); thr->kt_state = KT_RUN; ktqueue_enqueue(&kt_runq,thr); apic_setipl(old_ipl); /*----Ends----*/ }
/* * Similar to sleep on, but the sleep can be cancelled. * * Don't forget to check the kt_cancelled flag at the correct times. * * Use the private queue manipulation functions above. */ int sched_cancellable_sleep_on(ktqueue_t *q) { if (curthr->kt_cancelled) return -EINTR; curthr->kt_state = KT_SLEEP_CANCELLABLE; ktqueue_enqueue(q, curthr); sched_switch(); if (curthr->kt_cancelled) return -EINTR; return 0; }
/* * Since we are modifying the run queue, we _MUST_ set the IPL to high * so that no interrupts happen at an inopportune moment. * Remember to restore the original IPL before you return from this * function. Otherwise, we will not get any interrupts after returning * from this function. * * Using intr_disable/intr_enable would be equally as effective as * modifying the IPL in this case. However, in some cases, we may want * more fine grained control, making modifying the IPL more * suitable. We modify the IPL here for consistency. */ void sched_make_runnable(kthread_t *thr) { KASSERT(&kt_runq != thr->kt_wchan); dbg(DBG_PRINT, "(GRADING1A 4.b)\n"); int oldIPL=intr_getipl(); intr_setipl(IPL_HIGH); thr->kt_state = KT_RUN; ktqueue_enqueue(&kt_runq, thr); intr_setipl(oldIPL); /*NOT_YET_IMPLEMENTED("PROCS: sched_make_runnable"); */ }
void sched_broadcast_on(ktqueue_t *q) { kthread_t *temp; while(!list_empty(&(q->tq_list))) { temp = ktqueue_dequeue(q); temp->kt_state = KT_RUN; ktqueue_enqueue(&kt_runq, temp); } sched_queue_init(q); return; }
kthread_t * sched_wakeup_on(ktqueue_t *q) { kthread_t *thr = NULL; if(list_empty(&(q->tq_list))) return NULL; else thr = ktqueue_dequeue(q); KASSERT((thr->kt_state == KT_SLEEP) || (thr->kt_state == KT_SLEEP_CANCELLABLE)); thr->kt_state = KT_RUN; ktqueue_enqueue(&kt_runq, thr); return thr; }
/* * Similar to sleep on, but the sleep can be cancelled. * * Don't forget to check the kt_cancelled flag at the correct times. * * Use the private queue manipulation functions above. */ int sched_cancellable_sleep_on(ktqueue_t *q) { //NOT_YET_IMPLEMENTED("PROCS: sched_cancellable_sleep_on"); if (curthr->kt_cancelled) { return -EINTR; } ktqueue_enqueue(q, curthr); curthr->kt_state = KT_SLEEP_CANCELLABLE; sched_switch(); if (curthr->kt_cancelled) { return -EINTR; } return 0; }
/* * Since we are modifying the run queue, we _MUST_ set the IPL to high * so that no interrupts happen at an inopportune moment. * Remember to restore the original IPL before you return from this * function. Otherwise, we will not get any interrupts after returning * from this function. * * Using intr_disable/intr_enable would be equally as effective as * modifying the IPL in this case. However, in some cases, we may want * more fine grained control, making modifying the IPL more * suitable. We modify the IPL here for consistency. */ void sched_make_runnable(kthread_t *thr) { uint8_t oldIPL = intr_getipl(); /* Check what currently running IPL is */ intr_setipl(IPL_HIGH); /* Block all hardware interrupts */ /* Add thread to run queue */ ktqueue_enqueue(&kt_runq, thr); /* Make thread runnable (just in case it wasn't already) */ thr->kt_state = KT_RUN; intr_setipl(oldIPL); /* Reset IPL level */ /* NOT_YET_IMPLEMENTED("PROCS: sched_make_runnable"); */ }
/* * Similar to sleep on, but the sleep can be cancelled. * * Don't forget to check the kt_cancelled flag at the correct times. * * Use the private queue manipulation functions above. */ int sched_cancellable_sleep_on(ktqueue_t *q) { kthread_t *temp = curthr; temp->kt_state = KT_SLEEP_CANCELLABLE; if(temp->kt_cancelled == 1) return -EINTR; else { ktqueue_enqueue(q, temp); sched_switch(); } return 0; }
/* * Updates the thread's state and enqueues it on the given * queue. Returns when the thread has been woken up with wakeup_on or * broadcast_on. * * Use the private queue manipulation functions above. */ void sched_sleep_on(ktqueue_t *q) { /* enqueue on this get off run queue context_switch */ curthr->kt_state = KT_SLEEP; ktqueue_enqueue(q, curthr); /*Why did i do this? ktqueue_remove(&kt_runq, curthr);*/ sched_switch(); /* NOT_YET_IMPLEMENTED("PROCS: sched_sleep_on");*/ }
/* * Similar to sleep on, but the sleep can be cancelled. * * Don't forget to check the kt_cancelled flag at the correct times. * * Use the private queue manipulation functions above. */ int sched_cancellable_sleep_on(ktqueue_t *q) { if(curthr->kt_cancelled) { dbg(DBG_PRINT, "(GRADING1C 5)\n"); return -EINTR; } curthr->kt_state = KT_SLEEP_CANCELLABLE; ktqueue_enqueue(q, curthr); sched_switch(); if(curthr->kt_cancelled) { dbg(DBG_PRINT, "(GRADING1C 5)\n"); return -EINTR; } dbg(DBG_PRINT, "(GRADING1C 3)\n"); return 0; /* NOT_YET_IMPLEMENTED("PROCS: sched_cancellable_sleep_on"); return 0;*/ }
/* * In this function, you will be modifying the run queue, which can * also be modified from an interrupt context. In order for thread * contexts and interrupt contexts to play nicely, you need to mask * all interrupts before reading or modifying the run queue and * re-enable interrupts when you are done. This is analagous to * locking a mutex before modifying a data structure shared between * threads. Masking interrupts is accomplished by setting the IPL to * high. * * Once you have masked interrupts, you need to remove a thread from * the run queue and switch into its context from the currently * executing context. * * If there are no threads on the run queue (assuming you do not have * any bugs), then all kernel threads are waiting for an interrupt * (for example, when reading from a block device, a kernel thread * will wait while the block device seeks). You will need to re-enable * interrupts and wait for one to occur in the hopes that a thread * gets put on the run queue from the interrupt context. * * The proper way to do this is with the intr_wait call. See * interrupt.h for more details on intr_wait. * * Note: When waiting for an interrupt, don't forget to modify the * IPL. If the IPL of the currently executing thread masks the * interrupt you are waiting for, the interrupt will never happen, and * your run queue will remain empty. This is very subtle, but * _EXTREMELY_ important. * * Note: Don't forget to set curproc and curthr. When sched_switch * returns, a different thread should be executing than the thread * which was executing when sched_switch was called. * * Note: The IPL is process specific. */ void sched_switch(void) { kthread_t *next_thr; /* Somewhere in here: set interrupts to protect run queue intr_setipl(IPL_LOW) or IPL_HIGH, in include/main/interrupt.h */ uint8_t oldIPL = intr_getipl(); /* Check what currently running IPL is */ intr_setipl(IPL_HIGH); /* Block all hardware interrupts */ /* Enqueue requesting thread on run queue if still runnable (dead threads become unschedulable) */ if (curthr->kt_state == KT_RUN) ktqueue_enqueue(&kt_runq, curthr); /* Pick a runnable thread. Take someone off the run queue. */ /* If no threads on run queue, re-enable interrupts and wait for one to occur */ if (sched_queue_empty(&kt_runq)) { intr_wait(); /* Once this returns, there should be a process in the run queue */ } /* Remove a thread from the run queue */ next_thr = ktqueue_dequeue(&kt_runq); /* Manage curproc, curthr */ kthread_t *old_thr = curthr; proc_t *old_proc = curproc; curthr = next_thr; curproc = next_thr->kt_proc; /* Switch context from old context to new context */ context_switch(&old_thr->kt_ctx, &curthr->kt_ctx); /* NOT_YET_IMPLEMENTED("PROCS: sched_switch"); */ }
void sched_make_runnable(kthread_t *thr) { KASSERT(&kt_runq != thr->kt_wchan); static int i = 1; if(thr->kt_proc->p_pid == 0 && i == 1) { sched_queue_init(&kt_runq); i = i+1; } dbg(DBG_THR,"ADDING PROCESS: %s, ON RUN_QUEUE\n", thr->kt_proc->p_comm); uint8_t curr_intr_level = apic_getipl(); apic_setipl(IPL_HIGH); thr->kt_state = KT_RUN; ktqueue_enqueue(&kt_runq,thr); apic_setipl(curr_intr_level); }