Ejemplo n.º 1
0
Archivo: pid.c Proyecto: gapry/os161
/*
 * pid_join - Store the exit status of the thread associated with
 * targetpid (in the status argument) as soon as it is available. 
 * If the thread has not yet exited, curthread waits unless the flag 
 * WNOHANG is sent. Return the pid of the joined thread on success or
 * a negative error code otherwise.
 */
int
pid_join(pid_t targetpid, int *status, int flags)
{	
    int result = 0;
    
    /* Check if targetpid is valid. */
    if (targetpid == INVALID_PID || targetpid == BOOTUP_PID)
        return -1 * EINVAL;
    
    /* Check if targetpid is caller. */
    if (targetpid == curthread->t_pid)
        return -1 * EDEADLK;
    
    /* Obtain process information of target thread. */
    struct pidinfo *pinfo;
    lock_acquire(pidlock);
    pinfo = pi_get(targetpid);
    
    /* No thread associated with targetpid could be found. */
    if (pinfo == NULL) {
        result = -1 * ESRCH;
        goto out;
    }
    
    /* Check if target thread has been detached. */
    if (pinfo->detached) {
        result = -1 * EINVAL;
        goto out;
    }
    
    if (!pinfo->pi_exited) {
        /* Target thread has not exited. */
        if (flags == WNOHANG)
            goto out;
        else {
            /* Put thread to sleep. */
            pinfo->waitingthreads++;
            DEBUG(DB_THREADS, "Parent waiting for %d\n", targetpid);
            cv_wait(pinfo->pi_cv, pidlock);
            pinfo->waitingthreads--;
        }
    }
    
    /* Store the exit status of the target thread in the caller */
    if (status != NULL)
    	*status = pinfo->pi_exitstatus;

    result = targetpid;
    
    /* Clean up pidinfo if there is no other thread waiting. */
    if (pinfo->waitingthreads == 0) {
        pinfo->pi_ppid = INVALID_PID;
        pi_drop(targetpid);
    }
    
out:
    lock_release(pidlock);
	return result;
}
Ejemplo n.º 2
0
/*
 * pid_setexitstatus: Sets the exit status of this thread. Must only
 * be called if the thread actually had a pid assigned. Wakes up any
 * waiters and disposes of the piddata if nobody else is still using it.
 */
void
pid_setexitstatus(int status)
{
	struct pidinfo *us;
	int i;

	KASSERT(curthread->t_pid != INVALID_PID);

	lock_acquire(pidlock);

	/* First, disown all children */
	for (i=0; i<PROCS_MAX; i++) {
		if (pidinfo[i]==NULL) {
			continue;
		}
		if (pidinfo[i]->pi_ppid == curthread->t_pid) {
			pidinfo[i]->pi_ppid = INVALID_PID;
			if (pidinfo[i]->pi_exited) {
				pi_drop(pidinfo[i]->pi_pid);
			}
		}
	}

	/* Now, wake up our parent */
	us = pi_get(curthread->t_pid);
	KASSERT(us != NULL);

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

	if (us->pi_ppid == INVALID_PID) {
		/* no parent */
		pi_drop(curthread->t_pid);
	}
	else {
		cv_broadcast(us->pi_cv, pidlock);
	}

	lock_release(pidlock);
}
Ejemplo n.º 3
0
/*
 * pid_detach - disavows interest in the child thread's exit status, so 
 * it can be freed as soon as it exits. May only be called by the
 * parent thread.
 */
