aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Burwell <ben@benburwell.com>2015-04-01 20:06:27 -0400
committerBen Burwell <ben@benburwell.com>2015-04-01 20:06:27 -0400
commitc4ed6736d2e093ea7433328a552d53d3bcaff927 (patch)
treeca54ce36f7d10b414ae9e559a184141d49f63f7e
parent7b0995ea20afed2632893f8528ce9d57772d5498 (diff)
as of 2013-09-302013-09-30
-rw-r--r--comhan.c294
-rw-r--r--main.c50
-rw-r--r--mpx.h49
-rw-r--r--pcb.c189
4 files changed, 557 insertions, 25 deletions
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 <stdio.h>
#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 <string.h>
+#include <stdio.h>
+
+/**
+ * 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;
+}