예제 #1
0
파일: pid.c 프로젝트: wangx173/CSC369-OS161
/*
 * pid_flag_activate - activate flag for input pid.
 * return 0 if successfull. Negative error code otherwise.
 *
 */
int pid_flag_activate(pid_t pid, int flag)
{
    // First get lock
    lock_acquire(pidlock);
    
    // Invalid signal.
    if (flag < 0 || flag > 31) {
        lock_release(pidlock);
        return -EINVAL;
    }
    
    // Unimplemented signal.
    if (flag != SIGINT && flag != SIGKILL && flag != SIGTERM && flag != SIGSTOP && flag != SIGCONT && flag != SIGHUP && flag != SIGWINCH && flag != SIGINFO && flag != 0) {
        lock_release(pidlock);
        return -EUNIMP;
    }
    // Check if the pid is legal or not.
    if (pid > PID_MAX || pid < PID_MIN || pid == INVALID_PID) {
        lock_release(pidlock);
        return -ESRCH;
    }
    
    // Create pidinfo struct for thread.
    struct pidinfo* info = pi_get(pid);
    // If thread doesn't exist, release lock.
    if (! info) {
        lock_release(pidlock);
        return -ESRCH;
    }
    
    // If thread exists, set its flag and release lock.
    info->flag = flag;
    lock_release(pidlock);
    return 0;
}
예제 #2
0
파일: pid.c 프로젝트: 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;
}
예제 #3
0
파일: pid.c 프로젝트: premachb/csc369A1
/*
 * 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);
	}	
}
예제 #4
0
파일: pid.c 프로젝트: YueGan/CSCC69A1
/*
 * 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);
}
예제 #5
0
파일: pid.c 프로젝트: YueGan/CSCC69A1
/*
 * target_parent(pid_t targetpid) returns 1 if the target's parent is
 * current thread, if not retuns 0
 */
int target_parent(pid_t targetpid, int parentpid){
	lock_acquire(pidlock); 

	struct pidinfo *target_pid = pi_get(targetpid);
	if(target_pid->pi_ppid == parentpid){
		lock_acquire(pidlock);
		return 1;
	}
	lock_acquire(pidlock);
	return 0;
}
예제 #6
0
/*
 * pid_exit - sets the exit status of this thread, disowns children,
 * and wakes any thread waiting for the curthread to exit. Frees 
 * the PID and exit status if the thread has been detached. Must be
 * called only if the thread has had a pid assigned.
 */
void
pid_exit(int status)
{
	struct pidinfo *my_pi;
	
	// Implement me. Existing code simply sets the exit status.
	my_pi = pi_get(curthread->t_pid);
	KASSERT(my_pi != NULL);
	my_pi->pi_exitstatus = status;

	lock_release(pidlock);
}
예제 #7
0
파일: pid.c 프로젝트: wangx173/CSC369-OS161
/*
 * pid_join - returns the exit status of the thread associated with
 * targetpid 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)
{
         /* The targetpid is invalid or bootup pid */
         if (targetpid == INVALID_PID || targetpid == BOOTUP_PID || targetpid < PID_MIN || targetpid > PID_MAX){
             return EINVAL * -1;
	 }

	 /* The targetpid refers to the calling thread */
	 if (targetpid == curthread->t_pid){
	   return EDEADLK * -1;
	 }

	 struct pidinfo *pi;
	 lock_acquire(pidlock);
	 pi = pi_get(targetpid);
	 
	 /* No thread could be found corresponding to that specified by targetpid */
	 if (pi == NULL){
	   lock_release(pidlock);
	   return ESRCH * -1;
	 }

	 /* The thread corresponding to targetpid has been detached */
	 if (pi->detached){
	   lock_release(pidlock);
	   return EINVAL * -1;
	 }

	 /* If thread has not exited */
	 if (!pi->pi_exited){

	   /* and the flag is not WNOHANG, we suspend this thread */
	   if (flags != WNOHANG){
	     pi->waitingThreads++;
	     cv_wait(pi->pi_cv, pidlock);
	     pi->waitingThreads--;
	   } else {
	     lock_release(pidlock);
	     return 0;
	   }
	 }

	 /* If status is not NULL, we store exit status of thread targetpid */
	 if (status != NULL){
	   *status = pi->pi_exitstatus;
	 }

	 lock_release(pidlock);
	 return targetpid;
}
예제 #8
0
파일: pid.c 프로젝트: premachb/csc369A1
bool pid_is_child(pid_t targetpid){
	pid_t my_pid = curthread->t_pid;

	lock_acquire(pidlock);
		struct pidinfo *tpi = pi_get(targetpid);
	lock_release(pidlock);

	if (tpi->pi_ppid == my_pid){
		return true;
	}
	else{
		return false;
	}
}
예제 #9
0
파일: pid.c 프로젝트: YueGan/CSCC69A1
/*
 * 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;
}
예제 #10
0
파일: pid.c 프로젝트: 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);
}
예제 #11
0
파일: pid.c 프로젝트: 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;
	
	(void)dodetach; /* for compiler - delete when dodetach has real use */

	// 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;

	lock_release(pidlock);
}
예제 #12
0
파일: pid.c 프로젝트: 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;
}
예제 #13
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);
}
예제 #14
0
파일: pid.c 프로젝트: gapry/os161
/*
 * Check whether ppid of a thread of given pid is the same as
 * the current thread's pid.
 * Returns -1 if such pid does not exist, 1 if comparison is true,
 * 0 otherwise.
 */
