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 --- comhan.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- main.c | 50 ++++++++++- mpx.h | 49 ++++++++++- pcb.c | 189 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 557 insertions(+), 25 deletions(-) create mode 100644 pcb.c diff --git a/comhan.c b/comhan.c index 556aab2..73b0c54 100644 --- a/comhan.c +++ b/comhan.c @@ -17,18 +17,22 @@ #define HELP 4 #define PROMPT 5 #define ALIAS 6 +#define SHOW 7 +#define ALLOCATE 8 +#define CMD_FREE 9 - -int length; /* Length of the command line. */ +int length; /* Length of the command line. */ char prompt[20] = "mpx>"; const char version[] = "MPX OS - Version 1.0\n"; char date[] = "01/09/1991"; -char *cmds[] = {"version", "date", "directory","stop", - "help", "prompt", "alias", NULL}; -char *aliases[] = {"", "", "", "", "", "", "", NULL}; +char *cmds[] = {"version", "date", "directory","stop","help", + "prompt", "alias", "show", "allocate", "free", NULL}; +char *aliases[] = {" ", " ", " ", " ", + " ", " ", " ", " ", + " ", " ", NULL}; /* * comhan() This is the command handler for the MPX OS. @@ -45,6 +49,7 @@ void comhan() { int argc; int cmd_num; char buffer[BUF_SIZE]; + int do_stop = 0; do { printf("%s ",prompt); /* Print a prompt. */ @@ -54,18 +59,21 @@ void comhan() { argc = set_args(buffer, args); switch (cmd_num = get_cmd(args[0])) { - case VERSION: cmd_version(); break; - case DATE: cmd_date(args); break; - case DIRECTORY: cmd_directory(); break; - case STOP: cmd_stop(); break; - case HELP: cmd_help(args); break; - case PROMPT: cmd_prompt(args); break; - case ALIAS: cmd_alias(args); break; + case VERSION: cmd_version(); break; + case DATE: cmd_date(args); break; + case DIRECTORY: cmd_directory(); break; + case STOP: do_stop = cmd_stop(); break; + case HELP: cmd_help(args); break; + case PROMPT: cmd_prompt(args); break; + case ALIAS: cmd_alias(args); break; + case SHOW: cmd_show(args); break; + case ALLOCATE: cmd_allocate(args); break; + case CMD_FREE: cmd_free(args); break; default: printf("Can't recognize.\n"); break; } - } while (cmd_num != STOP); + } while (!do_stop); } int get_cmd(char cmd[]){ @@ -158,8 +166,20 @@ void cmd_directory(){ /** * Print a goodbye message */ -void cmd_stop(){ - printf("**COMHAN execution complete **\n"); +int cmd_stop(){ + char buffer[2]; + int length = 2; + + printf("Are you sure you want to exit? [y/n]: "); + sys_req(CON,READ,buffer,&length); + + if (strcmp(buffer, "y") == 0 || strcmp(buffer, "Y") == 0) { + printf("**COMHAN execution complete **\n"); + return 1; + } else { + printf("Okay! \n"); + return 0; + } } /** @@ -168,13 +188,16 @@ void cmd_stop(){ * argument if given. */ void cmd_help(char *args[]){ - char ver[] = "version Display version number\n"; - char hlp[] = "help Provide information about commands\n"; - char dir[] = "directory List .mpx files\n"; - char dat[] = "date [mm/dd/yyyy] Display or set the system date\n"; - char stp[] = "stop Terminate execution of COMHAN\n"; - char prmpt[] = "prompt string Change the prompt for commands\n"; - char als[] = "alias command=string Create an alias for a command\n"; + char ver[] = "version Display version number \n"; + char hlp[] = "help Provide information about commands \n"; + char dir[] = "directory List .mpx files \n"; + char dat[] = "date [mm/dd/yyyy] Display or set the system date \n"; + char stp[] = "stop Terminate execution of COMHAN \n"; + char prmpt[] = "prompt string Change the prompt for commands \n"; + char als[] = "alias command=string Create an alias for a command \n"; + char shw[] = "show Prints PCB information \n"; + char alloc[] = "allocate Builds PCB with specified options \n"; + char free[] = "free name Frees the PCB called name \n"; switch(get_cmd(args[1])){ case VERSION: printf(ver); break; @@ -184,6 +207,9 @@ void cmd_help(char *args[]){ case HELP: printf(hlp); break; case PROMPT: printf(prmpt); break; case ALIAS: printf(als); break; + case SHOW: printf(shw); break; + case ALLOCATE: printf(alloc); break; + case CMD_FREE: printf(free); break; default: printf("**\tCommand Summary\t**\n"); printf("Name Use\n"); @@ -195,6 +221,9 @@ void cmd_help(char *args[]){ printf(hlp); printf(prmpt); printf(als); + printf(shw); + printf(alloc); + printf(free); } } @@ -211,3 +240,224 @@ void cmd_alias(char *args[]){ strcpy(aliases[num], args[2]); num ++; } + +void print_pcb(pcb * p) { + + char str[4]; + + if (p->type == FREE) { + str[0] = 'f'; + } else if (p->type == SYS_PROCESS) { + str[0] = 's'; + } else if (p->type == APP_PROCESS) { + str[0] = 'a'; + } else { + str[0] = '-'; + } + + if (p->state == READY) { + str[1] = 'r'; + } else if (p->state == RUNNING) { + str[1] = 'o'; + } else if (p->state == BLOCKED) { + str[1] = 'b'; + } else { + str[1] = '-'; + } + + if (p->suspend == SUSPENDED) { + str[2] = 'y'; + } else if (p->suspend == NOT_SUSPENDED) { + str[2] = 'n'; + } else { + str[2] = '-'; + } + + str[3] = '\0'; + + printf("0x%04x %8s %s 0x%04x 0x%04x 0x%04x %3d 0x%04x \n", + p, p->name, str, p->chain, p->prev, + p->next, p->priority, p->loadaddr); +} + +void cmd_show(char *args[]) { + pcb * current = pcb_list; + + if (!args[1]) { + printf("Show: free, all, system, application, \n"); + printf(" suspended, ready, init. \n"); + return; + } + + printf("PCB_Ad Name TSP chain prev next pri l_addr \n"); + printf("------ -------- --- ------ ------ ------ --- ------ \n"); + + if (strcmp(args[1], "init") == 0 || strcmp(args[1], "ready") == 0) { + current = (strcmp(args[1], "init") == 0)? io_init_queue : ready_queue; + + if (current == NULL) { + return; + } + + do { + print_pcb(current); + current = current->next; + } while (current != NULL); + return; + } + + do { + if (strcmp(args[1], "free") == 0 && current->type == FREE) { + print_pcb(current); + } else if (strcmp(args[1], "all") == 0) { + print_pcb(current); + } else if (strcmp(args[1], "system") == 0 && + current->type == SYS_PROCESS) { + print_pcb(current); + } else if (strcmp(args[1], "application") == 0 && + current->type == APP_PROCESS) { + print_pcb(current); + } else if (strcmp(args[1], "suspended") == 0 && + current->suspend == SUSPENDED) { + print_pcb(current); + } else if (strcmp(args[1], "ready") == 0 && + current->state == READY) { + print_pcb(current); + } + + current = current->chain; + } while (current != NULL); +} + +void cmd_allocate(char *args[]) { + pcb * new; + int result; + int type, state, suspend, priority; + pcb * exists; + + if (!args[1] || !args[2] || !args[3] || !args[4] || !args[5]) { + printf("***Error*** \n"); + printf("Please use the correct number of arguments. \n"); + return; + } + + if (strcmp(args[2], "f") != 0 && + strcmp(args[2], "a") != 0 && + strcmp(args[2], "s") != 0) { + printf("***Error*** \n"); + printf("PCB type must be f(ree), a(pplication) or s(ystem). \n"); + printf("You said: %s \n", args[2]); + return; + } + + if (strcmp(args[3], "r") != 0 && + strcmp(args[3], "o") != 0 && + strcmp(args[3], "b") != 0) { + printf("***Error*** \n"); + printf("PCB state must be r(eady), o(running), or b(locked). \n"); + printf("You said: %s \n", args[3]); + return; + } + + if (strcmp(args[4], "y") != 0 && + strcmp(args[4], "n") != 0) { + printf("***Error*** \n"); + printf("PCB suspended flag must be y(es) or n(o). \n"); + printf("You said: %s \n", args[4]); + return; + } + + priority = atoi(args[5]); + + exists = search_pcb(pcb_list, args[1]); + + if(exists != NULL){ + printf("***Error*** \n"); + printf("A pcb with that name already esists. \n"); + return; + } + + new = get_pcb(pcb_list); + + type = FREE; + if (strcmp(args[2], "a") == 0) { + type = APP_PROCESS; + } else if (strcmp(args[2], "s") == 0) { + type = SYS_PROCESS; + } + + state = READY; + if (strcmp(args[3], "o") == 0) { + state = RUNNING; + } else if (strcmp(args[3], "b") == 0) { + state = BLOCKED; + } + + suspend = NOT_SUSPENDED; + if (strcmp(args[4], "y") == 0) { + suspend = SUSPENDED; + } + + if (type == APP_PROCESS && (priority < -126 || priority > 126)) { + printf("***Error*** \n"); + printf("The priority for an application process must be \n"); + printf("between -126 and 126, inclusive. \n"); + return; + } + + if (type == SYS_PROCESS && (priority < -128 || priority > 127)) { + printf("***Error*** \n"); + printf("The priority for a system process must be \n"); + printf("between -128 and 127, inclusive. \n"); + return; + } + + result = build_pcb(new, args[1], type, state, suspend, priority); + + switch (result) { + case 1: break; + + case -1: printf("***Error*** \n"); + printf("There was no space for another pcb. \n"); + break; + + case -2: printf("***Error*** \n"); + printf("Invalid type \n"); + break; + + case -3: printf("***Error*** \n"); + printf("Invalid state \n"); + break; + + case -4: printf("***Error*** \n"); + printf("Invalid suspend \n"); + break; + } + + //put the pcb in a queue + if (state == READY) { + insert_pcb(&ready_queue, new, 0); //insert in priority order + } else if (state == BLOCKED) { + insert_pcb(&io_init_queue, new, 1); //insert at end of queue + } + + return; +} + +void cmd_free(char *args[]) { + pcb * to_free = search_pcb(pcb_list, args[1]); + int result; + + if (to_free->state == READY) { + remove_pcb(&ready_queue, to_free); + } else if(to_free->state == BLOCKED) { + remove_pcb(&io_init_queue, to_free); + } + + result = free_pcb(pcb_list, to_free); + switch (result) { + case 1: printf("PCB freed\n"); break; + case -1: printf("Couldn't find PCB\n"); break; + case -2: printf("PCB already free\n"); break; + } +} \ No newline at end of file diff --git a/main.c b/main.c index 76e9168..9bd8b55 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,3 @@ - /* file: main.c * * This file contains the function main @@ -9,12 +8,59 @@ #include #include "mpx.h" +pcb * pcb_list; +pcb * ready_queue; +pcb * io_init_queue; int main(void) { - printf("... booting MPX\n\n"); /* Put initialization code here */ + // allocate memory for PCBs + pcb pcb0; + pcb pcb1; + pcb pcb2; + pcb pcb3; + pcb pcb4; + pcb pcb5; + pcb pcb6; + pcb pcb7; + pcb pcb8; + pcb pcb9; + pcb pcb10; + pcb pcb11; + + // create the chain + pcb0.chain = &pcb1; + pcb1.chain = &pcb2; + pcb2.chain = &pcb3; + pcb3.chain = &pcb4; + pcb4.chain = &pcb5; + pcb5.chain = &pcb6; + pcb6.chain = &pcb7; + pcb7.chain = &pcb8; + pcb8.chain = &pcb9; + pcb9.chain = &pcb10; + pcb10.chain = &pcb11; + pcb11.chain = NULL; + + build_pcb(&pcb0, " ", FREE, -1, -1, 0); + build_pcb(&pcb1, " ", FREE, -1, -1, 0); + build_pcb(&pcb2, " ", FREE, -1, -1, 0); + build_pcb(&pcb3, " ", FREE, -1, -1, 0); + build_pcb(&pcb4, " ", FREE, -1, -1, 0); + build_pcb(&pcb5, " ", FREE, -1, -1, 0); + build_pcb(&pcb6, " ", FREE, -1, -1, 0); + build_pcb(&pcb7, " ", FREE, -1, -1, 0); + build_pcb(&pcb8, " ", FREE, -1, -1, 0); + build_pcb(&pcb9, " ", FREE, -1, -1, 0); + build_pcb(&pcb10, " ", FREE, -1, -1, 0); + build_pcb(&pcb11, " ", FREE, -1, -1, 0); + + pcb_list = &pcb0; + + printf("... booting MPX\n\n"); + comhan(); /* Execute the command handler */ return 0; diff --git a/mpx.h b/mpx.h index dfecbed..7d64022 100644 --- a/mpx.h +++ b/mpx.h @@ -31,6 +31,36 @@ struct dirstruct { /* Data type for a directory entry. */ typedef struct dirstruct dir; /* Use dir as the data typer name. */ +/** + * PCB + */ + +#define FREE 0 +#define SYS_PROCESS 1 +#define APP_PROCESS 2 +#define READY 0 +#define RUNNING 1 +#define BLOCKED 2 +#define NOT_SUSPENDED 0 +#define SUSPENDED 1 + + +struct pcbstruct { + struct pcbstruct * chain; + struct pcbstruct * next; + struct pcbstruct * prev; + char name[9]; + short type; + short priority; + short state; + short suspend; + unsigned stack_ptr; + unsigned stack[400]; + unsigned loadaddr; + int mem_size; +}; +typedef struct pcbstruct pcb; + /* Function prototypes. */ /* main.c */ @@ -42,14 +72,28 @@ int get_cmd(char args[]); void cmd_version(void); void cmd_date(char *[]); void cmd_directory(void); -void cmd_stop(void); +int cmd_stop(void); void cmd_help(char *[]); void cmd_prompt(char *[]); void cmd_alias(char *[]); +void cmd_show(char *[]); +void cmd_allocate(char *[]); +void cmd_free(char *[]); void sys_req(int,int,char *,int *); /* MPX system request function. */ int directory(dir *, int); /* Support function to load the */ /* directory array. */ +/** + * PCB.C + */ +pcb * search_pcb(pcb *, char[]); +pcb * get_pcb(pcb *); +int free_pcb(pcb *, pcb *); +int build_pcb(pcb *, char[], int, int, int, int); +int insert_pcb(pcb**, pcb *, int); +int remove_pcb(pcb**, pcb *); + + /* * Global variable EXTERN directives. * @@ -62,3 +106,6 @@ int directory(dir *, int); /* Support function to load the */ extern dir direct[]; /* Array of directory entries - see direct.c */ extern int directory(dir *direct, int dir_size); +extern pcb * pcb_list; +extern pcb * ready_queue; +extern pcb * io_init_queue; 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