Example #1
0
File: menu.c Project: Adam-Koza/A3
static
int
common_prog(int nargs, char **args)
{
	int result;
	char **args_copy;
#if OPT_SYNCHPROBS
	kprintf("Warning: this probably won't work with a "
		"synchronization-problems kernel.\n");
#endif

	/*
	 * Implementation of & option for menu when running programs.
	 * By default, menu will wait for user program to end before running.
	 * If on menu command line has a '&' at the end,
	 * it will not wait for the user program to end
	 * before continuing to run.
	 */

	bool toDetach;
	toDetach = false;
	pid_t childpid;
	if (*args[nargs - 1] == '&'){
		nargs--; // So we don't pass on &
		toDetach = true;
	}


	/* demke: Make a copy of arguments to pass to new thread,
	 * so that we aren't depending on parent's stack!
	 */
	args_copy = copy_args(nargs, args);
	if (!args_copy) {
		return ENOMEM;
	}

	/* demke: and now call thread_fork with the copy */
	
	result = thread_fork(args_copy[0] /* thread name */,
			cmd_progthread /* thread function */,
			args_copy /* thread arg */, nargs /* thread arg */,
			&childpid);
	if (result) {
		kprintf("thread_fork failed: %s\n", strerror(result));
		/* demke: need to free copy of args if fork fails */
		free_args(nargs, args_copy);
		return result;
	}

	// If toDetach, then wont wait for program to end before continuing menu.
	if (toDetach) {
		pid_detach(childpid);
	}
	// Wait for program to end before continuing
	// (unless it's detached, in which case join will do nothing.)
	pid_join(childpid, NULL, (int)NULL);

	return 0;
}
Example #2
0
/*
 * pid_exit 
 *  - sets the exit status of this thread (i.e. curthread). 
 *  - disowns children. 
 *  - if dodetach is true, children are also detached. 
 *  - wakes any thread waiting for the curthread to exit. 
 *  - frees the PID and exit status if the curthread has been detached. 
 *  - must be called only if the thread has had a pid assigned.
 */
void
pid_exit(int status, bool dodetach)
{
	struct pidinfo *my_pi;

	
	// Implement me. Existing code simply sets the exit status.
	lock_acquire(pidlock);

	my_pi = pi_get(curthread->t_pid);
	KASSERT(my_pi != NULL);
	my_pi->pi_exitstatus = status;
	my_pi->pi_exited = true;

	/* Disown kids */
	int i;
	struct pidinfo *current_kid;
	for(i = 0; i < my_pi->kids_tail; i++){
		current_kid = pi_get(my_pi->kids[i]);

		if(current_kid != NULL){
			current_kid->pi_ppid = INVALID_PID;
			if(dodetach){
				lock_release(pidlock);
				pid_detach(current_kid->pi_pid);
			}
		}
	}
		

	//wake people up
	cv_broadcast(my_pi->pi_cv, pidlock);

	if(my_pi->detached){
		my_pi->pi_ppid = INVALID_PID;
		pi_drop(my_pi->pi_pid);
	}

	if(lock_do_i_hold(pidlock)){
		lock_release(pidlock);
	}	
}
Example #3
0
/*
 * pid_exit 
 *  - sets the exit status of this thread (i.e. curthread). 
 *  - disowns children. 
 *  - if dodetach is true, children are also detached. 
 *  - wakes any thread waiting for the curthread to exit. 
 *  - frees the PID and exit status if the curthread has been detached. 
 *  - must be called only if the thread has had a pid assigned.
 */
void
pid_exit(int status, bool dodetach)
{

	// Lock aquired
	lock_acquire(pidlock); 

	// Get the current thread pid
	struct pidinfo *my_pi;
	my_pi = pi_get(curthread->t_pid);
	KASSERT(my_pi != NULL);

	// Set the current pid exit to true and set the exitstatus
	my_pi->pi_exited = true;
	my_pi->pi_exitstatus = status;
	struct pidinfo *this_pid = NULL;
	// If dodetach is true, then we detach every child of this process
	if(dodetach){
		for(int i =PID_MIN; i < PID_MAX; i++){ 
			this_pid = pi_get((pid_t)i);
			if((this_pid != NULL) && (this_pid->pi_ppid == my_pi->pi_pid)){
				lock_release(pidlock);
				pid_detach(this_pid->pi_pid);
				// Set Parent pid to invalid after detach
				lock_acquire(pidlock);
				this_pid->detached = true;
			}
		}
	}

	// tell the waiting thread about the exit status
	cv_broadcast(my_pi->pi_cv, pidlock); 

	// if the pid we called is being detached, then we clear it in the 
	// pid list
	if(my_pi->detached){
		my_pi->pi_ppid = INVALID_PID;
		pi_drop(my_pi->pi_pid);
	}

	lock_release(pidlock);
}
Example #4
0
/*
 * pid_exit 
 *  - sets the exit status of this thread (i.e. curthread). 
 *  - disowns children. 
 *  - if dodetach is true, children are also detached. 
 *  - wakes any thread waiting for the curthread to exit. 
 *  - frees the PID and exit status if the curthread has been detached. 
 *  - must be called only if the thread has had a pid assigned.
 */