int
pid_detach(pid_t childpid)
{
	
	
	// Lock acquired
	lock_acquire(pidlock);
	
	// EINVAL: childpid is INVALID_PID or BOOTUP_PID.
	if(childpid == INVALID_PID || childpid == BOOTUP_PID || childpid < PID_MIN){
		lock_release(pidlock);
		return -EINVAL;
	}
	
	// Get the pid info for the child pid
	struct pidinfo *child_pid;
	child_pid = pi_get(childpid);


	// ESRCH: No thread could be found corresponding to that specified by childpid.
	if(child_pid == NULL){
		lock_release(pidlock);
		return -ESRCH;
	}

	// EINVAL: The thread childpid is already in the detached state.
	if(child_pid->pi_ppid == INVALID_PID){
		lock_release(pidlock);
		return -EINVAL;	
	}

	// EINVAL: The caller is not the parent of childpid.
	if(child_pid->pi_ppid != curthread->t_pid){
		lock_release(pidlock); 
		return -EINVAL;	
	}

	// If child has exit when pid_detach has been called, then call drop function
	// to remove pidinfo and free its space.
	child_pid->pi_ppid = INVALID_PID;
	child_pid->detached = true;
	if(child_pid->pi_exited == true){
		pi_drop(child_pid->pi_pid);
	}

	lock_release(pidlock); 
	// On success
	return 0;
}
Ejemplo n.º 4
0
Archivo: pid.c Proyecto: gapry/os161
/*
 * pid_detach - disavows interest in the child thread's exit status, so 
 * it can be freed as soon as it exits. May only be called by the
 * parent thread. Returns 0 if the thread childpid is successfully placed
 * in the detached state.
 */
int
pid_detach(pid_t childpid)
{
    int err = 0;
    
    /* Check if childpid is valid. */
    if (childpid == INVALID_PID || childpid == BOOTUP_PID)
        return EINVAL;
    
    /* Obtain process information of childs thread. */
    struct pidinfo *pinfo;
    lock_acquire(pidlock);
    pinfo = pi_get(childpid);
    
    /* No thread associated with childpid could be found. */
    if (pinfo == NULL) {
        err = ESRCH;
        goto out;
    }
    
    /* Check the childpid for the following:
     * (1) The caller is not the parent of childpid
     * (2) childpid has been joined at another thread
     * (3) childpid is already in the detached state */
    if (pinfo->pi_ppid != curthread->t_pid ||
        pinfo->waitingthreads > 0 ||
        pinfo->detached) {
        err = EINVAL;
        goto out;
    }
    
    /* If thread already exited, drop associated pidinfo.
     * Otherwise, detach childpid by setting pi_ppid. */
    if (pinfo->pi_exited) {
        pi_drop(childpid);
    } else {
        pinfo->detached = true;
    }
        
out:
    lock_release(pidlock);
	return err;
}
Ejemplo n.º 5
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);
	}	
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
/*
 * pid_disown - disown any interest in waiting for a child's exit
 * status.
 */
void
pid_disown(pid_t theirpid)
{
	struct pidinfo *them;

	KASSERT(theirpid >= PID_MIN && theirpid <= PID_MAX);

	lock_acquire(pidlock);

	them = pi_get(theirpid);
	KASSERT(them != NULL);
	KASSERT(them->pi_ppid==curthread->t_pid);

	them->pi_ppid = INVALID_PID;
	if (them->pi_exited) {
		pi_drop(them->pi_pid);
	}

	lock_release(pidlock);
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
/*
 * pid_detach - disavows interest in the child thread's exit status, so 
 * it can be freed as soon as it exits. May only be called by the
 * parent thread.
 */
int
pid_detach(pid_t childpid)
{

        /* The childpid is invalid or bootup pid */
	if (childpid == INVALID_PID || childpid == BOOTUP_PID){
	  return EINVAL;
	}

        struct pidinfo *pi;
	lock_acquire(pidlock);
	pi = pi_get(childpid);

	/* No thread could be found corresponding to that specified by childpid */
	if (pi == NULL){
	  lock_release(pidlock);
	  return ESRCH;
	}

	/* The thread childpid is already in detached state or the caller is not parent 
	    or the thread has joined another thread */
	if (pi->detached || pi->pi_ppid != curthread->t_pid || pi->waitingThreads > 0){
	  lock_release(pidlock);
	  return EINVAL;
	}	

	/* If childpid already exited, drop it from process tabel
	   else set it to detached state */
	if (pi->pi_exited){
	  pi->pi_ppid = INVALID_PID;
	  pi->pi_exited = true;
	  pi_drop(pi->pi_pid);
	} else {
	  pi->detached = true;
	}

	lock_release(pidlock);
	return 0;
	
}
Ejemplo n.º 10
0
/*
 * pid_unalloc - unallocate a process id (allocated with pid_alloc) that
 * hasn't run yet.
 */
void
pid_unalloc(pid_t theirpid)
{
	struct pidinfo *them;

	KASSERT(theirpid >= PID_MIN && theirpid <= PID_MAX);

	lock_acquire(pidlock);

	them = pi_get(theirpid);
	KASSERT(them != NULL);
	KASSERT(them->pi_exited == false);
	KASSERT(them->pi_ppid == curthread->t_pid);

	/* keep pidinfo_destroy from complaining */
	them->pi_exitstatus = 0xdead;
	them->pi_exited = true;
	them->pi_ppid = INVALID_PID;

	pi_drop(theirpid);

	lock_release(pidlock);
}
Ejemplo n.º 11
0
Archivo: pid.c Proyecto: gapry/os161
/*
 * 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 && my_pi->pi_pid == curthread->t_pid);
    
    // Update the exit status of the current thread
    my_pi->pi_exited = true;
    my_pi->pi_exitstatus = status;
    
    // Disown children.
    pid_t pidindex = PID_MIN;
	while (pidindex <= PID_MAX) {
        struct pidinfo *pinfo = pi_get(pidindex);
        if (pinfo != NULL && pinfo->pi_ppid == my_pi->pi_pid) {
            pinfo->pi_ppid = INVALID_PID;
            if (dodetach)
                pinfo->detached = true;
        }
		pidindex++;
	}
    
    /* If current thread has been detached, discard the pid struct. */
    if (my_pi->detached) {
        my_pi->pi_ppid = INVALID_PID;
        pi_drop(my_pi->pi_pid);
    } else {
        // Wakes any thread waiting for current thread.
        cv_broadcast(my_pi->pi_cv, pidlock);
    }
    
	lock_release(pidlock);
}
Ejemplo n.º 12
0
/*
 * pid_join - returns the exit status of the thread associated with
 * targetpid (in the status argument) as soon as it is available. 
 * If the thread has not yet exited, curthread waits unless the flag 
 * WNOHANG is sent. 
 *
 */
