Annotation of linux/kernel/exit.c, revision 1.1.1.1
1.1 root 1: #include <errno.h>
2: #include <signal.h>
3: #include <sys/wait.h>
4:
5: #include <linux/sched.h>
6: #include <linux/kernel.h>
7: #include <linux/tty.h>
8: #include <asm/segment.h>
9:
10: int sys_pause(void);
11: int sys_close(int fd);
12:
13: void release(struct task_struct * p)
14: {
15: int i;
16:
17: if (!p)
18: return;
19: for (i=1 ; i<NR_TASKS ; i++)
20: if (task[i]==p) {
21: task[i]=NULL;
22: free_page((long)p);
23: schedule();
24: return;
25: }
26: panic("trying to release non-existent task");
27: }
28:
29: static inline void send_sig(long sig,struct task_struct * p,int priv)
30: {
31: if (!p || sig<1 || sig>32)
32: return;
33: if (priv ||
34: current->uid==p->uid ||
35: current->euid==p->uid ||
36: current->uid==p->euid ||
37: current->euid==p->euid)
38: p->signal |= (1<<(sig-1));
39: }
40:
41: void do_kill(long pid,long sig,int priv)
42: {
43: struct task_struct **p = NR_TASKS + task;
44:
45: if (!pid) while (--p > &FIRST_TASK) {
46: if (*p && (*p)->pgrp == current->pid)
47: send_sig(sig,*p,priv);
48: } else if (pid>0) while (--p > &FIRST_TASK) {
49: if (*p && (*p)->pid == pid)
50: send_sig(sig,*p,priv);
51: } else if (pid == -1) while (--p > &FIRST_TASK)
52: send_sig(sig,*p,priv);
53: else while (--p > &FIRST_TASK)
54: if (*p && (*p)->pgrp == -pid)
55: send_sig(sig,*p,priv);
56: }
57:
58: int sys_kill(int pid,int sig)
59: {
60: do_kill(pid,sig,!(current->uid || current->euid));
61: return 0;
62: }
63:
64: int do_exit(long code)
65: {
66: int i;
67:
68: free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
69: free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
70: for (i=0 ; i<NR_TASKS ; i++)
71: if (task[i] && task[i]->father == current->pid)
72: task[i]->father = 0;
73: for (i=0 ; i<NR_OPEN ; i++)
74: if (current->filp[i])
75: sys_close(i);
76: iput(current->pwd);
77: current->pwd=NULL;
78: iput(current->root);
79: current->root=NULL;
80: if (current->leader && current->tty >= 0)
81: tty_table[current->tty].pgrp = 0;
82: if (last_task_used_math == current)
83: last_task_used_math = NULL;
84: if (current->father) {
85: current->state = TASK_ZOMBIE;
86: do_kill(current->father,SIGCHLD,1);
87: current->exit_code = code;
88: } else
89: release(current);
90: schedule();
91: return (-1); /* just to suppress warnings */
92: }
93:
94: int sys_exit(int error_code)
95: {
96: return do_exit((error_code&0xff)<<8);
97: }
98:
99: int sys_waitpid(pid_t pid,int * stat_addr, int options)
100: {
101: int flag=0;
102: struct task_struct ** p;
103:
104: verify_area(stat_addr,4);
105: repeat:
106: for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
107: if (*p && *p != current &&
108: (pid==-1 || (*p)->pid==pid ||
109: (pid==0 && (*p)->pgrp==current->pgrp) ||
110: (pid<0 && (*p)->pgrp==-pid)))
111: if ((*p)->father == current->pid) {
112: flag=1;
113: if ((*p)->state==TASK_ZOMBIE) {
114: put_fs_long((*p)->exit_code,
115: (unsigned long *) stat_addr);
116: current->cutime += (*p)->utime;
117: current->cstime += (*p)->stime;
118: flag = (*p)->pid;
119: release(*p);
120: return flag;
121: }
122: }
123: if (flag) {
124: if (options & WNOHANG)
125: return 0;
126: sys_pause();
127: if (!(current->signal &= ~(1<<(SIGCHLD-1))))
128: goto repeat;
129: else
130: return -EINTR;
131: }
132: return -ECHILD;
133: }
134:
135:
unix.superglobalmegacorp.com