Linux-0.01 (September 17, 1991)
[davej-history.git] / kernel / exit.c
blob3402c3312076b61df3c9b9efb492bf7a9c77d789
1 #include <errno.h>
2 #include <signal.h>
3 #include <sys/wait.h>
5 #include <linux/sched.h>
6 #include <linux/kernel.h>
7 #include <linux/tty.h>
8 #include <asm/segment.h>
10 int sys_pause(void);
11 int sys_close(int fd);
13 void release(struct task_struct * p)
15 int i;
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;
26 panic("trying to release non-existent task");
29 static inline void send_sig(long sig,struct task_struct * p,int priv)
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));
41 void do_kill(long pid,long sig,int priv)
43 struct task_struct **p = NR_TASKS + task;
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);
58 int sys_kill(int pid,int sig)
60 do_kill(pid,sig,!(current->uid || current->euid));
61 return 0;
64 int do_exit(long code)
66 int i;
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 */
94 int sys_exit(int error_code)
96 return do_exit((error_code&0xff)<<8);
99 int sys_waitpid(pid_t pid,int * stat_addr, int options)
101 int flag=0;
102 struct task_struct ** p;
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;
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;
132 return -ECHILD;