patch-2.1.36 linux/kernel/exit.c
Next file: linux/kernel/fork.c
Previous file: linux/init/main.c
Back to the patch index
Back to the overall index
- Lines: 457
- Date:
Tue Apr 22 22:53:52 1997
- Orig file:
v2.1.35/linux/kernel/exit.c
- Orig date:
Sun Apr 13 10:18:22 1997
diff -u --recursive --new-file v2.1.35/linux/kernel/exit.c linux/kernel/exit.c
@@ -41,18 +41,23 @@
* be handled immediately (ie non-blocked and untraced)
* and that is ignored (either explicitly or by default)
*/
+ spin_lock_irq(&p->sig->siglock);
if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
/* don't bother with ignored signals (but SIGCHLD is special) */
if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
- return;
+ goto out;
/* some signals are ignored by default.. (but SIGCONT already did its deed) */
if ((sa->sa_handler == SIG_DFL) &&
(sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
- return;
+ goto out;
}
+ spin_lock(&p->sigmask_lock);
p->signal |= mask;
+ spin_unlock(&p->sigmask_lock);
if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
wake_up_process(p);
+out:
+ spin_unlock_irq(&p->sig->siglock);
}
/*
@@ -65,16 +70,23 @@
if (p->sig) {
unsigned long mask = 1UL << sig;
struct sigaction *sa = p->sig->action + sig;
+
+ spin_lock_irq(&p->sig->siglock);
+
+ spin_lock(&p->sigmask_lock);
p->signal |= mask;
p->blocked &= ~mask;
+ spin_unlock(&p->sigmask_lock);
+
if (sa->sa_handler == SIG_IGN)
sa->sa_handler = SIG_DFL;
if (p->state == TASK_INTERRUPTIBLE)
wake_up_process(p);
+
+ spin_unlock_irq(&p->sig->siglock);
}
}
-
int send_sig(unsigned long sig,struct task_struct * p,int priv)
{
if (!p || sig > 32)
@@ -84,24 +96,23 @@
(current->uid ^ p->suid) && (current->uid ^ p->uid) &&
!suser())
return -EPERM;
- if (!sig)
- return 0;
- /*
- * Forget it if the process is already zombie'd.
- */
- if (!p->sig)
- return 0;
- if ((sig == SIGKILL) || (sig == SIGCONT)) {
- if (p->state == TASK_STOPPED)
- wake_up_process(p);
- p->exit_code = 0;
- p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
- (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
- }
- if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
- p->signal &= ~(1<<(SIGCONT-1));
- /* Actually generate the signal */
- generate(sig,p);
+
+ if (sig && p->sig) {
+ spin_lock_irq(&p->sigmask_lock);
+ if ((sig == SIGKILL) || (sig == SIGCONT)) {
+ if (p->state == TASK_STOPPED)
+ wake_up_process(p);
+ p->exit_code = 0;
+ p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
+ (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
+ }
+ if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+ p->signal &= ~(1<<(SIGCONT-1));
+ spin_unlock_irq(&p->sigmask_lock);
+
+ /* Actually generate the signal */
+ generate(sig,p);
+ }
return 0;
}
@@ -125,6 +136,12 @@
}
for (i=1 ; i<NR_TASKS ; i++)
if (task[i] == p) {
+#ifdef __SMP__
+ /* FIXME! Cheesy, but kills the window... -DaveM */
+ while(p->processor != NO_PROC_ID)
+ barrier();
+ spin_unlock_wait(&scheduler_lock);
+#endif
nr_tasks--;
task[i] = NULL;
REMOVE_LINKS(p);
@@ -245,14 +262,18 @@
int fallback;
fallback = -1;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->session <= 0)
continue;
- if (p->pgrp == pgrp)
- return p->session;
+ if (p->pgrp == pgrp) {
+ fallback = p->session;
+ break;
+ }
if (p->pid == pgrp)
fallback = p->session;
}
+ read_unlock(&tasklist_lock);
return fallback;
}
@@ -262,21 +283,29 @@
*/
int kill_pg(int pgrp, int sig, int priv)
{
- struct task_struct *p;
- int err,retval = -ESRCH;
- int found = 0;
+ int retval;
- if (sig<0 || sig>32 || pgrp<=0)
- return -EINVAL;
- for_each_task(p) {
- if (p->pgrp == pgrp) {
- if ((err = send_sig(sig,p,priv)) != 0)
- retval = err;
- else
- found++;
+ retval = -EINVAL;
+ if (sig >= 0 && sig <= 32 && pgrp > 0) {
+ struct task_struct *p;
+ int found = 0;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pgrp == pgrp) {
+ int err = send_sig(sig,p,priv);
+ if (err != 0)
+ retval = err;
+ else
+ found++;
+ }
}
+ read_unlock(&tasklist_lock);
+ if (found)
+ retval = 0;
}
- return(found ? 0 : retval);
+ return retval;
}
/*
@@ -286,34 +315,51 @@
*/
int kill_sl(int sess, int sig, int priv)
{
- struct task_struct *p;
- int err,retval = -ESRCH;
- int found = 0;
+ int retval;
- if (sig<0 || sig>32 || sess<=0)
- return -EINVAL;
- for_each_task(p) {
- if (p->session == sess && p->leader) {
- if ((err = send_sig(sig,p,priv)) != 0)
- retval = err;
- else
- found++;
+ retval = -EINVAL;
+ if (sig >= 0 && sig <= 32 && sess > 0) {
+ struct task_struct *p;
+ int found = 0;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->leader && p->session == sess) {
+ int err = send_sig(sig,p,priv);
+
+ if (err)
+ retval = err;
+ else
+ found++;
+ }
}
+ read_unlock(&tasklist_lock);
+ if (found)
+ retval = 0;
}
- return(found ? 0 : retval);
+ return retval;
}
int kill_proc(int pid, int sig, int priv)
{
- struct task_struct *p;
+ int retval;
- if (sig<0 || sig>32)
- return -EINVAL;
- for_each_task(p) {
- if (p && p->pid == pid)
- return send_sig(sig,p,priv);
+ retval = -EINVAL;
+ if (sig >= 0 && sig <= 32) {
+ struct task_struct *p;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pid != pid)
+ continue;
+ retval = send_sig(sig,p,priv);
+ break;
+ }
+ read_unlock(&tasklist_lock);
}
- return(-ESRCH);
+ return retval;
}
/*
@@ -322,34 +368,30 @@
*/
asmlinkage int sys_kill(int pid,int sig)
{
- int err, retval = 0, count = 0;
+ if (!pid)
+ return kill_pg(current->pgrp,sig,0);
- lock_kernel();
- if (!pid) {
- err = kill_pg(current->pgrp,sig,0);
- goto out;
- }
if (pid == -1) {
+ int retval = 0, count = 0;
struct task_struct * p;
+
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pid > 1 && p != current) {
+ int err;
++count;
if ((err = send_sig(sig,p,0)) != -EPERM)
retval = err;
}
}
- err = count ? retval : -ESRCH;
- goto out;
- }
- if (pid < 0) {
- err = kill_pg(-pid,sig,0);
- goto out;
+ read_unlock(&tasklist_lock);
+ return count ? retval : -ESRCH;
}
+ if (pid < 0)
+ return kill_pg(-pid,sig,0);
+
/* Normal kill */
- err = kill_proc(pid,sig,0);
-out:
- unlock_kernel();
- return err;
+ return kill_proc(pid,sig,0);
}
/*
@@ -364,16 +406,20 @@
{
struct task_struct *p;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if ((p == ignored_task) || (p->pgrp != pgrp) ||
(p->state == TASK_ZOMBIE) ||
(p->p_pptr->pid == 1))
continue;
if ((p->p_pptr->pgrp != pgrp) &&
- (p->p_pptr->session == p->session))
- return 0;
+ (p->p_pptr->session == p->session)) {
+ read_unlock(&tasklist_lock);
+ return 0;
+ }
}
- return(1); /* (sighing) "Often!" */
+ read_unlock(&tasklist_lock);
+ return 1; /* (sighing) "Often!" */
}
int is_orphaned_pgrp(int pgrp)
@@ -383,21 +429,27 @@
static inline int has_stopped_jobs(int pgrp)
{
+ int retval = 0;
struct task_struct * p;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pgrp != pgrp)
continue;
- if (p->state == TASK_STOPPED)
- return(1);
+ if (p->state != TASK_STOPPED)
+ continue;
+ retval = 1;
+ break;
}
- return(0);
+ read_unlock(&tasklist_lock);
+ return retval;
}
static inline void forget_original_parent(struct task_struct * father)
{
struct task_struct * p;
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->p_opptr == father)
if (task[smp_num_cpus]) /* init */
@@ -405,6 +457,7 @@
else
p->p_opptr = task[0];
}
+ read_unlock(&tasklist_lock);
}
static inline void close_files(struct files_struct * files)
@@ -470,9 +523,8 @@
if (sig) {
tsk->sig = NULL;
- if (!--sig->count) {
+ if (atomic_dec_and_test(&sig->count))
kfree(sig);
- }
}
}
@@ -635,24 +687,22 @@
struct wait_queue wait = { current, NULL };
struct task_struct *p;
- lock_kernel();
if (stat_addr) {
- retval = verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr));
- if (retval)
- goto out;
+ if(verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr)))
+ return -EFAULT;
}
if (ru) {
- retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
- if (retval)
- goto out;
+ if(verify_area(VERIFY_WRITE, ru, sizeof(*ru)))
+ return -EFAULT;
}
- retval = -EINVAL;
+
if (options & ~(WNOHANG|WUNTRACED|__WCLONE))
- goto out;
+ return -EINVAL;
add_wait_queue(¤t->wait_chldexit,&wait);
repeat:
- flag=0;
+ flag = 0;
+ read_lock(&tasklist_lock);
for (p = current->p_cptr ; p ; p = p->p_osptr) {
if (pid>0) {
if (p->pid != pid)
@@ -674,23 +724,28 @@
continue;
if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
continue;
+ read_unlock(&tasklist_lock);
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
if (stat_addr)
- put_user((p->exit_code << 8) | 0x7f,
- stat_addr);
+ __put_user((p->exit_code << 8) | 0x7f,
+ stat_addr);
p->exit_code = 0;
retval = p->pid;
goto end_wait4;
case TASK_ZOMBIE:
current->cutime += p->utime + p->cutime;
current->cstime += p->stime + p->cstime;
+ read_unlock(&tasklist_lock);
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
if (stat_addr)
- put_user(p->exit_code, stat_addr);
+ __put_user(p->exit_code, stat_addr);
retval = p->pid;
if (p->p_opptr != p->p_pptr) {
+ /* Note this grabs tasklist_lock
+ * as a writer... (twice!)
+ */
REMOVE_LINKS(p);
p->p_pptr = p->p_opptr;
SET_LINKS(p);
@@ -705,6 +760,7 @@
continue;
}
}
+ read_unlock(&tasklist_lock);
if (flag) {
retval = 0;
if (options & WNOHANG)
@@ -719,8 +775,6 @@
retval = -ECHILD;
end_wait4:
remove_wait_queue(¤t->wait_chldexit,&wait);
-out:
- unlock_kernel();
return retval;
}
@@ -732,12 +786,7 @@
*/
asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options)
{
- int ret;
-
- lock_kernel();
- ret = sys_wait4(pid, stat_addr, options, NULL);
- unlock_kernel();
- return ret;
+ return sys_wait4(pid, stat_addr, options, NULL);
}
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov