Exemple #1
0
pid_t
sys_waitpid(pid_t pid, int * status, int options, int *retval){

	int result = valid_pid(pid);
	
	if(result){
		return result;
	}
	//If there is an option attached, FAIL. NO OPTIONS FOR YOU
	else if(options != 0){
		return EINVAL;
	}
	//If pointer is not aligned, throw an error. NO EXIT CODE FOR YOU
	else if((int)status%4 != 0){
		return EFAULT;
	}
	acquire_lock(pid);
	//While the process has not exited yet,  
	while(has_exit_code(pid) == false){
		put_to_sleep(pid);
	}
	
	*status = _MKWAIT_EXIT(get_exit_code(pid));
	release_lock(pid);
	release_pid(pid);
	*retval = pid;
	return 0;
}
Exemple #2
0
void sys__exit(int exitcode) {

	// array init

	exitcode = _MKWAIT_EXIT(exitcode);

	// add to exitcode array
	struct exitc *c = find_exitc(curproc->p_pid);
	if(c) {
		c->exitcode = exitcode;
	}

	// remove from procarray.
	unsigned num = procarray_num(procarr);
	for (unsigned i = 0 ; i < num ; i++) {
		if ((procarray_get(procarr, i)) == curproc) {
			procarray_remove(procarr,i);
			break;
		}
	}
	// pid_list[curproc->p_pid] = false;

	cv_broadcast(curproc->p_cv,curproc->p_lk);

	//proc_remthread(curthread);
	thread_exit();
	// curthread->t_proc = NULL; //what is this??? you removed it at the bottom and then added it here?
	// code below is removed. Since the process is destroyed, there is no "curthread" now.
	// We cannot access to it.
	// curthread->t_proc = NULL;
}
void
sys__exit(int exitcode)
{

    struct addrspace* as;
    struct proc* p = curproc;
    DEBUG(DB_EXEC, "sys_exit(): process %u exiting with code %d\n",p->p_pid,exitcode);

    KASSERT(p->p_addrspace != NULL);
    as_deactivate();
    as = proc_setas(NULL);
    as_destroy(as);
    proc_remthread(curthread);

    p->p_exitstatus = _MKWAIT_EXIT(exitcode);
    p->p_exitable = true;

    lock_acquire(p->p_waitpid_lk);
        cv_broadcast(p->p_waitpid_cv, p->p_waitpid_lk);
    lock_release(p->p_waitpid_lk);

    proc_destroy(p);
    thread_exit();
    panic("sys__exit(): unexpected return from thread_exit()\n");
}
Exemple #4
0
void sys_exit(int exitcode, bool is_sig){

    lock_acquire(curproc->exitlock);

    for (int fd = 0; fd < OPEN_MAX; fd++) {
        int err;
        sys_close(fd, &err);
    }

    curproc->exit_flag = true;

    if (is_sig) {
        curproc->exit_code = _MKWAIT_SIG(exitcode);
    } else {
        curproc->exit_code = _MKWAIT_EXIT(exitcode);
    }

    if (proc_ids[curproc->ppid]->exit_flag == false) {
        cv_broadcast(curproc->exitcv, curproc->exitlock);
        lock_release(curproc->exitlock);
    } else {
        /* Clean Up */
        lock_release(curproc->exitlock);
        cv_destroy(curproc->exitcv);
        as_destroy(curproc->p_addrspace);
        kfree(proc_ids[curproc->pid]->p_name);
        curproc->p_addrspace = NULL;
        kfree(proc_ids[curproc->pid]);
        proc_ids[curproc->pid] = NULL;
        lock_destroy(curproc->exitlock);
    }

    thread_exit();
}
Exemple #5
0
// Doesn't return
void sys_exit(int exit_code){

	lock_acquire(pid_lock);

	if(curthread->ppid == -1){     // no parent
		kprintf("NO PARENT");
		thread_exit();
	}

	process_array[curthread->mypid]->exited = 1;
	process_array[curthread->mypid]->exit_code = _MKWAIT_EXIT(exit_code); //TODO: ppid?

//	TODO: close filehandletable entries (memory leak)
//	for(int fd = 0; fd < MAX_FILE_DESCRIPTORS; fd++){
//		sys_close(fd);
//	}

	if(process_array[curthread->ppid] != NULL){
		if(process_array[curthread->ppid]->thread != NULL){
			V(process_array[curthread->ppid]->thread->exit_sem);
		}
	}

	lock_release(pid_lock);
	thread_exit();
}
/*
 * Function called when user-level code hits a fatal fault.
 */
