Esempio n. 1
0
void initialize_user_process(char **kos_argv)
{

	// zero out the memory
	bzero(main_memory, MemorySize);

	PCB *pcb = (PCB *) malloc(sizeof(PCB));
	pcb_init(pcb);
	printf("filename: %s\n", kos_argv[0]);

	if (load_user_program(kos_argv[0]) < 0) {
		fprintf(stderr,"Can't load program.\n");
		exit(1);
	}


	// set up the program counters and the stack register 

	pcb->registers[PCReg] = 0;
	pcb->registers[NextPCReg] = 4;

	/* need to back off from top of memory */
	/* 12 for argc, argv, envp */
	/* 12 for stack frame */
	pcb->registers[StackReg] = MemorySize - 24;

	dll_append(readyq, new_jval_v((void *) pcb));
	printf("Running user code.\n");

	kt_exit();
}
Esempio n. 2
0
int syscall_return(PCB *pcb, int returnVal)
{
  // printf("Goes in syscall\n");
  //  printf("This is the user_base and user_limit of the curProc in syscall: %i %i\n",curProc->user_base, curProc->user_limit); 
  //Set PCReg in the saved registers to NextPCReg. This pcb is not the global one in KOS() 
  pcb->registers[PCReg] =  pcb->registers[NextPCReg];
  pcb->registers[2] = returnVal;
  //Put the PCB onto the ready queue.                                   

  Jval value = new_jval_v((void *)pcb);
  //value.v = pcb;
    //places it at the end of the dllist
    dll_append(readyq,value);                                                      
    kt_exit();
}
//Console buffer. Code buffers input from the console until a program requests it with a call to read(). CREATE.
//a thread whose sole job is to read characters from the console and put them into a buffer.
void *console_buffer(void *arg)
{
  //printf("Goes into the console_buffer\n");
  //  int cbTail = 0;
  //int cbHead =0;
  //char *filename = (char *)arg;
  //these are used to convert the char to int and place into buf
  int i;
  char c;
  //int stop =1;
  PIPE *pipe= (PIPE *)arg;
  //printf("Enters console_buffer\n");
  //while(stop)
  while(pipe->ref_count!=0) //bc it it is then you have to deallocate
    {
      P_kt_sem(consoleWait);
      //printf("P_kt_sem(consoleWait): %i\n",kt_getval(consoleWait));
      //have to check if the buffer is full or not
      //printf("Enters while loop in console\n");
      //if not full yet
      //if (cbTail !=cbSize)
      if (pipe->pbuf_tail!=256)
        {
      	  //printf("We are reading from the console into the buffer\n");	  
      	  //currently a char
      	  c = console_read();
      	  //	  printf("Reading from console: %c\n", c);
      	  //conversion to a int bc buffer holds ints only
      	  i = c -'0';
      	  //  printf("Coverted c into i: %i\n",i);
      	  //enqueue - insert it into the buffer cb, enter through the back! and 256 size of the buffer
          //cbTail = (cbTail+1)%256; //this is a shortcut
          pipe->pbuf_tail = (pipe->pbuf_tail+1)%256;
      	  pipe->read_buf[pipe->pbuf_tail] = i;
      	  //printf("Placed into cb[%i]: %i\n", cbTail, cb[cbTail]);
      	  //	 	  printf("This is in index %i: %c %i\n", cbTail, c, cb[cbTail]);
      	  
      	  
      	  //Step 17:
      	  V_kt_sem(nelem);
      	  //printf("V_kt_sem(nelem): %i\n",kt_getval(nelem));
      	}
    }
  //  printf("Exits while loop in console buffer\n");
  kt_exit();
}
Esempio n. 4
0
void *console_buf_read(void *arg) {
	char c;
	int i;

	while (sysStopRead != 1) {
		P_kt_sem(consoleWait);

		if (!full(consoleBufferTail, consoleSize)) {
			c = console_read();
			i = c - '0';

			add_to_queue(consoleBuffer, &consoleBufferTail, i);
			V_kt_sem(nelem);
		}
	}

	kt_exit();
}
Esempio n. 5
0
int syscall_exec(PCB *pcb, int returnVal)
{
  //  printf("Goes into syscall_return exec\n");
    //Set PCReg in the saved registers to NextPCReg. This pcb is not the global one in KOS()
  pcb->registers[PCReg] =  0;
  pcb->registers[NextPCReg] = 4;
  //  pcb->registers[NextPCReg]+=4;
    //Put the return value into register 2.  pcb->registers[2] = returnVal;
  pcb->registers[2] = returnVal;
    //Put the PCB onto the ready queue.
  Jval value = new_jval_v((void *)pcb);
    //value.v = pcb;
    //printf("This is in the syscall_return pcb that gets placed in the value to be placed in readyq: %s\n", value.v);
    //places it at the end of the dllist
    dll_append(readyq,value);
    
    //Call kt_exit
    kt_exit();
}
Esempio n. 6
0
void *initialize_user_process(void *arg)
{
  //  printf("Enters initalize_user_process\n");
  int i;
  char **filename = (char **)arg;
  int argc = 0;
    
  while (filename[argc]!=NULL)
    {
       printf("This is filename[%i]: %s\n", argc, filename[argc]);
      argc++;
    }
  //    printf("This is argc in init: %i\n", argc);
    
  //Step 19: putting in argc
  //k = WordToMachine(argc);
  //memcpy(main_memory+MemorySize-40+12, &k, 4);
    
  //L3 Step 18: start first process, is this init? 
    init=(PCB *)malloc(sizeof(PCB));
    init->registers = (int *)malloc(NumTotalRegs*sizeof(int));
    for (i=0; i < NumTotalRegs; i++)
    {  
      init->registers[i] = 0;
    }
    init->pid = (int *)0;
    //    printf("This is init's pid: %i\n", (int)init->pid);
    //L3 Step 19: 
    init->waiter_sem = make_kt_sem(0);
    init->waiters = new_dllist();
    init->children = make_jrb();

    //Allocate a new PCB
  PCB *temp=(PCB *)malloc(sizeof(PCB));
  temp->registers = (int *)malloc(NumTotalRegs*sizeof(int));
  temp->user_base = 0;
  //printf("Initial user_base: %i\n", temp->user_base);
  //Changed Step 12: temp->user_limit = MemorySize-2048;
  temp->user_limit = MemorySize/8;
  //printf("Initial user_limt: %i\n", temp->user_limit);
  
  //L3 Step 18: 
  temp->parent = init;
  //L3 Step 19: 
  temp->waiter_sem = make_kt_sem(0);
  temp->waiters = new_dllist();
  //L3 Step 21: make rb tree for children 
  temp->children = make_jrb();
  
  //Changed at Step 12: User_Base = temp->user_base;
  User_Base = memory8();
  User_Limit = temp->user_limit;
  //printf("This is User_Base in initialize: %i\n", User_Base);
  //printf("This is User_Limit in initialize: %i\n", User_Limit);

  //set the regs of the
  //printf("Setting all the registers to 0 in initalize_user_process\n");
  for (i=0; i < NumTotalRegs; i++)
    temp->registers[i] = 0;
  
  //printf("Setting pid in init\n");
  temp->pid = (int *)get_new_pid();
  printf("First Pid: %i and its parent's should be 0 init: %i\n", temp->pid, temp->parent->pid );
  /* set up the program counters and the stack register */
  temp->registers[PCReg] = 0;
  temp->registers[NextPCReg] = 4;

  //insert the first process as init's child; WOW you can use this function!
  Jval tempN = new_jval_v((void*)temp); //can only insert Jvals 
  jrb_insert_int(init->children, (int)temp->pid, tempN); //JRB tree, int ikey, Jval val 
  //JRB ptr;
  //  jrb_traverse(ptr, init->children)
  //{
  //printf("This is child pid %i of init %i\n", ptr->key, (int)init->pid);
  //}
  //perform_execve(job, fn, argv)
  // where job is the new PCB, fn is the name of your initial executable (at this point, mine is a.out),
  //and argv is the argv of this initial job.
  //returns-> 0 success, errno if error
  //PrintStack(temp->registers[StackReg], temp->user_base);
  int errno = perform_execve(temp, filename[0],filename);
  // printf("This is perform_execve: %i\n", errno);
    //returns to initialize_user_process(), it either exits because there was an error, or it puts the new job onto the ready queue and calls kt_exit()
  PrintStack(temp->registers[StackReg], temp->user_base);
  if (errno!=0)
  {
      printf("Perform_execve returned unsucessful\n"); 
      kt_exit();
  }
  //printf("Placing jval into queue\n");
  Jval value = new_jval_v((void *)temp);
  //value.v = temp;
  //printf("This is the value being placed into the readyq in the initalize_user_process: %s\n",value.v );
  dll_append(readyq, value);
  // printf("Program %s loaded\n", kos_argv[0]);
  kt_exit();
}
Esempio n. 7
0
File: kos.c Progetto: cbia4/KOS
void *initialize_user_process(void *arg) {
	PCB *start = (PCB *) malloc(sizeof(PCB));
	start->registers = (int *) malloc(NumTotalRegs * sizeof(int));

	int i;
	for (i = 0; i < NumTotalRegs; i++) {
		start->registers[i] = 0;
	}

	int argc = 0;
	while (kos_argv[argc] != NULL) {
		argc++;
	}

	int tempCount = argc;
	int fIndex = 0;
	int ptr[argc];
	int topOfStack = MemorySize - 20;
	while (tempCount != 0) {
		tempCount--;
		topOfStack -= strlen(kos_argv[fIndex]) + 1;
		ptr[tempCount] = topOfStack;
		strcpy(main_memory + topOfStack, kos_argv[fIndex]);
		fIndex++;
	}

	while (topOfStack % 4) {
		topOfStack--;
	}

	topOfStack -= 4;
	int machineAddress = WordToMachine(0);
	memcpy(main_memory + topOfStack, &machineAddress, 4);

	fIndex = 0;
	while (fIndex < argc) {
		topOfStack -= 4;
		machineAddress = WordToMachine(ptr[fIndex]);
		memcpy(main_memory + topOfStack, &machineAddress, 4);
		fIndex++;
	}

	int argv = topOfStack;

	// envp
	topOfStack -= 4;
	machineAddress = WordToMachine(0);
	memcpy(main_memory + topOfStack, &machineAddress, 4);

	// argv
	topOfStack -= 4;
	machineAddress = WordToMachine(argv);
	memcpy(main_memory + topOfStack, &machineAddress, 4);

	// argc
	topOfStack -= 4;
	machineAddress = WordToMachine(argc);
	memcpy(main_memory + topOfStack, &machineAddress, 4);

	if (load_user_program(kos_argv[0]) < 0) {
		fprintf(stderr, "Error: Unable to load user program.\n");
		exit(1);
	}

	start->registers[StackReg] = topOfStack - 12;
	start->registers[PCReg] = 0;
	start->registers[NextPCReg] = 4;

	Jval j = new_jval_v((void *)start);
	dll_append(queue, j);

	kt_exit();
}
Esempio n. 8
0
void
KtSched()
{
	K_t kt;
	JRB jb;
	unsigned int sp;
	unsigned int now;
        JRB tmp;
        Dllist dtmp;

	/*
	 * start by recording the current stack contents in case
	 * I'm descheduled
	 *
	 * this is where I return to when I'm rescheduled
	 */
	if(setjmp(ktRunning->jmpbuf) != 0)
	{
		FreeFinishedThreads();
		/*
		 * if we are being killed by another thread, jump through
		 * the exitbuf
		 */
		if(ktRunning->die_now)
		{
                        /* Jim: This used to longjmp to the exitbuf,
                                but I changed it for two reasons:  
                                1. It wasn't being removed from ktActive
                                2. Hell will be paid if it is ktOriginal.
                                I believe kt_exit() is cleaner.  I
                                have not tested it.  I should.  */
			kt_exit();
			/* not reached */
		}
		return;
	}


start:

        if (!jrb_empty(ktSleeping)) {
  	  now = time(0);
	  while(!jrb_empty(ktSleeping))
	  {
	  	kt = (K_t) jval_v(jrb_val(jrb_first(ktSleeping)));
		if(kt->wake_time > now)
		{
			break;
		}
		WakeKThread(kt);
          }
	}
			


	/*
	 * if there is nothing left to run, exit.  However, if there 
         * are sleepers or a joinall, deal with them appropriately
	 */
	if(dll_empty(ktRunnable))
	{

		/*
		 * first, check for sleepers and deal with them
		 */
		if(!jrb_empty(ktSleeping))
		{
			kt = jval_v(jrb_val(jrb_first(ktSleeping)));
			sleep(kt->wake_time - now);
			goto start;
		}

		/*
		 * next, see if there is a joinall thread waiting
		 */
		jb = jrb_find_int(ktBlocked,0);
		if(jb != NULL)
		{
			WakeKThread((K_t)jval_v(jrb_val(jb)));
			goto start;
		}

		if(!jrb_empty(ktBlocked)) 
		{
			if(Debug & KT_DEBUG)
			{
				fprintf(stderr,
					"All processes blocked, exiting\n");
				fflush(stderr);
			}
			exit(1);
		} else {
			if(Debug & KT_DEBUG)
			{
				fprintf(stderr,
					"No runnable threads, exiting\n");
				fflush(stderr);
			}
			exit(0);
                }

                fprintf(stderr, "We shouldn't get here\n");
                exit(1);
	}

        /* Grab the first job of the ready queue */

        dtmp = dll_first(ktRunnable);
        kt = (K_t) dtmp->val.v;
	dll_delete_node(dtmp);

        /* If it is runnable, run it */

	if(kt->state == RUNNABLE) {

		ktRunning = kt;
		ktRunning->state = RUNNING;
		longjmp(ktRunning->jmpbuf,1);
                /* This doesn't return */
	}

	/*
	 * if we have never run before, set up initial stack and go
	 */
	if(kt->state == STARTING) {
		if(setjmp(kt->jmpbuf) == 0)
		{
			/*
			 * get double word aligned SP -- stacks grow from high
			 * to low
			 */
			sp = (unsigned int)&((kt->stack[kt->stack_size-1]));
			while((sp % 8) != 0)
				sp--;
#ifdef LINUX
			/*
			 * keep double word aligned but put in enough
			 * space to handle local variables for KtSched
			 */
			kt->jmpbuf->__jmpbuf[JB_BP] = (int)sp;
			kt->jmpbuf->__jmpbuf[JB_SP] = (int)sp-1024;
			PTR_MANGLE(kt->jmpbuf->__jmpbuf[JB_SP]);
#endif

#ifdef SOLARIS
			/*
			 * keep double word aligned but put in enough
			 * space to handle local variables for KtSched
			 */
			kt->jmpbuf[JB_FP] = (int)sp;
			kt->jmpbuf[JB_SP] = (int)sp-1024;
#endif
			/*
			 * set ktRunning while we still have local variables
			 */
			kt->state = RUNNING;
			ktRunning = kt;
			/*
			 * now jump onto the new stack
			 */
			longjmp(kt->jmpbuf,1);
		}
		else
		{
			/*
			 * here we are on a new, clean stack -- touch nothing,
			 * set the state, and call
			 *
			 * ktRunning is global so there is no local variable
			 * problem
			 *
			 * borrow this stack to try and free the last thread
			 * if there was one
			 */

			FreeFinishedThreads();

			if(setjmp(ktRunning->exitbuf) == 0)
			{
				/*
				 * if we were killed before we ran, skip the
				 * function call
				 */
				if(ktRunning->die_now == 0)
				{
					ktRunning->func(ktRunning->arg);
				}
			}


			/*
			 * we are back and this thread is done
			 *
			 * make it inactive
			 */

			jb = jrb_find_int(ktActive,ktRunning->tid);
			if(jb == NULL)
			{
				if(Debug & KT_DEBUG)
				{
					fprintf(stderr,
				"KtSched: panic -- inactive return\n");
					fflush(stderr);
				}
				exit(1);
			}
			jrb_delete_node(jb);

			/*
			 * look to see if there is a thread waiting for this
			 * one to exit -- careful with locals
			 */
			jb = jrb_find_int(ktBlocked,ktRunning->tid);
			if(jb != NULL)
			{
				WakeKThread((K_t)jval_v(jrb_val(jb)));
			}


			/*
			 * all we can do now is to commit suicide
			 *
			 * don't touch the locals;
			 *
			 * and don't free the stack we are running on
			 */
			FreeFinishedThreads();
                        ktRunning->state = DEAD;
			dll_append(ktFree_me,new_jval_v(ktRunning));
			ktRunning = NULL;
			goto start;
		}
	}

        /* The only way we get here is if there was a thread on the
           runnable queue whose state was not RUNNABLE or STARTING.
           Flag that as an error */

        fprintf(stderr, 
                "Error: non-STARTING or RUNNABLE thread on the ready queue\n");
        exit(1);
}
Esempio n. 9
0
void *initialize_user_process(void *arg){

  PCB *user_process;
  Jval jval_pcb;
  Jval user_process_child_node;
  char **filename;
  int base;
  int arg_count;
  int errno;
  int i;
  
  arg_count = 0;
  errno = 0;
  i = 0;
  
  
  
  /* Unmarshalling */
  filename = (char **) arg;
  
  
  /* Create the global init process */
  init = (PCB *)malloc(sizeof(PCB));
  init->registers = (int *)malloc(sizeof(int) * NumTotalRegs);
  
  // Initialize init's registers */
  for (i = 0; i < NumTotalRegs; i++) {
    init->registers[i] = 0;
  }
  
  // Initialize init's other variables
  init->pid = (int *)0;
  init->waiter = make_kt_sem(0);
  init->waiters = new_dllist();
  init->children = make_jrb();
  
  
  
  /* Allocate new PCB and initialize registers */
  user_process = (PCB *)malloc(sizeof(PCB));
  user_process->registers = (int *)malloc(NumTotalRegs * sizeof(int));
  for (i = 0; i < NumTotalRegs; i++) {
    user_process->registers[i] = 0;
  }
  
  // Obtain pid and partiton memory for new process
  user_process->pid = (int *)get_new_pid();
  base = partition_memory(user_process->pid);
  
  
  // Initialize first process' other variables
  user_process->waiter = make_kt_sem(0);
  user_process->waiters = new_dllist();
  user_process->children = make_jrb(); 
  

  // Set base and limit for new process
  user_process->base = 0;
  user_process->limit = MemorySize/8;
  
  // Set User global vars
  User_Base = base;
  User_Limit = user_process->limit;
  
  // Set process' PCRegs
  user_process->registers[PCReg] = 0;
  user_process->registers[NextPCReg] = 4;
  
  
  // Set first process' parent as init and add to init's children
  user_process->parent = (struct PCB *)init;
  user_process_child_node.v = user_process;
  jrb_insert_int(init->children, (int)user_process->pid, user_process_child_node);
    
  
  // Get number of args and turn off exec flag.
  while (filename[arg_count] != NULL) {
    arg_count++;
  }
  totalArgs = arg_count;
  is_exec = 0;
  
  /* Call perform_execve */
  errno = perform_execve(user_process, filename[0], filename);
  
  // If errors, returns proper errno
  if (errno != 1) {
    syscall_return(user_process, errno);
  } else {
  // Puts new job onto readyQ and calls kt_exit()
    jval_pcb.v = user_process;
    dll_append(readyQ, jval_pcb);
    kt_exit();
  }
  
}