int
pid_join(pid_t targetpid, int *status, int flags)
{

	(void) flags;


	struct pidinfo *targetpi;


	pid_t temppid;  //temporarly hold the pid so we can destroy targetpi
	int tempstatus; ///temporaly holds pid status


	lock_acquire(pidlock);

	//ERROR: if "targetpid" is INVALID_PID or BOOTUP_PID then return "EINVAL"
	if(targetpid == INVALID_PID || targetpid == BOOTUP_PID){
		lock_release(pidlock);
		return EINVAL;
	}


	targetpi = pi_get(targetpid);

	//ERROR: if "targetpid" doesnt have a pid struct then return "ESRCH"
	if(targetpi == NULL){
		lock_release(pidlock);
		return ESRCH;
	}

	//ERROR: if "targetpid" has been detached then return "EINVAL"
	else if(targetpi->detached){
		lock_release(pidlock);
		return EINVAL;
	}

	//ERROR:if "targetpid" is pid of the thread that called PID_JOIN then return "EDEADLK". 
	//MUST ADD ERROR
	else if(targetpi->pi_pid == curthread->t_pid){
		lock_release(pidlock);
		return EDEADLK;
	}

	lock_release(pidlock);

	//check if pid has ALREADY exited
	if(targetpi->pi_exited){

		
		//grab needed information
		if(!status){
			temppid = targetpi->pi_pid;
		}else{
			tempstatus = targetpi->pi_exitstatus;
			temppid = targetpi->pi_pid;	
		}

		lock_acquire(pidlock);
		targetpi->pi_ppid = INVALID_PID;
		pi_drop(targetpi->pi_pid);
		lock_release(pidlock);

	}else{ //NOT EXITED

		if(flags == WNOHANG){
			return 0;
		}

		//increase exit count
		lock_acquire(exitlock);
		targetpi->joined_pid += 1;
		lock_release(exitlock);

		

		lock_acquire(pidlock);
		//wait it exit
		cv_wait(targetpi->pi_cv, pidlock);

		lock_release(pidlock);
		//grab needed imformation
		if(!status){
			temppid = targetpi->pi_pid;
		}else{
			tempstatus = targetpi->pi_exitstatus;
			temppid = targetpi->pi_pid;	
		}


		//decrease count
		lock_acquire(exitlock);
		targetpi->joined_pid -= 1;
		
		//if last person exiting, drop information
		if(targetpi->joined_pid==0){
			lock_acquire(pidlock);
			targetpi->pi_exited = true;
			targetpi->pi_ppid = INVALID_PID;
			pi_drop(targetpi->pi_pid);
			lock_release(pidlock);
		}

		lock_release(exitlock);

	}

	*status = tempstatus;
	return temppid;

}
Ejemplo n.º 13
0
/*
 * pid_detach - disavows interest in the child thread's exit status, so 
 * it can be freed as soon as it exits. May only be called by the
 * parent thread.
 */
