diff options
| -rw-r--r-- | comhan.c | 294 | ||||
| -rw-r--r-- | main.c | 50 | ||||
| -rw-r--r-- | mpx.h | 49 | ||||
| -rw-r--r-- | pcb.c | 189 | 
4 files changed, 557 insertions, 25 deletions
| @@ -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 @@ -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;
 @@ -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;
 @@ -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;
 +}
 | 