static
void
kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
{
	int sig = 0;

	KASSERT(code < NTRAPCODES);
	switch (code) {
	    case EX_IRQ:
	    case EX_IBE:
	    case EX_DBE:
	    case EX_SYS:
		/* should not be seen */
		KASSERT(0);
		sig = SIGABRT;
		break;
	    case EX_MOD:
	    case EX_TLBL:
	    case EX_TLBS:
		sig = SIGSEGV;
		break;
	    case EX_ADEL:
	    case EX_ADES:
		sig = SIGBUS;
		break;
	    case EX_BP:
		sig = SIGTRAP;
		break;
	    case EX_RI:
		sig = SIGILL;
		break;
	    case EX_CPU:
		sig = SIGSEGV;
		break;
	    case EX_OVF:
		sig = SIGFPE;
		break;
	}

	/*
	 * You will probably want to change this.
	 */

	kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
		code, sig, trapcodenames[code], epc, vaddr);
	if(curthread->pid == 1){
		V(menu_semaphore);
	}
	else {
		
                proc_tbl[curthread->pid]->exit_code = _MKWAIT_EXIT(1);
                proc_tbl[curthread->pid]->exit = true;
                V(proc_tbl[curthread->pid]->sem);
        

	}
	thread_exit();
//	panic("I don't know how to handle this\n");
}
Exemple #7
0
int
sys___exit(int exit_code)
{
	//Check whether the process calling exit has no children?

	pid_t pid_process=curthread->t_pid;

	//Check whether to indicate exit by calling cv_broadcast as well
//	cv_broadcast(process_array[pid_process]->process_cv,process_array[pid_process]->process_lock);

	//Now using a semaphore and V when the thread exits
	if(process_array[pid_process]->waitstatus==true)
	{
		lock_acquire(process_array[pid_process]->process_lock);

		//Indicate Exit by calling changing the exit status in the process array
		process_array[pid_process]->exit_code= _MKWAIT_EXIT(exit_code);

		process_array[pid_process]->exit_status=true;

		cv_signal(process_array[pid_process]->process_cv,process_array[pid_process]->process_lock);

		lock_release(process_array[pid_process]->process_lock);

	}
		//V(process_array[pid_process]->process_sem);
	else
	{
		lock_acquire(process_array[pid_process]->process_lock);

		//Store the exit code passed in the argument
		process_array[pid_process]->exit_code= _MKWAIT_EXIT(exit_code);

		//Indicate Exit by calling changing the exit status in the process array
		process_array[pid_process]->exit_status=true;

		lock_release(process_array[pid_process]->process_lock);

	}

	thread_exit();

	return 0;
}
/*
void free_root(struct procinfo* pi){
  KASSERT(pi != NULL);
  if (pi->parent_pid == -1){
    array_set(proc)
  }
  
}*/
void sys__exit(int exitcode) {

  struct addrspace *as;
  struct proc *p = curproc;
  /* for now, just include this to keep the compiler from complaining about
     an unused variable */
  #if OPT_A2
  
  struct procinfo *pi = array_get(procinfotable, p->pid-1);
  
  if(pi == NULL){
    goto parentexited;
  }

  lock_acquire(p->p_waitpid_lock);
  
  pi->exit_code = _MKWAIT_EXIT(exitcode);
  pi->active = 0;
  cv_broadcast(pi->waitpid_cv,p->p_waitpid_lock);

  lock_release(p->p_waitpid_lock);

  free_children(p->pid);
  
parentexited:  
  #else

  (void)exitcode;

  #endif
  DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);

  KASSERT(curproc->p_addrspace != NULL);
  as_deactivate();
  /*
   * clear p_addrspace before calling as_destroy. Otherwise if
   * as_destroy sleeps (which is quite possible) when we
   * come back we'll be calling as_activate on a
   * half-destroyed address space. This tends to be
   * messily fatal.
   */
  as = curproc_setas(NULL);
  as_destroy(as);

  /* detach this thread from its process */
  /* note: curproc cannot be used after this call */
  proc_remthread(curthread);

  /* if this is the last user process in the system, proc_destroy()
     will wake up the kernel menu thread */
  proc_destroy(p);
  
  thread_exit();
  /* thread_exit() does not return, so we should never get here */
  panic("return from thread_exit in sys_exit\n");
}
Exemple #9
0
static
void
fail(unsigned long num, const char *msg)
{
    kprintf("thread %lu: Mismatch on %s\n", num, msg);
    kprintf("Test failed\n");

    lock_release(testlock);

    V(donesem);
    thread_exit(_MKWAIT_EXIT(1));
}
Exemple #10
0
int
sys_waitpid(pid_t pid, userptr_t retstatus, int flags, pid_t *retval)
{
	int status; 
	int result;

	result = pid_wait(pid, &status, flags, retval);
	if (result) {
		return result;
	}
  status = _MKWAIT_EXIT(status);	
	return copyout(&status, retstatus, sizeof(int));
}
Exemple #11
0
static
void
cvtestthread(void *junk, unsigned long num)
{
    int i;
    volatile int j;
    time_t secs1, secs2;
    uint32_t nsecs1, nsecs2;

    (void)junk;

    for (i=0; i<NCVLOOPS; i++) {
        lock_acquire(testlock);
        while (testval1 != num) {
            gettime(&secs1, &nsecs1);
            cv_wait(testcv, testlock);
            gettime(&secs2, &nsecs2);

            if (nsecs2 < nsecs1) {
                secs2--;
                nsecs2 += 1000000000;
            }

            nsecs2 -= nsecs1;
            secs2 -= secs1;

            /* Require at least 2000 cpu cycles (we're 25mhz) */
            if (secs2==0 && nsecs2 < 40*2000) {
                kprintf("cv_wait took only %u ns\n", nsecs2);
                kprintf("That's too fast... you must be "
                        "busy-looping\n");
                V(donesem);
                thread_exit(_MKWAIT_EXIT(1));
            }

        }
        kprintf("Thread %lu\n", num);
        testval1 = (testval1 + NTHREADS - 1)%NTHREADS;

        /*
         * loop a little while to make sure we can measure the
         * time waiting on the cv.
         */
        for (j=0; j<3000; j++);

        cv_broadcast(testcv, testlock);
        lock_release(testlock);
    }
    V(donesem);
}
Exemple #12
0
void _exit(int exitcode){

	int t= splhigh();
	splx(t);

	struct process_block *currentProcess = pid_array[getpid()];
	if(currentProcess !=NULL){
		currentProcess->exited = true;
		currentProcess->exitcode = _MKWAIT_EXIT(exitcode);
		thread_exit();
	}
	else{
		kprintf("current process %d is null. something wrong\n",(int)getpid());
	}
}
Exemple #13
0
void proctable_exit_process(struct proc *proc_exited, int exitcode) {
  // DEBUG(DB_EXEC, "Exiting PID: %d from proctable\n", getPID(proc_exited));

  KASSERT(proc_exited != NULL);
  KASSERT(proc_exited->p_pid > 0);

  // set the process state to exited
  setState(proc_exited, PROC_EXITED);

  // encode the exit code as per the docs.
  setExitcode(proc_exited, _MKWAIT_EXIT(exitcode));

  // Next we need to evaluate some cases:
  // If proc_exited has living children, they should now have a NULL parent.
  // If proc_exited has dead children, they should now be destroyed.

  int exitedPID = getPID(proc_exited);

  // Find the children of proc_exited.
  for (int i = MIN_PID; i < pidLimit; i++) {
    struct proc* cur = procarray_get(procTable, i);
    if (cur != NULL && getPPID(cur) == exitedPID) {
      // Check state of child
      int state = getState(cur);
      
      // A running child has its parent set to NULL
      if (state == PROC_RUNNING) {
        setPPID(cur, PROC_NO_PID);
      }

      // An exited child can now be completely removed.
      else if (state == PROC_EXITED) {
        proctable_remove_process(cur);
      }
    }
  }

  // If proc_exited has no parent, it can be removed
  if (getPPID(proc_exited) == PROC_NO_PID) {
    proctable_remove_process(proc_exited);
  }

  // Otherwise if proc_exited has a parent
  // then proc_exited must wake its potentially waiting parent
  else {
    cv_signal(proc_exited->wait_cv, procTableLock);
  }
}
Exemple #14
0
static
void
waitfirstthread(void *junk, unsigned long num)
{
	unsigned long i;
	(void)junk;
	
	kprintf("waitfirstthread %lu started...\n", num);

	for (i = 0; i < 100 * (num + 1); i++)
		thread_yield();

	kprintf("waitfirstthread %lu exiting.\n", num);

	thread_exit(_MKWAIT_EXIT(num));
}
Exemple #15
0
void sys_exit(int exit_code){
	pid_t pid = curthread->pid ;
	lock_acquire(process_table[pid]->exit_lock) ;
	process_table[pid]->exited = true ;
	process_table[pid]->exitcode=_MKWAIT_EXIT(exit_code);
	int i=0;
	for(i=0;i<OPEN_MAX_LOCAL;i++){
		if(curthread->fd[i] != NULL)
		{
			sys_close((userptr_t)i);
		}

	}
	cv_broadcast(process_table[pid]->exit_cv,process_table[pid]->exit_lock) ;
	lock_release(process_table[pid]->exit_lock) ;
	thread_exit();
}
Exemple #16
0
void sys__exit(int exitcode) {
  struct addrspace *as;
  struct proc *p = curproc;
  /* for now, just include this to keep the compiler from complaining about
     an unused variable */

  //(void) exitcode;

#if OPT_A2
  proctable_update(proctable, curproc,_MKWAIT_EXIT (exitcode));
#endif
  DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);

  KASSERT(curproc->p_addrspace != NULL);
  as_deactivate();
  /*
   * clear p_addrspace before calling as_destroy. Otherwise if
   * as_destroy sleeps (which is quite possible) when we
   :* come back we'll be calling as_activate on a
   * half-destroyed address space. This tends to be
   * messily fatal.
   */
  as = curproc_setas(NULL);
  as_destroy(as);
  
  /* detach this thread from its process */
  /* note: curproc cannot be used after this call */
  proc_remthread(curthread);

  /* if this is the last user process in the system, proc_destroy()
     will wake up the kernel menu thread */
  proc_destroy(p);
  
  thread_exit();
  /* thread_exit() does not return, so we should never get here */
  panic("return from thread_exit in sys_exit\n");
}
Exemple #17
0
void sys__exit(int exitcode) {
	(void) exitcode;

	lock_acquire(proc_table_lock);

	// orphan all children, should be done no matter what
	for (int i = 0; i < PID_MAX; i++) {
		// Found a children
		if (proc_table[i] != NULL && proc_table[i]->parent_pid == curproc->pid) {
			proc_table[i]->parent_pid = INVALID_PID;
			// weird case, parent doesn't wait, but exited later
			if (proc_table[i]->exited) {
				proc_destroy(proc_table[i]);
			}
		}
	}

	// set exitcode stuff is probably unnecessary for orphan
	if (curproc->parent_pid == INVALID_PID) {
		// Parent is dead, suicide
		proc_destroy(curproc);
	} else {
		// do fancy shit and don't destroy itself
		// it should be destroyed by parent in waitpid

		// TODO: This is probably not a good design
		curproc->exited = true;
		curproc->exitcode = _MKWAIT_EXIT(exitcode);
		// Wake up parent
		cv_signal(curproc->waitpid_cv, proc_table_lock);
	}

	lock_release(proc_table_lock);
	// kfree(curproc);
	thread_exit();
}
/*
 * System call dispatcher.
 *
 * A pointer to the trapframe created during exception entry (in
 * exception.S) is passed in.
 *
 * The calling conventions for syscalls are as follows: Like ordinary
 * function calls, the first 4 32-bit arguments are passed in the 4
 * argument registers a0-a3. 64-bit arguments are passed in *aligned*
 * pairs of registers, that is, either a0/a1 or a2/a3. This means that
 * if the first argument is 32-bit and the second is 64-bit, a1 is
 * unused.
 *
 * This much is the same as the calling conventions for ordinary
 * function calls. In addition, the system call number is passed in
 * the v0 register.
 *
 * On successful return, the return value is passed back in the v0
 * register, or v0 and v1 if 64-bit. This is also like an ordinary
 * function call, and additionally the a3 register is also set to 0 to
 * indicate success.
 *
 * On an error return, the error code is passed back in the v0
 * register, and the a3 register is set to 1 to indicate failure.
 * (Userlevel code takes care of storing the error code in errno and
 * returning the value -1 from the actual userlevel syscall function.
 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
 *
 * Upon syscall return the program counter stored in the trapframe
 * must be incremented by one instruction; otherwise the exception
 * return code will restart the "syscall" instruction and the system
 * call will repeat forever.
 *
 * If you run out of registers (which happens quickly with 64-bit
 * values) further arguments must be fetched from the user-level
 * stack, starting at sp+16 to skip over the slots for the
 * registerized values, with copyin().
 */
