/*
 * 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)
{
	/* Do I need to enque prevthr?
	 * Do I need to continue running prevthr if it is still runnable */
	/*for bugs check Run Queue Access Slide */

	uint8_t prev_ipl = intr_getipl();
	intr_setipl(IPL_HIGH);
	
	kthread_t *prevthr = curthr;
	
	if (prevthr->kt_state == KT_RUN)
		ktqueue_enqueue(&kt_runq, prevthr);

	while (sched_queue_empty(&kt_runq)) { 
		panic("I never actually wait on things here");
		intr_setipl(IPL_LOW);
		intr_wait();
		intr_setipl(IPL_HIGH);
	}
	/*If there is a thread*/
	kthread_t *t = ktqueue_dequeue(&kt_runq);
	
	curproc = t->kt_proc;
	curthr = t; 
       /* NOT_YET_IMPLEMENTED("PROCS: sched_switch");*/
	context_switch(&prevthr->kt_ctx, &curthr->kt_ctx);
		intr_setipl(prev_ipl);	

}
Exemple #2
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)
{
        //NOT_YET_IMPLEMENTED("PROCS: sched_make_runnable");
        uint8_t orig_ipl = intr_getipl();
        intr_setipl(IPL_HIGH);
        thr->kt_state = KT_RUN;
        ktqueue_enqueue(&kt_runq, thr);
        intr_setipl(orig_ipl);
}
Exemple #3
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"); */
}
Exemple #4
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");
        */
}
Exemple #5
0
void
vt_unblock_io(tty_driver_t *ttyd, void *data)
{
        uint8_t oldipl = (uint8_t)(uintptr_t)data;
        KASSERT(NULL != ttyd);

        KASSERT(intr_getipl() == INTR_KEYBOARD &&
                "Virtual terminal I/O not blocked");
        intr_setipl(oldipl);
}
Exemple #6
0
void *
vt_block_io(tty_driver_t *ttyd)
{
        uint8_t oldipl;
        KASSERT(NULL != ttyd);

        oldipl = intr_getipl();
        intr_setipl(INTR_KEYBOARD);
        return (void *)(uintptr_t)oldipl;
}
Exemple #7
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)
{
        //NOT_YET_IMPLEMENTED("PROCS: sched_switch");
        uint8_t orig_ipl = intr_getipl();
        intr_setipl(IPL_HIGH);
        while (sched_queue_empty(&kt_runq)) {
                intr_setipl(IPL_LOW);
                intr_wait();
                intr_setipl(IPL_HIGH);
        }
        kthread_t *thr = ktqueue_dequeue(&kt_runq);
        context_t *old_context = &(curthr->kt_ctx);
        context_t *new_context = &(thr->kt_ctx);
        curthr = thr;
        curproc = thr->kt_proc;
        context_switch(old_context, new_context);
        intr_setipl(orig_ipl);
}
Exemple #8
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)
{
    /* dbg(DBG_PRINT, "(In sched switch)\n");*/
    kthread_t *oldthr;
    int oldIPL;
    oldIPL=intr_getipl();
    intr_setipl(IPL_HIGH);
    while(sched_queue_empty(&kt_runq)) {
        intr_disable();
        intr_setipl(0);
        intr_wait();
        intr_setipl(IPL_HIGH);
    }
    oldthr=curthr;
    curthr=ktqueue_dequeue(&kt_runq);
    curproc = curthr->kt_proc;
    context_switch(&(oldthr->kt_ctx),&(curthr->kt_ctx));
    intr_setipl(oldIPL);
    dbg(DBG_PRINT, "(GRADING1C 1)\n");
    /*NOT_YET_IMPLEMENTED("PROCS: sched_switch");*/
}
Exemple #9
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"); */
}