| 
							
								 | 
							
							/*
 | 
						
						
						
						
							 | 
							
								 | 
							
							 *  linux/kernel/exit.c
 | 
						
						
						
						
							 | 
							
								 | 
							
							 *
 | 
						
						
						
						
							 | 
							
								 | 
							
							 *  (C) 1991  Linus Torvalds
 | 
						
						
						
						
							 | 
							
								 | 
							
							 */
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <errno.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <signal.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <sys/wait.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <linux/sched.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <linux/kernel.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <linux/tty.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <asm/segment.h>
 | 
						
						
						
						
							 | 
							
								 | 
							
							#include <unistd.h>//
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_pause(void);
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_close(int fd);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							void* thread_value[4096] = {};//
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							void release(struct task_struct* p)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								int i;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (!p)
 | 
						
						
						
						
							 | 
							
								 | 
							
									return;
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (i = 1; i < NR_TASKS; i++)
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (task[i] == p) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										task[i] = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
										free_page((long)p);
 | 
						
						
						
						
							 | 
							
								 | 
							
										schedule();
 | 
						
						
						
						
							 | 
							
								 | 
							
										return;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
								panic("trying to release non-existent task");
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							static inline int send_sig(long sig, struct task_struct* p, int priv)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (!p || sig < 1 || sig>32)
 | 
						
						
						
						
							 | 
							
								 | 
							
									return -EINVAL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (priv || (current->euid == p->euid) || suser())
 | 
						
						
						
						
							 | 
							
								 | 
							
									p->signal |= (1 << (sig - 1));
 | 
						
						
						
						
							 | 
							
								 | 
							
								else
 | 
						
						
						
						
							 | 
							
								 | 
							
									return -EPERM;
 | 
						
						
						
						
							 | 
							
								 | 
							
								return 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							static void kill_session(void)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								struct task_struct** p = NR_TASKS + task;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
								while (--p > &FIRST_TASK) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (*p && (*p)->session == current->session)
 | 
						
						
						
						
							 | 
							
								 | 
							
										(*p)->signal |= 1 << (SIGHUP - 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							/*
 | 
						
						
						
						
							 | 
							
								 | 
							
							 * XXX need to check permissions needed to send signals to process
 | 
						
						
						
						
							 | 
							
								 | 
							
							 * groups, etc. etc.  kill() permissions semantics are tricky!
 | 
						
						
						
						
							 | 
							
								 | 
							
							 */
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_kill(int pid, int sig)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								struct task_struct** p = NR_TASKS + task;
 | 
						
						
						
						
							 | 
							
								 | 
							
								int err, retval = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (!pid) while (--p > &FIRST_TASK) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (*p && (*p)->pgrp == current->pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (err = send_sig(sig, *p, 1))
 | 
						
						
						
						
							 | 
							
								 | 
							
											retval = err;
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								else if (pid > 0) while (--p > &FIRST_TASK) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (*p && (*p)->pid == pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (err = send_sig(sig, *p, 0))
 | 
						
						
						
						
							 | 
							
								 | 
							
											retval = err;
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								else if (pid == -1) while (--p > &FIRST_TASK)
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (err = send_sig(sig, *p, 0))
 | 
						
						
						
						
							 | 
							
								 | 
							
										retval = err;
 | 
						
						
						
						
							 | 
							
								 | 
							
									else while (--p > &FIRST_TASK)
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (*p && (*p)->pgrp == -pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
											if (err = send_sig(sig, *p, 0))
 | 
						
						
						
						
							 | 
							
								 | 
							
												retval = err;
 | 
						
						
						
						
							 | 
							
								 | 
							
								return retval;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							static void tell_father(int pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								int i;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
									for (i = 0; i < NR_TASKS; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (!task[i])
 | 
						
						
						
						
							 | 
							
								 | 
							
											continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (task[i]->pid != pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
											continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
										task[i]->signal |= (1 << (SIGCHLD - 1));
 | 
						
						
						
						
							 | 
							
								 | 
							
										return;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
								/* if we don't find any fathers, we just release ourselves */
 | 
						
						
						
						
							 | 
							
								 | 
							
								/* This is not really OK. Must change it to make father 1 */
 | 
						
						
						
						
							 | 
							
								 | 
							
								printk("BAD BAD - no father found\n\r");
 | 
						
						
						
						
							 | 
							
								 | 
							
								release(current);
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							int do_exit(long code)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								int i;
 | 
						
						
						
						
							 | 
							
								 | 
							
								free_page_tables(get_base(current->ldt[1]), get_limit(0x0f));
 | 
						
						
						
						
							 | 
							
								 | 
							
								free_page_tables(get_base(current->ldt[2]), get_limit(0x17));
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (i = 0; i < NR_TASKS; i++)
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (task[i] && task[i]->father == current->pid) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										task[i]->father = 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (task[i]->state == TASK_ZOMBIE)
 | 
						
						
						
						
							 | 
							
								 | 
							
											/* assumption task[1] is always init */
 | 
						
						
						
						
							 | 
							
								 | 
							
											(void)send_sig(SIGCHLD, task[1], 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (i = 0; i < NR_OPEN; i++)
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (current->filp[i])
 | 
						
						
						
						
							 | 
							
								 | 
							
										sys_close(i);
 | 
						
						
						
						
							 | 
							
								 | 
							
								iput(current->pwd);
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->pwd = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								iput(current->root);
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->root = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								iput(current->executable);
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->executable = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (current->leader && current->tty >= 0)
 | 
						
						
						
						
							 | 
							
								 | 
							
									tty_table[current->tty].pgrp = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (last_task_used_math == current)
 | 
						
						
						
						
							 | 
							
								 | 
							
									last_task_used_math = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (current->leader)
 | 
						
						
						
						
							 | 
							
								 | 
							
									kill_session();
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->state = TASK_ZOMBIE;
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->exit_code = code;
 | 
						
						
						
						
							 | 
							
								 | 
							
								tell_father(current->father);
 | 
						
						
						
						
							 | 
							
								 | 
							
								schedule();
 | 
						
						
						
						
							 | 
							
								 | 
							
								return (-1);	/* just to suppress warnings */
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_exit(int error_code)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								return do_exit((error_code & 0xff) << 8);
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_waitpid(pid_t pid, unsigned long* stat_addr, int options)
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								int flag, code;
 | 
						
						
						
						
							 | 
							
								 | 
							
								struct task_struct** p;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
								verify_area(stat_addr, 4);
 | 
						
						
						
						
							 | 
							
								 | 
							
							repeat:
 | 
						
						
						
						
							 | 
							
								 | 
							
								flag = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (p = &LAST_TASK; p > &FIRST_TASK; --p) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (!*p || *p == current)
 | 
						
						
						
						
							 | 
							
								 | 
							
										continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									if ((*p)->father != current->pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
										continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (pid > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										if ((*p)->pid != pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
											continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
									else if (!pid) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										if ((*p)->pgrp != current->pgrp)
 | 
						
						
						
						
							 | 
							
								 | 
							
											continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
									else if (pid != -1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										if ((*p)->pgrp != -pid)
 | 
						
						
						
						
							 | 
							
								 | 
							
											continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
									switch ((*p)->state) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									case TASK_STOPPED:
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (!(options & WUNTRACED))
 | 
						
						
						
						
							 | 
							
								 | 
							
											continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
										put_fs_long(0x7f, stat_addr);
 | 
						
						
						
						
							 | 
							
								 | 
							
										return (*p)->pid;
 | 
						
						
						
						
							 | 
							
								 | 
							
									case TASK_ZOMBIE:
 | 
						
						
						
						
							 | 
							
								 | 
							
										current->cutime += (*p)->utime;
 | 
						
						
						
						
							 | 
							
								 | 
							
										current->cstime += (*p)->stime;
 | 
						
						
						
						
							 | 
							
								 | 
							
										flag = (*p)->pid;
 | 
						
						
						
						
							 | 
							
								 | 
							
										code = (*p)->exit_code;
 | 
						
						
						
						
							 | 
							
								 | 
							
										release(*p);
 | 
						
						
						
						
							 | 
							
								 | 
							
										put_fs_long(code, stat_addr);
 | 
						
						
						
						
							 | 
							
								 | 
							
										return flag;
 | 
						
						
						
						
							 | 
							
								 | 
							
									default:
 | 
						
						
						
						
							 | 
							
								 | 
							
										flag = 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
										continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (flag) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (options & WNOHANG)
 | 
						
						
						
						
							 | 
							
								 | 
							
										return 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
									current->state = TASK_INTERRUPTIBLE;
 | 
						
						
						
						
							 | 
							
								 | 
							
									schedule();
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (!(current->signal &= ~(1 << (SIGCHLD - 1))))
 | 
						
						
						
						
							 | 
							
								 | 
							
										goto repeat;
 | 
						
						
						
						
							 | 
							
								 | 
							
									else
 | 
						
						
						
						
							 | 
							
								 | 
							
										return -EINTR;
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								return -ECHILD;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_thread_exit(void* value_ptr)               /* ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD>thread_exitʵ<74>ֺ<EFBFBD><D6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ο<EFBFBD><CEBF><EFBFBD>do_exit */
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								int i;
 | 
						
						
						
						
							 | 
							
								 | 
							
								pthread_t thread;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
								free_page_tables(get_base(current->ldt[1]), get_limit(0x0f));
 | 
						
						
						
						
							 | 
							
								 | 
							
								free_page_tables(get_base(current->ldt[2]), get_limit(0x17));
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (i = 0; i < NR_TASKS; i++)
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (task[i] && task[i]->father == current->pid) {
 | 
						
						
						
						
							 | 
							
								 | 
							
										task[i]->father = 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
										if (task[i]->state == TASK_ZOMBIE)
 | 
						
						
						
						
							 | 
							
								 | 
							
											/* assumption task[1] is always init */
 | 
						
						
						
						
							 | 
							
								 | 
							
											(void)send_sig(SIGCHLD, task[1], 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (i = 0; i < NR_OPEN; i++)
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (current->filp[i])
 | 
						
						
						
						
							 | 
							
								 | 
							
										sys_close(i);
 | 
						
						
						
						
							 | 
							
								 | 
							
								iput(current->pwd);
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->pwd = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								iput(current->root);
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->root = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								iput(current->executable);
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->executable = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (current->leader && current->tty >= 0)
 | 
						
						
						
						
							 | 
							
								 | 
							
									tty_table[current->tty].pgrp = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (last_task_used_math == current)
 | 
						
						
						
						
							 | 
							
								 | 
							
									last_task_used_math = NULL;
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (current->leader)
 | 
						
						
						
						
							 | 
							
								 | 
							
									kill_session();
 | 
						
						
						
						
							 | 
							
								 | 
							
								current->state = TASK_ZOMBIE;
 | 
						
						
						
						
							 | 
							
								 | 
							
								/*********************************************/
 | 
						
						
						
						
							 | 
							
								 | 
							
								thread = current->pid;                 /* <20><>ǰ<EFBFBD>߳<EFBFBD>ID */
 | 
						
						
						
						
							 | 
							
								 | 
							
								thread_value[thread] = value_ptr;      /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵߳ķ<CCB5><C4B7><EFBFBD>ֵ<EFBFBD><D6B5>¼<EFBFBD><C2BC>thread_value<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
 | 
						
						
						
						
							 | 
							
								 | 
							
								/*********************************************/
 | 
						
						
						
						
							 | 
							
								 | 
							
								tell_father(current->father);
 | 
						
						
						
						
							 | 
							
								 | 
							
								schedule();
 | 
						
						
						
						
							 | 
							
								 | 
							
								return (-1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							int sys_thread_join(pthread_t thread, void** value_ptr)  /* ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD>thread_exitʵ<74>ֺ<EFBFBD><D6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ο<EFBFBD><CEBF><EFBFBD>wait_pid */
 | 
						
						
						
						
							 | 
							
								 | 
							
							{
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (thread <= 0 || value_ptr == NULL)
 | 
						
						
						
						
							 | 
							
								 | 
							
								{
 | 
						
						
						
						
							 | 
							
								 | 
							
									printk("Error:thread joining failed!\n");
 | 
						
						
						
						
							 | 
							
								 | 
							
									sys_exit(0);
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								int flag;
 | 
						
						
						
						
							 | 
							
								 | 
							
								struct task_struct** p;
 | 
						
						
						
						
							 | 
							
								 | 
							
							repeat:
 | 
						
						
						
						
							 | 
							
								 | 
							
								flag = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
								/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĩ<EFBFBD>˿<EFBFBD>ʼɨ<CABC><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA1A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>ǵ<EFBFBD>ǰ<EFBFBD>̵߳<DFB3><CCB5><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD> */
 | 
						
						
						
						
							 | 
							
								 | 
							
								for (p = &LAST_TASK; p > &FIRST_TASK; --p)
 | 
						
						
						
						
							 | 
							
								 | 
							
								{
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (!*p || *p == current) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									if ((*p)->father != current->pid) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									/****************************************/
 | 
						
						
						
						
							 | 
							
								 | 
							
									if ((*p)->pid != thread) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
									/****************************************/
 | 
						
						
						
						
							 | 
							
								 | 
							
									/* <20><>ʱ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>p<EFBFBD><70><EFBFBD>ǵ<EFBFBD>ǰ<EFBFBD>̵߳<DFB3><CCB5><EFBFBD><EFBFBD>߳<EFBFBD> */
 | 
						
						
						
						
							 | 
							
								 | 
							
									switch ((*p)->state)
 | 
						
						
						
						
							 | 
							
								 | 
							
									{
 | 
						
						
						
						
							 | 
							
								 | 
							
									case TASK_STOPPED:
 | 
						
						
						
						
							 | 
							
								 | 
							
										break;
 | 
						
						
						
						
							 | 
							
								 | 
							
									case TASK_ZOMBIE:
 | 
						
						
						
						
							 | 
							
								 | 
							
										current->cutime += (*p)->utime;
 | 
						
						
						
						
							 | 
							
								 | 
							
										current->cstime += (*p)->stime;
 | 
						
						
						
						
							 | 
							
								 | 
							
										release(*p);
 | 
						
						
						
						
							 | 
							
								 | 
							
										/****************************************/
 | 
						
						
						
						
							 | 
							
								 | 
							
										put_fs_long(thread_value[thread], value_ptr); /* <20><>thread_value<75><65><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> value_ptr<74><72>Ҳ<EFBFBD><D2B2><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD>thread_exit<69><74><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>ֵ */
 | 
						
						
						
						
							 | 
							
								 | 
							
										/****************************************/    /* <20><>˸<EFBFBD><CBB8>̵߳<DFB3><CCB5><EFBFBD>sys_thread_join<69><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ֵ */
 | 
						
						
						
						
							 | 
							
								 | 
							
										return 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
									default:
 | 
						
						
						
						
							 | 
							
								 | 
							
										flag = 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
										break;
 | 
						
						
						
						
							 | 
							
								 | 
							
									}
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								/* flag=1˵<31><CBB5><EFBFBD>з<EFBFBD><D0B7>ϵȴ<CFB5>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<DFB3><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ʱ<EFBFBD>ѵ<EFBFBD>ǰ<EFBFBD>߳<EFBFBD><DFB3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>жϵȴ<CFB5>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5>ȣ<EFBFBD><C8A3>ظ<EFBFBD>ִ<EFBFBD><D6B4> */
 | 
						
						
						
						
							 | 
							
								 | 
							
								if (flag) {
 | 
						
						
						
						
							 | 
							
								 | 
							
									current->state = TASK_INTERRUPTIBLE;
 | 
						
						
						
						
							 | 
							
								 | 
							
									schedule();
 | 
						
						
						
						
							 | 
							
								 | 
							
									if (!(current->signal &= ~(1 << (SIGCHLD - 1))))
 | 
						
						
						
						
							 | 
							
								 | 
							
										goto repeat;
 | 
						
						
						
						
							 | 
							
								 | 
							
									else
 | 
						
						
						
						
							 | 
							
								 | 
							
										return -EINTR;
 | 
						
						
						
						
							 | 
							
								 | 
							
								}
 | 
						
						
						
						
							 | 
							
								 | 
							
								return -ECHILD;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 |