Custom-OS-Kernel / phase2 / syscall.c
syscall.c
Raw
#include "../h/syscall.h"

extern pcb_t* currentProcess; // pointer to the current executing process
extern int softBlockCount; // number of soft blocked processes
extern int device_semaphores[49];
extern pcb_t* readyQueue; // tail pointer to the queue of ready pcbs
extern int processCount; // number of started but not terminated processes
extern cpu_t startTime; // start time
state_t* savedException;


void SyscallExceptionHandler(state_t* exception_state)
{

    savedException = exception_state;
    savedException->pc_epc += 4; // increment by 4B to avoid repeat
    unsigned int sysCallCode = 0;
    sysCallCode = (unsigned int) savedException->reg_a0;
    switch (sysCallCode)
    {
        case CREATEPROCESS:
            Create_Process_SYS1(); 
            break;
        case TERMPROCESS:
            Terminate_Process_SYS2();
            break;
        case PASSEREN:
            // Requests the Nucleus to perform a P operation on a semaphore
            Passeren_SYS3((int*) exception_state->reg_a1);
            break;
        case VERHOGEN:
            Verhogen_SYS4((int*) exception_state->reg_a1);
            break;
        case IOWAIT:
            Wait_For_IO_Device_SYS5();
            break;
        case GETTIME:
            Get_CPU_Time_SYS6();
            break;
        case CLOCKWAIT:
            Wait_For_Clock_SYS7();
            break;
        case GETSUPPORTPTR:
            Get_Support_Data_SYS8(exception_state);
            break;
        default:
            PassUpOrDie(GENERALEXCEPT, exception_state);
            break;
    } 
}

void Create_Process_SYS1()
{
    // Create local copies of reg_a1 and reg_a2
    state_t a1Copy = *((state_t*) savedException->reg_a1);
    support_t* a2Copy = (support_t*) savedException->reg_a2;

    pcb_t* allocatedPcb = allocPcb();
    if(allocatedPcb != NULL){
        // the pcb for the process is successfully created
        // PCB tree and queue fields are set to null in allocPcb process
        insertProcQ(&readyQueue, allocatedPcb);
        insertChild(currentProcess, allocatedPcb);

        currentProcess->p_s.reg_v0 = OK;
        processCount++;
        allocatedPcb->p_semAdd = NULL;
        allocatedPcb->p_time = 0;
        allocatedPcb->p_s = a1Copy;
        allocatedPcb->p_supportStruct = a2Copy;
    } else {
        // process creation was unsuccessful
        currentProcess->p_s.reg_v0 = NOPROC;
    }

    LDST(savedException);
}

/*
* This services causes the executing process to cease to exist. In addition, 
* recursively, all progeny of this process are terminated as well. 
*/
void Terminate_Process_SYS2()
{
    if (currentProcess != NULL) {
        // If the current process exists
        outChild(currentProcess);
        TerminateTree(currentProcess);
        currentProcess = NULL;
        Scheduler();
    }
}

/*
 * This method will terminate all children of the current process (referred to as to_terminate) and 
 * should finally terminate the to_terminate itself.
 */
 void TerminateTree(pcb_t* to_terminate)
{
    if (to_terminate == NULL) {
        return;
    }

    while (!emptyChild(to_terminate)) {
        // terminated process has a child process
        pcb_t* removedChild = removeChild(to_terminate);
        TerminateTree(removedChild); // recursively remove all children
    }

    TerminateSingleProcess(to_terminate); // terminate the current process
}

 void TerminateSingleProcess(pcb_t* to_terminate) // declared static so it can only be called in this file's scope.
{
    outProcQ(&readyQueue, to_terminate);
    processCount--;

    if (to_terminate->p_semAdd != NULL) {
        if (to_terminate->p_semAdd >= &(device_semaphores[0]) &&  to_terminate->p_semAdd <= &(device_semaphores[48])) {
            softBlockCount--;
        } else {
            *(to_terminate->p_semAdd) = *(to_terminate->p_semAdd) + 1;
        }
        outBlocked(to_terminate);
    }
    freePcb(to_terminate);
}

void Passeren_SYS3(int* semAddr) 
{   
    (*semAddr) = (*semAddr) - 1; // Decrement the semaphore value
    if (*semAddr < 0) {
        currentProcess->p_s = *savedException;
        int result = insertBlocked(semAddr, currentProcess);
        switch (result) {
            case 0: // false case
                Scheduler();
                break;
            case 1: // true case
                PANIC();
        }
    } else {
        LDST(savedException);
    }
}

void Verhogen_SYS4(int* semAddr) 
{
    (*semAddr) = (*semAddr) + 1; // Increment the semaphore value
    pcb_t* removedPcb = removeBlocked(semAddr);

    if(removedPcb != NULL){
        // The process was in a blocked state
        removedPcb->p_semAdd = NULL;
        insertProcQ(&readyQueue, removedPcb);
    }
    
    LDST(savedException);
    
}

void Wait_For_IO_Device_SYS5()
{
    int deviceNumber;
    // Access the saved exception state
    if (savedException->reg_a1 == 7) {
        // Terminal device
        deviceNumber = 2 * savedException->reg_a2 + savedException->reg_a3;
    } else {
        // Non-terminal device
        deviceNumber = savedException->reg_a2;
    }

    // Calculate semaphore index
    int semIndex = (savedException->reg_a1 - 3) * 8 + deviceNumber;

    // Increment soft block count
    softBlockCount++;

    // Perform the P operation on the device semaphore
    Passeren_SYS3(&device_semaphores[semIndex]);
}

/* This service requests that the accumulated processor
 * (in microseconds) used by the requesting process be placed/returned in the caller’s v0. 
 */
void Get_CPU_Time_SYS6()
{
    currentProcess->p_time += (CURRENT_TOD - startTime);
    savedException->reg_v0 = currentProcess->p_time;
    STCK(startTime);
    LDST(savedException);
}

/* 
 * This service performs a P operation on the Nucleus maintained pseudo-clock semaphore
 */
void Wait_For_Clock_SYS7() 
{
    softBlockCount++;
    Passeren_SYS3(&device_semaphores[48]); // call SYS3
}

/* 
 * This service requests a pointer to the current process's support structure.
 * If no value for p_supportStruct was provided for the current process when it was created,
 * return NULL.
 */
void Get_Support_Data_SYS8()
{
    savedException->reg_v0 = (unsigned int) currentProcess->p_supportStruct;    
    LDST(savedException);
}