Exemplo n.º 1
0
Arquivo: cpu.c Projeto: DuyH/TCSS422
void CPU_pseudo_isr(CPU_p cpu, int PC) {
    if (cpu->currentProcess != NULL) {
        fprintf(file, "Timer interrupt...\n");

        // 1. Change the state of the running process to interrupted
        PCB_set_state(cpu->currentProcess, interrupted);

        // 2. Save the CPU state to the PCB
        PCB_set_pc(cpu->currentProcess, cpu->pc);

        fprintf(file, "Process interrupted: %s",
                PCB_toString(cpu->currentProcess));

        //Replace PC of CPU will value stored in systemStack
        cpu->pc = cpu->sysStack;

        //cpu->pc = CPU_pop_sysStack(cpu);

        // 3. "Do an up-call" to the scheduler
        CPU_scheduler(cpu, timer, PC);

    } else {
        fprintf(file, "No process currently running. Normal interrupt...\n");
        CPU_scheduler(cpu, normal, PC);
    }

    return;
}
Exemplo n.º 2
0
Arquivo: cpu.c Projeto: DuyH/TCSS422
void CPU_scheduler(CPU_p cpu, Interrupt_type interrupt_type, int PC) {
    while (!Queue_isEmpty(cpu->newProcessesQueue)) {
        PCB_p temp_pcb = Queue_dequeue(cpu->newProcessesQueue);
        PCB_set_state(temp_pcb, ready);
        //PCB_set_pc(temp_pcb, PC);
        Queue_enqueue(cpu->readyQueue, temp_pcb);
        fprintf(file, "Process ID: %u Enqueued\n", temp_pcb->pid);
        fprintf(file, "%s", PCB_toString(temp_pcb));
    }
    fprintf(file, "\n");
    switch (interrupt_type) {
        case timer:
            // 1. Put process back into the readyQueue
            Queue_enqueue(cpu->readyQueue, cpu->currentProcess);

            // 2. Change its state from interrupted to ready
            PCB_set_state(cpu->currentProcess, ready);

            // 3. Make call to dispatcher
            CPU_dispatcher(cpu, timer);

            // 4. Returned from dispatcher, do any housekeeping
            // Nothing here to do at the moment!

            // 5. Returns to pseudo-ISR
            return;
            break;
        default:
            CPU_dispatcher(cpu, normal);
            break;
    }
    return;
}
Exemplo n.º 3
0
void execute_ISR(Interrupt interrupt) {
    int error;

    switch (interrupt) {
        case timer_interrupt: {
            current_pcb->state = interrupted;

            char *PCB_string = PCB_toString(current_pcb, &error);
            printf("Timer interrupt during %s\n", PCB_string);
            free(PCB_string);

            runScheduler(timer_interrupt);
            break;
        }
        case io1_interrupt: {
            current_pcb->state = interrupted;

            printf("I/O 1 Trap request complete.\n");
            runScheduler(io1_interrupt);

            current_pcb->state = running;
            break;
        }
        case io2_interrupt: {
            current_pcb->state = interrupted;

            printf("I/O 2 Trap request complete.\n");
            runScheduler(io2_interrupt);

            current_pcb->state = running;
            break;
        }
        case trap_interrupt: {
            current_pcb->state = interrupted;

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("Trap requested by %s\n", PCB_string);

            execute_TSR(trap);

            break;
        }
        case no_interrupt:
            // This shouldn't happen here.
            break;
    }
}
Exemplo n.º 4
0
Arquivo: cpu.c Projeto: DuyH/TCSS422
void CPU_dispatcher(CPU_p cpu, Interrupt_type interrupt_type) {

    // Save pointers to the previous and next process (needed so we can print)
    PCB_p prevProcess = cpu->currentProcess;
    PCB_p nextProcess = Queue_peek(cpu->readyQueue);
    if (CTX_SWITCH_COUNT % 4 == 0) {
    	if (prevProcess != NULL)
    		fprintf(file, "Running process: %s", PCB_toString(prevProcess));
    	if (nextProcess != NULL)
    		fprintf(file, "Switching to: %s", PCB_toString(nextProcess));
    }
    // 1. Save the state of current process into its PCB (PC value)
    // Per Canvas Discussions, DON'T DO THIS AGAIN HERE! It's in ISR.

    // 2. Then dequeue next waiting process
    if (!Queue_isEmpty(cpu->readyQueue))
        cpu->currentProcess = Queue_dequeue(cpu->readyQueue);

    // 3. Change its state to running
    PCB_set_state(cpu->currentProcess, running);

    if (interrupt_type == timer) {
        // 4. Copy its PC value to sysStack, replacing the interrupted process
        CPU_push_sysStack(cpu, PCB_get_PC(cpu->currentProcess));
    } else if (interrupt_type == normal) {
        CPU_set_pc(cpu, cpu->sysStack);
    }

    if (CTX_SWITCH_COUNT % 4 == 0) {
    	if (prevProcess != NULL)
    		fprintf(file, "Last Process: %s", PCB_toString(prevProcess));
    	if (nextProcess != NULL)
    		fprintf(file, "Current running Process: %s", PCB_toString(nextProcess));
    	fprintf(file, "Ready Queue: %s", Queue_toString(cpu->readyQueue, 0));
    }

    // 5. Return to the scheduler
    // returns prevalent stuff to scheduler, but not for this project
    return;
}
Exemplo n.º 5
0
void OS_loop() {
    int error;

    topOffProcesses();

    // Run the current process until the next interrupt or trap call.
    char* string = PCB_toString(current_pcb, &error);
    printf("Now Running: %s\n", string);
    free(string);
    Interrupt interrupt = CPU_run();

    execute_ISR(interrupt);
}
Exemplo n.º 6
0
void runDispatcher() {
    int error;

    if(PriorityQ_isEmpty(ready_PCBs, &error)) {
        current_pcb = idle_pcb;
    } else {
        current_pcb = PriorityQ_dequeue(ready_PCBs, &error);
    }
    CPU_setTimer(TIMER_QUANTUM);

    char* string = PCB_toString(current_pcb, &error);
    printf("Switching to: %s\n", string);
    free(string);

    current_pcb->state = running;
}
Exemplo n.º 7
0
void execute_TSR(TSR routine) {
    int error;

    switch (routine) {
        case io1_trap: {
            current_pcb->state = waiting;
            FIFOq_enqueue(io1_PCBs, current_pcb, &error);

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("I/O 1 Trap requested by %s\n", PCB_string);
            free(PCB_string);

            runScheduler(trap_interrupt);
            break;
        }
        case io2_trap: {
            current_pcb->state = waiting;
            FIFOq_enqueue(io2_PCBs, current_pcb, &error);

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("I/O 2 Trap requested by %s\n", PCB_string);
            free(PCB_string);

            runScheduler(trap_interrupt);
            break;
        }
        case terminate_trap: {
            current_pcb->state = terminated;
            current_pcb->termination = time(NULL);
            FIFOq_enqueue(terminated_PCBs, current_pcb, &error);
            processes_terminated++;

            // Unlock any mutexes that this terminated PCB may have.
            if (current_pcb->type == consumer || current_pcb->type == producer || current_pcb->type == resource_user_A) {
                Mutex_remove(current_pcb->mutex_A, current_pcb);
            } else  if (current_pcb->type == resource_user_B) {
                Mutex_remove(current_pcb->mutex_B, current_pcb);
            }

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("Terminated process: %s\n", PCB_string);
            free(PCB_string);
            current_pcb = NULL;

            runScheduler(trap_interrupt);
            break;
        }
        case mutex_lock_trap:
            if (current_pcb->type == resource_user_A) {
                // If this is a resource_user "A" process lock mutex A then B.
                if (!Mutex_Is_Locked(current_pcb->mutex_A) || current_pcb->mutex_A->key != current_pcb) {
                    mutexLock(current_pcb, current_pcb->mutex_A);
                } else if (!Mutex_Is_Locked(current_pcb->mutex_B) || current_pcb->mutex_B->key != current_pcb) {
                    mutexLock(current_pcb, current_pcb->mutex_B);
                }
            } else if (current_pcb->type == resource_user_B) {
                // If this is a resource_user "B" process then lock A then B if no-deadlock, and B then A if deadlock.
                if (!deadlock) {
                    if (!Mutex_Is_Locked(current_pcb->mutex_A) || current_pcb->mutex_A->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_A);
                    } else if (!Mutex_Is_Locked(current_pcb->mutex_B) || current_pcb->mutex_B->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_B);
                    }
                } else {
                    if (!Mutex_Is_Locked(current_pcb->mutex_B) || current_pcb->mutex_B->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_B);
                    } else if (!Mutex_Is_Locked(current_pcb->mutex_A) || current_pcb->mutex_A->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_A);
                    }
                }
            } else {
                mutexLock(current_pcb, current_pcb->mutex_A);
            }
            break;
        case mutex_unlock_trap:
            if (current_pcb->type == resource_user_A) {
                // If this is a resource_user "A" process unlock mutex B then A.
                if (Mutex_Is_Locked(current_pcb->mutex_B)) {
                    mutexUnlock(current_pcb, current_pcb->mutex_B);
                } else if (Mutex_Is_Locked(current_pcb->mutex_A)) {
                    mutexUnlock(current_pcb, current_pcb->mutex_A);
                }
            } else if (current_pcb->type == resource_user_B) {
                // If this is a resource_user "B" process then unlock B then A if no-deadlock, and A then B if deadlock.
                if (!deadlock) {
                    if (Mutex_Is_Locked(current_pcb->mutex_B)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_B);
                    } else if (Mutex_Is_Locked(current_pcb->mutex_A)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_B);
                    }
                } else {
                    if (Mutex_Is_Locked(current_pcb->mutex_A)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_A);
                    } else if (Mutex_Is_Locked(current_pcb->mutex_B)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_B);
                    }
                }
            } else {
                mutexUnlock(current_pcb, current_pcb->mutex_A);
            }
            break;
        case condition_signal_and_wait_trap:
            printf("PID %lu: sent signal on condition %lu\n", current_pcb->PID, current_pcb->conditional_variable->ID);

            PCB_p returnedPCB = Condition_signal(current_pcb->conditional_variable, current_pcb);
            if (returnedPCB != NULL) {
                returnedPCB->state = ready;
                PriorityQ_enqueue(ready_PCBs, returnedPCB, &error);
            }

            printf("PID %lu: requested wait on condition %lu with mutex M%lu\n", current_pcb->PID,
                   current_pcb->conditional_variable->ID, current_pcb->mutex_A->ID);
            Condition_wait(current_pcb->conditional_variable, current_pcb->mutex_A, current_pcb);
            current_pcb->state = waiting;
            // Don't enqueue the current PCB as now it's waiting.

            // Interrupt this PCB and run the scheduler to dispatch the next process.
            runScheduler(trap_interrupt);
            break;
        case no_trap:
            // This shouldn't happen here.
            break;
    }
}
Exemplo n.º 8
0
void runScheduler(Interrupt interrupt) {
    int error;

    // Add any newly created PCBs to the ready queue.
    while (!FIFOq_isEmpty(new_PCBs, &error)) {
        PCB_p newPCB = FIFOq_dequeue(new_PCBs, &error);
        newPCB->state = ready;
        PriorityQ_enqueue(ready_PCBs, newPCB, &error);
        char* string = PCB_toString(newPCB, &error);
        printf("Added to ready queue: %s\n", string);
        free(string);
    }

    switch (interrupt) {
        case timer_interrupt:
            current_pcb->state = ready;

            // Put the interrupted process into the ready queue (if it's not the idle process).
            if (current_pcb != idle_pcb) {
                // If this is a boosted PCB, we can unboost it
                if(current_pcb->priority_boost) {
                    current_pcb->priority_boost = 0;
                }

                PriorityQ_enqueue(ready_PCBs, current_pcb, &error);
                char* string = PCB_toString(current_pcb, &error);
                printf("Returned to ready queue: %s\n", string);
                free(string);
            }

            runDispatcher();
            break;
        case io1_interrupt: {
            PCB_p completedIOPCB = FIFOq_dequeue(io1_PCBs, &error);
            completedIOPCB->state = ready;
            PriorityQ_enqueue(ready_PCBs, completedIOPCB, &error);

            char* PCB_string = PCB_toString(completedIOPCB, &error);
            printf("Returned to ready queue: %s\n", PCB_string);
            free(PCB_string);
            break;
        }
        case io2_interrupt: {
            PCB_p completedIOPCB = FIFOq_dequeue(io2_PCBs, &error);
            completedIOPCB->state = ready;
            PriorityQ_enqueue(ready_PCBs, completedIOPCB, &error);

            char* PCB_string = PCB_toString(completedIOPCB, &error);
            printf("Returned to ready queue: %s\n", PCB_string);
            free(PCB_string);
            break;
        }
        case trap_interrupt:
            // The current PCB has been placed in it's appropriate queue by the TSR,
            // so just run the dispatcher to dispatch the next process in line.
            runDispatcher();
            break;
        case no_interrupt:
            // This shouldn't happen here.
            break;
    }

    // Housekeeping work.
    starvationDetection();
    // Only do this every tenth time.
    static int count = 10;
    count--;
    if (count == 0) {
        deadlockDetection();
        count = 10;
    }

    // Free all terminated PCBs.
    while (!FIFOq_isEmpty(terminated_PCBs, &error)) {
        PCB_p terminatedPCB = FIFOq_dequeue(terminated_PCBs, &error);
        char* string = PCB_toString(terminatedPCB, &error);
        printf("Freeing terminated PCB: %s\n", string);
        free(string);
        PCB_destruct(terminatedPCB);
    }
}