int
check_ppid(pid_t pid)
{
    struct pidinfo *my_pi;
    int retval;
    
    lock_acquire(pidlock);
    my_pi = pi_get(pid);
    
    if (my_pi == NULL) {
        return -1;
    } else if (my_pi->pi_ppid == curthread->t_pid) {
        retval = 1;
    } else {
        retval = 0;
    }
    
    lock_release(pidlock);
    return retval;
}
예제 #15
0
파일: pid.c 프로젝트: wangx173/CSC369-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);

	/* 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);
}
예제 #16
0
파일: pid.c 프로젝트: wangx173/CSC369-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.
 */
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;
	
}
예제 #17
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);
}
예제 #18
0
파일: pid.c 프로젝트: premachb/csc369A1
/*
 * 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);
}
예제 #19
0
파일: pid.c 프로젝트: premachb/csc369A1
/*
 * Create a pidinfo structure for the specified pid.
 */
static
struct pidinfo *
pidinfo_create(pid_t pid, pid_t ppid)
{
	struct pidinfo *pi;
	struct pidinfo *ppi;

	if(ppid != INVALID_PID){
		ppi = pi_get(ppid);
		ppi->kids[ppi->kids_tail] = pid;
		ppi->kids_tail++;
	}

	KASSERT(pid != INVALID_PID);

	pi = kmalloc(sizeof(struct pidinfo));
	if (pi==NULL) {
		return NULL;
	}

	pi->pi_cv = cv_create("pidinfo cv");
	if (pi->pi_cv == NULL) {
		kfree(pi);
		return NULL;
	}

	pi->pi_pid = pid;
	pi->pi_ppid = ppid;
	pi->pi_exited = false;
	pi->pi_exitstatus = 0xbaad;  /* Recognizably invalid value */
	pi->joined_pid = 0;
	pi->detached = false;
	pi->kids_tail = 0;

	return pi;
}
예제 #20
0
파일: pid.c 프로젝트: wangx173/CSC369-OS161
/*
 * pid_flag_retrieve - return the flag for input pid. Error code otherwise.
 *
 */
int pid_flag_retrieve(pid_t pid)
{
    // First get lock
    lock_acquire(pidlock);
    
    // Check if the pid is legal or not.
    if (pid > PID_MAX || pid < PID_MIN || pid == INVALID_PID) {
        lock_release(pidlock);
        return EINVAL;
    }
    
    // Create pidinfo struct for thread.
    struct pidinfo* info = pi_get(pid);
    // If thread doesn't exist, release lock.
    if (! info) {
        lock_release(pidlock);
        return ESRCH;
    }
    
    // Retrieve flag, release lock, return flag.
    int flag = info->flag;
    lock_release(pidlock);
    return flag;
}
예제 #21
0
파일: pid.c 프로젝트: gapry/os161
/* Handle the signal for a thread with given pid. */
void
pid_handlesignal(pid_t pid)
{
	/* Obtain process information of target thread. */
	struct pidinfo *pinfo;
	lock_acquire(pidlock);
	pinfo = pi_get(pid);
    /* Check if the thread associated with pid was found */
    KASSERT(pinfo != NULL);

    /* Handle signal. */    
    if (pinfo->sigkill > 0) {
    	/* Order the thread to exit */
        lock_release(pidlock);
        thread_exit(_MKWAIT_SIG(pinfo->sigkill));
    } else if (pinfo->sigstop) {
        /* Order the thread to sleep, and set the sigstop
         * flag to false when woken up */
        cv_wait(pinfo->pi_signal_cv, pidlock);
        pinfo->sigstop = false;
    }

	lock_release(pidlock);
}
예제 #22
0
파일: pid.c 프로젝트: premachb/csc369A1
/*
 * 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;
}
예제 #23
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;
}
예제 #24
0
파일: pid.c 프로젝트: premachb/csc369A1
/*
 * 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;

}
예제 #25
0
파일: pid.c 프로젝트: gapry/os161
/*
 * pid_setsignal - Set the signal for a thread with given pid.
 * Store a return value of 0 to retval if no errors occur and -1
 * otherwise. Return the error code if an error occurs and 0 otherwise.
 */