void
syscall(struct trapframe *tf)
{
	int callno;
	int32_t retval;
	int err;

	KASSERT(curthread != NULL);
	KASSERT(curthread->t_curspl == 0);
	KASSERT(curthread->t_iplhigh_count == 0);

	callno = tf->tf_v0;

	/*
	 * Initialize retval to 0. Many of the system calls don't
	 * really return a value, just 0 for success and -1 on
	 * error. Since retval is the value returned on success,
	 * initialize it to 0 by default; thus it's not necessary to
	 * deal with it except for calls that return other values, 
	 * like write.
	 */

	retval = 0;

	switch (callno) {
	    case SYS_reboot:
		    err = sys_reboot(tf->tf_a0);
		    break;

	    case SYS___time:
		    err = sys___time((userptr_t)tf->tf_a0,
				     (userptr_t)tf->tf_a1);


		    break;

            /* ASST2: These implementations of read and write only work for
             * console I/O (stdin, stdout and stderr file descriptors)
             */
            case SYS_read:
                err = sys_read(tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2,
                               &retval);
                break;

            case SYS_write:
                err = sys_write(tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2,
                                &retval);
                break;

            /* process calls */
            case SYS__exit:
            	thread_exit(_MKWAIT_EXIT(tf->tf_a0));
            	panic("Returning from exit\n");
	
            case SYS_fork:
            	err = sys_fork(tf, &retval);
            	break;

            /* ASST2 - You need to fill in the code for each of these cases */
            case SYS_getpid:
            	err = sys_getpid(&retval);
                break;

            case SYS_waitpid:
                if(sys_waitpid(tf->tf_a0, \
                		(userptr_t)tf->tf_a1, tf->tf_a2, &retval) == -1)
                {
                  err=retval;
                }
                else{
                err=0;
                }
                break;

            case SYS_kill:
            	err = sys_kill(tf->tf_a0, tf->tf_a1);
            	break;

	    /* Even more system calls will go here */
 
	    default:
		kprintf("Unknown syscall %d\n", callno);
		err = ENOSYS;
		break;
	}


	if (err) {
		/*
		 * Return the error code. This gets converted at
		 * userlevel to a return value of -1 and the error
		 * code in errno.
		 */
		tf->tf_v0 = err;
		tf->tf_a3 = 1;      /* signal an error */
	}
	else {
		/* Success. */
		tf->tf_v0 = retval;
		tf->tf_a3 = 0;      /* signal no error */
	}
	
	/*
	 * Now, advance the program counter, to avoid restarting
	 * the syscall over and over again.
	 */
	
	tf->tf_epc += 4;

	/* Make sure the syscall code didn't forget to lower spl */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);
}