Custom-OS-Kernel / phase3 / sysSupport.c
sysSupport.c
Raw
#include "../h/sysSupport.h"
#include "../h/syscall.h"
#include "../h/libraries.h"

extern swap_t swapPoolTable[POOLSIZE];
extern int supportDeviceSemaphore[3][UPROCMAX]; // 3 device semaphores for printer, terminal receiver and terminal transmitter
extern int flashSemaphores[UPROCMAX];

extern int master_sem;

void GeneralException_Handler()
{
    
    support_t* supportPointer = (support_t*) SYSCALL(GETSUPPORTPTR, 0, 0, 0); // Get access to the support info of the current process
    
    int exceptionCode = GET_EXEC_CODE(supportPointer->sup_exceptState[GENERALEXCEPT].cause);

    if (exceptionCode >= 9) {
        Terminate_SYS9(supportPointer);
        return;
    }
    
    int sysnumber = (int) supportPointer->sup_exceptState[GENERALEXCEPT].reg_a0;
    supportPointer->sup_exceptState[GENERALEXCEPT].pc_epc = supportPointer->sup_exceptState[GENERALEXCEPT].pc_epc + 4;
    
    switch (sysnumber)
    {
        case TERMINATE:
            Terminate_SYS9(supportPointer);
            break;

        case GET_TOD:
            Get_Tod_SYS10(supportPointer);
            break;

        case WRITEPRINTER:
            Write_To_Printer_SYS11(supportPointer);
            break;

        case WRITETERMINAL:
            Write_to_Terminal_SYS12(supportPointer);
            break;

        case READTERMINAL:
            Read_From_Terminal_SYS13(supportPointer);
            break;

        default:
            Terminate_SYS9(supportPointer);
            break;
    }

    LDST((state_t*) &(supportPointer->sup_exceptState[GENERALEXCEPT]));
   
}   
/*
void Terminate_SYS9(support_t* sPtr) 
{
    SYSCALL(VERHOGEN, (int) &master_sem, 0, 0);
    deleteSwTbEntries(sPtr->sup_asid); // Clear entries in the swap pool table

    // Any device semaphore being held should be released
    for (int device = 0; device < 3; device++) {
        if (sPtr->sup_asid - 1 <= 0) {
            SYSCALL(VERHOGEN, (int) &(supportDeviceSemaphore[device][(sPtr->sup_asid) - 1]), 0, 0);
        }
    }

    if (flashSemaphores[(sPtr->sup_asid) - 1] <= 0) {
        SYSCALL(VERHOGEN, (int) &(flashSemaphores[(sPtr->sup_asid) - 1]), 0, 0);
    }
}
*/

void Terminate_SYS9(support_t* sPtr) // sys2 wrapper 
{
    // cleaning the entries on the swap table
    deleteSwTbEntries(sPtr->sup_asid);

    // checking if the process to be terminated is holding any mutex semaphore
    // in that case use a SYS4 to free it and terminate it with sys2
    
    for (int i = 0; i < SUPP_SEM_N; i++) 
    {
        if (supportDeviceSemaphore[i][sPtr->sup_asid - 1] <= 0)  // i is the device semaphore line, asid represents the device 
            SYSCALL(VERHOGEN, (int) &supportDeviceSemaphore[i][sPtr->sup_asid - 1], 0, 0); 
    }

    if (flashSemaphores[sPtr->sup_asid - 1] <= 0)
        SYSCALL(VERHOGEN, (int) &flashSemaphores[sPtr->sup_asid - 1], 0, 0); 

    // waking up the test proc
    SYSCALL(VERHOGEN, (int) &master_sem, 0, 0);

    SYSCALL(TERMPROCESS, 0, 0, 0);  
}

void Get_Tod_SYS10(support_t* sPtr) 
{
    unsigned int timeofDay;

    STCK(timeofDay); // population of timeofDay with current time of day

    sPtr->sup_exceptState[1].reg_v0 = (unsigned int) timeofDay;
}

void Write_To_Printer_SYS11(support_t* sPtr)
{
    // Get the address of the device register associated with the printer
    devreg_t* deviceRegister = GET_DEV_ADDR(6, ((sPtr->sup_asid) - 1));

    // Gain mutual exclusion on the printer device semaphore
    SYSCALL(PASSEREN, (int) &(supportDeviceSemaphore[0][(sPtr->sup_asid) - 1]), 0, 0);

    int stringLength = (int) sPtr->sup_exceptState[1].reg_a2; // length of the passed string

    char* s_addr = (char*) sPtr->sup_exceptState[1].reg_a1; // address of the first character of the string

    int charTransmitted = 0;
    unsigned int printerStatus;

    // Transmit all characters in length
    for (charTransmitted = 0; charTransmitted < stringLength; charTransmitted++) {
        deviceRegister->dtp.data0 = *s_addr;

        DISABLE_INTERRUPTS_COMMAND; // ATOMIC
        deviceRegister->dtp.command = 2;
        SYSCALL(IOWAIT, 6, (sPtr->sup_asid) - 1, 0);
        ENABLE_INTERRUPTS_COMMAND; // ATOMIC END
        
        printerStatus = deviceRegister->dtp.status;

        if (printerStatus != 1) {
            // Error
            printerStatus = printerStatus*(-1);
            break;
        }

        //No error
        s_addr = s_addr + 1;
        charTransmitted = charTransmitted + 1;
    }

    sPtr->sup_exceptState->reg_v0 = charTransmitted;
    SYSCALL(VERHOGEN, (int) &(supportDeviceSemaphore[0][(sPtr->sup_asid) - 1]), 0, 0);

}


// Communicate with the TERMINAL device
void Write_to_Terminal_SYS12(support_t* sPtr) 
{
    devreg_t* deviceRegister = GET_DEV_ADDR(7, ((sPtr->sup_asid) - 1));

    SYSCALL(PASSERN, (memaddr) &supportDeviceSemaphore[1][(sPtr->sup_asid) - 1], 0, 0); // Gain mutual exclusion

    int stringLength = (int) sPtr->sup_exceptState[1].reg_a2;

    char* s_addr = (char*) sPtr->sup_exceptState[1].reg_a1;

    int charTransmitted = 0;
    unsigned int terminalStatus;

if( (memaddr) s_addr >= 0x80000000 && stringLength >=0 && stringLength <=128) {
    for (charTransmitted = 0; charTransmitted < stringLength; charTransmitted++) {
        DISABLE_INTERRUPTS_COMMAND;
        deviceRegister->term.transm_command = ((unsigned int) *s_addr << 8) | 2;
        // Constructs a transmitter command by embedding the address in the 
        // higher-order bits and a specific command (2) in the lower-order bits, then assigns it to the device register
        terminalStatus = SYSCALL(IOWAIT, 7, (sPtr->sup_asid) - 1, 0);
        ENABLE_INTERRUPTS_COMMAND;
        if ((terminalStatus & 0xFF) != 5) {
            // error
            terminalStatus = terminalStatus * (-1);
            break;
        }

        // not error
        s_addr = s_addr + 1;
        //charTransmitted = charTransmitted + 1;  //I changed this (incrementing is already being done in the for loop (while loop would have required this)
    }
    }
    else {
    	Terminate_SYS9(sPtr);    //I changed code here (added the missing else condition)
    }
    

    sPtr->sup_exceptState[1].reg_v0 = charTransmitted;
    SYSCALL(VERHOGEN, (int) &supportDeviceSemaphore[1][(sPtr->sup_asid) - 1], 0, 0);
}


void Read_From_Terminal_SYS13(support_t* sPtr) 
{
    devreg_t* deviceRegister = GET_DEV_ADDR(7, ((sPtr->sup_asid) - 1));
    
    SYSCALL(PASSERN, (int) &supportDeviceSemaphore[2][(sPtr->sup_asid) - 1], 0, 0); // Gain mutual exclusion

    char* s_addr = (char*) sPtr->sup_exceptState[1].reg_a1; // address of the first character in the string

    int charTransmitted = 0;
    unsigned int terminalStatus;

if( (memaddr) s_addr >= 0x80000000) {  //I changed this (added this missing if)

    while(1) { // terminates when new line is read
        DISABLE_INTERRUPTS_COMMAND;
        deviceRegister->term.recv_command = 2;
        terminalStatus = SYSCALL(IOWAIT, 7, (sPtr->sup_asid) - 1, 1);
        ENABLE_INTERRUPTS_COMMAND;

        if ((terminalStatus & 0xFF) != 5) {
            // failed read operation
            charTransmitted = ((terminalStatus >> 8) & 0xFF) * (-1);
            break;
        }
        else {

        // successful read operation
        charTransmitted = charTransmitted + 1;
        *s_addr = (terminalStatus >> 8) & 0xFF;
        char currentChar = *s_addr;
        s_addr = s_addr + 1;
        if (currentChar == '\n') {
            break;
        }
    }
    }
    }
    else {
    	Terminate_SYS9(sPtr);  //I changed code here (added the missing else condition)
    }

    sPtr->sup_exceptState[1].reg_v0 = charTransmitted;
    SYSCALL(VERHOGEN, (int) &supportDeviceSemaphore[2][(sPtr->sup_asid) - 1], 0, 0); //I changed this .. & was missing
}



// Clear all those entries in the swap pool table that are related to a specific process whose ASID
// matches the asid value passed in
void deleteSwTbEntries(int asid)
{
    for (int i = 0; i < POOLSIZE; i++) {
        if (swapPoolTable[i].sw_asid == asid) {
            swapPoolTable[i].sw_asid = NOPROC;
        }
    }
}