int
pid_detach(pid_t childpid)
{

	struct pidinfo *childpi;

	lock_acquire(pidlock);

	//ERROR: if "childpid" is INVALID_PID or BOOTUP_PID then return "EINVAL"
	if(childpid == INVALID_PID || childpid == BOOTUP_PID){
		return EINVAL;
	}

	childpi = pi_get(childpid);

	/*
	1) check to see "childpid" has exited
	*/

	//ERROR: if thread "childpid" could not be found return "ESRCH"
	if (childpi == NULL){
		lock_release(pidlock);
		return ESRCH;
	}

	//ERROR: if thread "childpid" is already in deteached state then return "EINVAL"
		
	if(childpi->detached){
		lock_release(pidlock);
		return EINVAL;
	}

	//ERROR: if the calling thread is not the parent of "childpid" then return "EINVAL"
		
	else if(childpi->pi_ppid != curthread->t_pid){
		lock_release(pidlock);
		return EINVAL;
	}

	//ERROR: if "childpid" has already been joined by atleast one other thread return "EINVAL"
	else if(childpi->joined_pid == 1){
		lock_release(pidlock);
		return EINVAL;
	}

	//check if pid has already exited, if so then frees it.
	if(childpi->pi_exited){

		pi_drop(childpi->pi_pid);
	}

	//Put the childpid into the detached state
	else{
		childpi->detached = true;
	}
	

	lock_release(pidlock);

	return 0;
}
Ejemplo n.º 14
0
/*
 * Waits on a pid, returning the exit status when it's available.
 * status and ret are a kernel pointers, but pid/flags may come from
 * userland and may thus be maliciously invalid.
 *
 * status may be null, in which case the status is thrown away. ret
 * may only be null if WNOHANG is not set.
 */
int
pid_wait(pid_t theirpid, int *status, int flags, pid_t *ret)
{
	struct pidinfo *them;

	KASSERT(curthread->t_pid != INVALID_PID);

	/* Don't let a process wait for itself. */
	if (theirpid == curthread->t_pid) {
		return EINVAL;
	}

	/* 
	 * We don't support the Unix meanings of negative pids or 0
	 * (0 is INVALID_PID) and other code may break on them, so
	 * check now.
	 */
	if (theirpid == INVALID_PID || theirpid<0) {
		return EINVAL;
	}

	/* Only valid options */
	if (flags != 0 && flags != WNOHANG) {
		return EINVAL;
	}

	lock_acquire(pidlock);

	them = pi_get(theirpid);
	if (them==NULL) {
		lock_release(pidlock);
		return ESRCH;
	}

	KASSERT(them->pi_pid==theirpid);

	/* Only allow waiting for own children. */
	if (them->pi_ppid != curthread->t_pid) {
		lock_release(pidlock);
		return EPERM;
	}

	if (them->pi_exited == false) {
		if (flags == WNOHANG) {
			lock_release(pidlock);
			KASSERT(ret != NULL);
			*ret = 0;
			return 0;
		}
		/* don't need to loop on this */
		cv_wait(them->pi_cv, pidlock);
		KASSERT(them->pi_exited == true);
	}

	if (status != NULL) {
		*status = them->pi_exitstatus;
	}
	if (ret != NULL) {
		/* 
		 * In Unix you can wait for any of several possible
		 * processes by passing particular magic values of
		 * pid. wait then returns the pid you actually
		 * found. We don't support this, so always return the
		 * pid we looked for.
		 */
		*ret = theirpid;
	}

	them->pi_ppid = 0;
	pi_drop(them->pi_pid);

	lock_release(pidlock);
	return 0;
}