Custom-OS-Kernel / phase2 / asl.c
asl.c
Raw

#include "../h/asl.h"

static semd_t* semdFree_h;     // free
semd_t* semd_h;         // active
static semd_t semdTable[MAXPROC + 2];


/*
 * Function:  insertBlocked
 * --------------------
 *  Insert the PCB pointed to by p at the tail of the process queue
 *  associated with the semaphore whose physical address is semAdd
 *  and set the semaphore address of p to semdAdd.
 *
 *  semAdd: pointer to semaphore value
 *  p: pointer to PCB
 *
 *  returns: returns 1 if semaphore is not in ASL and semdFree is empty
 *           returns 0 otherwise
 */
int insertBlocked(int *semAdd, pcb_t *p)
{
    int found = 0;
    semd_t* current = semd_h;
    
    while(current->s_semAdd <= semAdd){
        if(current->s_semAdd == semAdd){
            found = 1;
            break;
        }
        current = current->s_next;
    }


    if (found) {
        // Semaphore found in ASL
        insertProcQ(&(current->s_procQ), p);
    } else {
        // Semaphore not found in ASL

        if(semdFree_h == NULL){
            return 1;
        }

        // Get new semaphore from head of free list
        semd_t* semNew = semdFree_h;
        semdFree_h = semdFree_h->s_next;

        // Place new semaphore in ASL
        semd_t* current = semd_h;

        while(current->s_next->s_semAdd <= semAdd) {
            current = current->s_next;
        }

        semNew->s_next = current->s_next;
        current->s_next = semNew;
        semNew->s_semAdd = semAdd;
        semNew->s_procQ = mkEmptyProcQ();

        insertProcQ(&(semNew->s_procQ), p);

    }
    p->p_semAdd = semAdd;
    return 0;
}


/*
 * Function:  removeBlocked
 * --------------------
 *  Removes the first PCB from the process queue of the semaphore.
 *
 *  semAdd: pointer to semaphore value
 *
 *  returns: returns pointer to PCB removed if semaphore found
 *           returns NULL otherwise
 */
pcb_t* removeBlocked(int *semAdd)
{
    int found = 0;
    semd_t* prev = NULL;
    semd_t* current = semd_h;
    
    while(current->s_semAdd <= semAdd){
        if(current->s_semAdd == semAdd){
            found = 1;
            break;
        }
        prev = current;
        current = current->s_next;
    }


    if(!found){
        // Semaphore is not found in ASL
        return NULL;
    }

    // Remove the first PCB from process queue
    pcb_t* removed = removeProcQ(&(current->s_procQ));


    if(emptyProcQ(current->s_procQ)){
        // Process queue is empty, remove the semaphore from ASL
        if (prev != NULL) {
            prev->s_next = current->s_next;
        } else {
            return removed;
        }

        // Return the semaphore to the free list
        current->s_next = semdFree_h;
        semdFree_h = current;
    }

    return removed;
}


/*
 * Function:  outBlocked
 * --------------------
 *  Remove the PCB pointed to by p from the process queue associate with
 *  p's semaphore (p -> p_semAdd) on the ASL.
 *
 *  p: pointer to PCB
 *
 *  returns: returns pointer to PCB removed if semaphore found and p
 *              if found in the process queue
 *           returns NULL otherwise
 */
pcb_t* outBlocked(pcb_t *p)
{
    int found = 0;
    semd_t* prev = NULL;
    semd_t* current = semd_h;
    
    while(current->s_semAdd <= p->p_semAdd){
        if(current->s_semAdd == p->p_semAdd){
            found = 1;
            break;
        }
        prev = current;
        current = current->s_next;
    }

    if(!found){
        // Semaphore not found in ASl
        return NULL;
    }

    pcb_t* result = outProcQ(&(current->s_procQ), p);

    if(result == NULL){
        return result;
    }

    p->p_semAdd = NULL;

    if(emptyProcQ(current->s_procQ)){
        // Process queue is empty, remove the semaphore from ASL
        if (prev != NULL) {
            prev->s_next = current->s_next;
        } else {
            return result;
        }

        // Return the semaphore to the free list
        current->s_next = semdFree_h;
        semdFree_h = current;
    }
    
    return result;
}


/*
 * Function:  headBlocked
 * --------------------
 *  Return (without removal) a pointer to the PCB that is at the head
 *  head of the process queue associated with the semaphore semAdd.
 *
 *  p: pointer to PCB
 *
 *  returns: returns pointer to PCB at the head of the process queue if
 *              semAdd found and the queue is non-empty
 *           returns NULL otherwise
 */
pcb_t* headBlocked(int *semAdd)
{
    int found = 0;
    semd_t* current = semd_h;
    
    while(current->s_semAdd <= semAdd){
        if(current->s_semAdd == semAdd){
            found = 1;
            break;
        }
        current = current->s_next;
    }

    if(!found){
        // Semaphore not found in ASL
        return NULL;
    }

    if(current->s_procQ == NULL){
        // Semaphore has empty process queue
        return NULL;
    }


    return current->s_procQ->p_next;
}



/*
 * Function:  initASL
 * --------------------
 *  Initialize the semdFree list to contain all the elements of
 *  the array.
 *
 */
void initASL()
{
    // Free list
    semdFree_h = &semdTable[1];

    for(int i = 1; i< MAXPROC; i++){
        semdTable[i].s_next = &semdTable[i+1];
    }

    semdTable[MAXPROC].s_next = NULL;


    // Active list
    semd_h = &semdTable[0];

    // head
    semd_h->s_procQ = NULL;
    semd_h->s_semAdd = (int*) 0x00000000;

    // tail
    semd_h->s_next = &semdTable[MAXPROC+1];
    semd_h->s_next->s_procQ = NULL;
    semd_h->s_next->s_semAdd = (int*) 0xFFFFFFFF;
    semd_h->s_next->s_next = NULL;
}