void
pid_exit(int status, bool dodetach)
{
	struct pidinfo *my_pi;

	lock_acquire(pidlock);

	my_pi = pi_get(curthread->t_pid);
	KASSERT(my_pi != NULL);

	/* Thread has had a pid assigned */
       	KASSERT(my_pi->pi_pid == curthread->t_pid);

	my_pi->pi_exitstatus = status;
	my_pi->pi_exited = true;

	/* Disown children */
	int i;
	for (i = 0; i < PROCS_MAX; i++){
	  if (pidinfo[i] != NULL && pidinfo[i]->pi_ppid == my_pi->pi_pid){
	    pidinfo[i]->pi_ppid = INVALID_PID;
	    
	    if (dodetach){
	      pid_detach(pidinfo[i]->pi_pid);
	    }
	  }
	}

	/* Wake up all threads waiting for curthread to exit */
	if (my_pi->waitingThreads != 0){
	  cv_broadcast(my_pi->pi_cv, pidlock);
	}

	/* Free the PID and exit status if curthread is detached */
	if (my_pi->detached){
	  my_pi->pi_ppid = INVALID_PID;
	  pi_drop(my_pi->pi_pid);
	}
	
	lock_release(pidlock);
}
Example #5
0
int thread_detach(pid_t pid) {
	/* Same as thread_join, we just hand off to pid function. */
	return pid_detach(pid);
}
Example #6
0
int
waittest(int nargs, char **args)
{
	int i, spl, status, err;
	pid_t kid;

	pid_t kids2[NTHREADS];
	int kids2_head = 0, kids2_tail = 0;

	(void)nargs;
	(void)args;

	init_sem();

	kprintf("Starting wait test...\n");
	
	/*
	 * This first set should (hopefully) still be running when
	 * wait is called (helped by the splhigh).
	 */
	
	kprintf("\n");
	kprintf("Set 1 (wait should generally succeed)\n");
	kprintf("-------------------------------------\n");

	spl = splhigh();
	for (i = 0; i < NTHREADS; i++) {
		err = thread_fork("wait test thread", waitfirstthread, NULL, i,
				  &kid);
		if (err) {
			panic("waittest: thread_fork failed (%d)\n", err);
		}
		kprintf("Spawned pid %d\n", kid);
		kids2[kids2_tail] = kid;
		kids2_tail = (kids2_tail+1) % NTHREADS;
	}
	splx(spl);

	for (i = 0; i < NTHREADS; i++) {
		kid = kids2[kids2_head];
		kids2_head = (kids2_head+1) % NTHREADS;
		kprintf("Waiting on pid %d...\n", kid);
		err = pid_join(kid, &status, 0);
		if (err) {
			kprintf("Pid %d waitpid error %d!\n", kid, err);
		}
		else {
			kprintf("Pid %d exit status: %d\n", kid, status);
		}
	}

	/*
	 * This second set has to V their semaphore before the exit,
	 * so when wait is called, they will have already exited, but
	 * their parent is still alive.
	 */

	kprintf("\n");
	kprintf("Set 2 (wait should always succeed)\n");
	kprintf("----------------------------------\n");

	for (i = 0; i < NTHREADS; i++) {
		err = thread_fork("wait test thread", exitfirstthread, NULL, i,
				  &kid);
		if (err) {
			panic("waittest: thread_fork failed (%d)\n", err);
		}
		kprintf("Spawned pid %d\n", kid);
		kids2[kids2_tail] = kid;
		kids2_tail = (kids2_tail+1) % NTHREADS;
		if (err) {
			panic("waittest: q_addtail failed (%d)\n", err);
		}
	}

	for (i = 0; i < NTHREADS; i++) {
		kid = kids2[kids2_head];
		kids2_head = (kids2_head+1) % NTHREADS;
		kprintf("Waiting for pid %d to V()...\n", kid);
		P(exitsems[i]);
		kprintf("Appears that pid %d P()'d\n", kid);
		kprintf("Waiting on pid %d...\n", kid);
		err = pid_join(kid, &status, 0);
		if (err) {
			kprintf("Pid %d waitpid error %d!\n", kid, err);
		}
		else {
			kprintf("Pid %d exit status: %d\n", kid, status);
		}
	}

	/*
	 * This third set has to V their semaphore before the exit, so
	 * when wait is called, they will have already exited, and
	 * since we've gone through and disowned them all, their exit
	 * statuses should have been disposed of already and our waits
	 * should all fail.
	 */

	kprintf("\n");
	kprintf("Set 3 (wait should never succeed)\n");
	kprintf("---------------------------------\n");

	for (i = 0; i < NTHREADS; i++) {
		err = thread_fork("wait test thread", exitfirstthread, NULL, i,
				  &kid);
		if (err) {
			panic("waittest: thread_fork failed (%d)\n", err);
		}
		kprintf("Spawned pid %d\n", kid);

		pid_detach(kid);
		
		kids2[kids2_tail] = kid;
		kids2_tail = (kids2_tail+1) % NTHREADS;
	}

	for (i = 0; i < NTHREADS; i++) {
		kid = kids2[kids2_head];
		kids2_head = (kids2_head+1) % NTHREADS;
		kprintf("Waiting for pid %d to V()...\n", kid);
		P(exitsems[i]);
		kprintf("Appears that pid %d P()'d\n", kid);
		kprintf("Waiting on pid %d...\n", kid);
		err = pid_join(kid, &status, 0);
		if (err) {
			kprintf("Pid %d waitpid error %d!\n", kid, err);
		}
		else {
			kprintf("Pid %d exit status: %d\n", kid, status);
		}
	}

	kprintf("\nWait test done.\n");

	return 0;
}