/* * 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; }
/* * 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; }
/* * 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); } }
/* * 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); }
/* * 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; }
/* * 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); }
/* * 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; }
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; } }
/* * 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; }
/* * 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); }
/* * 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); }
/* * 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; }
/* * 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); }
/* * 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; }
/* * 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); }
/* * 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; }
/* * 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); }
/* * 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); }
/* * 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; }
/* * 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; }
/* 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); }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }