From c4ed6736d2e093ea7433328a552d53d3bcaff927 Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Wed, 1 Apr 2015 20:06:27 -0400 Subject: as of 2013-09-30 --- pcb.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 pcb.c (limited to 'pcb.c') diff --git a/pcb.c b/pcb.c new file mode 100644 index 0000000..8cffe3f --- /dev/null +++ b/pcb.c @@ -0,0 +1,189 @@ +#include "mpx.h" +#include +#include + +/** + * Returns the address of the PCB with the specified name + */ +pcb * search_pcb(pcb * list, char name[]) { + pcb * current = list; + + // step through the chain + do { + if (strcmp(current->name, name) == 0) { + return current; + } + current = current->chain; + } while (current != NULL); + + // nothing found + return NULL; +} + +/** + * Returns the address of the first free PCB. + * If all PCBs are in use, it returns NULL. + */ +pcb * get_pcb(pcb * list) { + pcb * current = list; + + // step through the list + do { + if (current->type == FREE) { + return current; + } + current = current->chain; + } while (current != NULL); + + // no free PCBs + return NULL; +} + +/** + * Sets the specified PCB to be free. + */ +int free_pcb(pcb * list, pcb * addr) { + pcb * current = list; + + do { + if (current == addr) { + + // check if PCB is already free + if (current->type == FREE) { + // it is, so we don't free it + return -2; + } else { + // we need to free the PCB + build_pcb(current, " ", 0, -1, -1, 0); + return 1; + } + } + current = current->chain; + } while (current != NULL); + + // invalid PCB address + return -1; +} + +/** + * Sets the properties of the given PCB. + */ +int build_pcb(pcb * addr, char name[], int type, int state, + int suspend, int priority) { + // check that address is valid + if (addr == 0 || addr == NULL) { + return -1; + } + + // check that type is FREE, SYS_PROCESS, APP_PROCESS + if (type != FREE && type != SYS_PROCESS && type != APP_PROCESS) { + return -2; + } + + // check that state is READY, RUNNING, BLOCKED, or -1 for free + if (state != READY && state != RUNNING && + state != BLOCKED && state != -1) { + return -3; + } + + // check that suspend is SUSPENDED, NOT_SUSPENDED or -1 for free + if (suspend != SUSPENDED && suspend != NOT_SUSPENDED && suspend != -1) { + return -4; + } + + strcpy(addr->name, name); + addr->type = type; + addr->state = state; + addr->suspend = suspend; + addr->next = NULL; + addr->prev = NULL; + addr->priority = priority; + + return 1; +} + +/** + * Puts the specified PCB into the specified queue, using either + * FIFO or priority queue (method==0: priority, method==1: FIFO) + */ +int insert_pcb(pcb **queue, pcb * addr, int method) { + pcb * current = *queue; + pcb * one_after; + + // if there's nothing in the queue yet, make the PCB the start + if (current == NULL) { + *queue = addr; + return 1; + } + + if (method == 1) { + // insert at end of queue + + // skip to the end of the queue + while(current->next != NULL) { + current = current->next; + } + + // add the PCB + current->next = addr; + addr->next = NULL; + addr->prev = current; + return 1; + } else if (method == 0) { + // insert in priority order + + // if we need to skip forward at all... + if (current->priority >= addr->priority) { + + // ...do it + while (current->next != NULL && + (current->next)->priority >= addr->priority) { + current = current->next; + } + + // and set the pointers + one_after = current->next; + current->next = addr; + addr->next = one_after; + addr->prev = current; + one_after->prev = addr; + } else { + + // otherwise, put it at the head + current->prev = addr; + addr->next = current; + *queue = addr; + } + return 1; + } else { + // There was a problem, return error code + return -1; + } +} + +/** + * Takes the PCB out of the specified queue + */ +int remove_pcb(pcb **queue, pcb * addr) { + pcb * current = *queue; + + // are we removing the head? + if (addr == *queue) { + *queue = addr->next; + (addr->next)->prev = NULL; + return 0; + } + + // not removing the head: + do { + if (current->next == addr) { + current->next = addr->next; + (current->next)->prev = current; + addr->next = NULL; + addr->prev = NULL; + return 0; + } + current = current->next; + } while (current != NULL); + return -1; +} -- cgit v1.2.3