int
pid_setsignal(pid_t targetpid, int signal, int *retval)
{
    int err = 0;
    
    /* 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) {
        err = ESRCH;
        goto out;
    }
    
    /* Check if given signal is valid and implemented. */
    if (signal <= 0 || signal > 31) {
        /* Signal is invalid. */
        err = EINVAL;
        goto out;
    } else {
        volatile bool implemented = false;
        int size = sizeof(implemented_signals) / sizeof(int *);
        int i;
        for (i = 0; i < size; i++) {
            if (implemented_signals[i] == signal) {
                implemented = true;
                break;
            }
        }
        
        if (!implemented) {
            /* Signal is not implemented. */
            err = EUNIMP;
            goto out;
        }
    }

    switch (signal) {
        case SIGHUP:
        case SIGINT:
        case SIGKILL:
        case SIGTERM:
        	/* For signals that terminates a process, set the pid's
        	 * sigkill flag to the specified signal. */
            pinfo->sigkill = signal;
            break;
        case SIGSTOP:
            pinfo->sigstop = true;
            break;
        case SIGCONT:
        	/* Wake up the target thread if the thread was
        	 * put to sleep with SIGSTOP */
            if (pinfo->sigstop) {
                cv_signal(pinfo->pi_signal_cv, pidlock);
            }    
            break;
        default:
            break;
	}
    
out:
	if (err > 0) {
    	/* An error occurred. */
    	*retval = -1;
    } else {
    	*retval = 0;
    }

    lock_release(pidlock);
    return err;
}
예제 #26
0
파일: pid.c 프로젝트: YueGan/CSCC69A1
/*
 * pid_join - returns the exit status of the thread associated with
 * targetpid 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)
{

	
	// Lock acquired
	lock_acquire(pidlock);
	
	// EINVAL: targetpid is INVALID_PID or BOOTUP_PID.
	if(targetpid == INVALID_PID || targetpid == BOOTUP_PID || targetpid < PID_MIN || targetpid > PID_MAX){
		lock_release(pidlock);
		return -EINVAL;
	}

	// Get the pid info for the target pid
	struct pidinfo *target_pid = pi_get(targetpid);


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

	// EINVAL: The thread corresponding to targetpid has been detached.
	if (target_pid->pi_ppid == INVALID_PID){
		lock_release(pidlock);
		return -EINVAL;
	}


	// EDEADLK: The targetpid argument refers to the calling thread
	if(targetpid == curthread->t_pid){
		lock_release(pidlock); 
		return -EDEADLK;
	}

	// If pid has not exit
	if(target_pid->pi_exited == false){

		// Then if flag raise WNOHANG then return 
		if(flags == WNOHANG){
			*status = 0;
			lock_release(pidlock);
			return 0;	
		}

		// Else it waits until it exits
		else{
			cv_wait(target_pid->pi_cv, pidlock);
			// keep it for now
			//KASSERT(target_pid->pi_exited == true);
		}
	}

	// If the targerpid has exited, set status to target pid's exit status
	// TO-DO check exited is true or not !!!!!!!!!!!!!!!
	if (status != NULL){
		*status = target_pid->pi_exitstatus;
	}

/*
	else{
		return -EFAULT;
	}
*/

	lock_release(pidlock);
	// Should return joined pid
	return targetpid;
}