diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-04-02 21:43:13 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-04-02 21:43:13 +0000 |
commit | af30415b0b2928465e43e6cf1262e7275d8dd1c5 (patch) | |
tree | c0943d31f2c4f5f6770363b2596da79e506bfc31 /sys/kern | |
parent | 92d3551f6f3379d9e9e7a6e3652ca50686373a1d (diff) |
On popular demand, the Linux-compatibility clone(2) implementation based
on NetBSD's code, as well as some faked Posix RT extensions by me. This makes
at least simple linuxthreads tests work.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_main.c | 12 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 27 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 24 | ||||
-rw-r--r-- | sys/kern/kern_kthread.c | 10 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 81 |
5 files changed, 134 insertions, 20 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 11ed4f6511e..7b53d5d6a43 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.60 2001/03/16 15:49:05 art Exp $ */ +/* $OpenBSD: init_main.c,v 1.61 2001/04/02 21:43:11 niklas Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -118,6 +118,7 @@ struct pcred cred0; struct filedesc0 filedesc0; struct plimit limit0; struct vmspace vmspace0; +struct sigacts sigacts0; #ifndef curproc struct proc *curproc; #endif @@ -305,11 +306,10 @@ main(framep) p->p_addr = proc0paddr; /* XXX */ /* - * We continue to place resource usage info and signal - * actions in the user struct so they're pageable. + * We continue to place resource usage info in the + * user struct so they're pageable. */ p->p_stats = &p->p_addr->u_stats; - p->p_sigacts = &p->p_addr->u_sigacts; /* * Charge root for one process. @@ -416,10 +416,12 @@ main(framep) p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; /* Initialize signal state for process 0. */ + signal_init(); + p->p_sigacts = &sigacts0; siginit(p); /* Create process 1 (init(8)). */ - if (fork1(p, FORK_FORK, NULL, 0, rval)) + if (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, rval)) panic("fork init"); #ifdef cpu_set_init_frame /* XXX should go away */ if (rval[1]) { diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 575394f72ae..bbe76ff7bc7 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.29 2001/03/23 18:42:06 art Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.30 2001/04/02 21:43:11 niklas Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -286,6 +286,10 @@ exit1(p, rv) wakeup((caddr_t)pp); } + if ((p->p_flag & P_FSTRACE) == 0 && p->p_exitsig != 0) + psignal(p->p_pptr, P_EXITSIG(p)); + wakeup((caddr_t)p->p_pptr); + /* * Notify procfs debugger */ @@ -293,6 +297,11 @@ exit1(p, rv) wakeup((caddr_t)p); /* + * Release the process's signal state. + */ + sigactsfree(p); + + /* * Clear curproc after we've done all operations * that could block, and before tearing down the rest * of the process state that might be used from clock, etc. @@ -433,6 +442,16 @@ loop: p->p_pid != SCARG(uap, pid) && p->p_pgid != -SCARG(uap, pid))) continue; + + /* + * Wait for processes with p_exitsig != SIGCHLD processes only + * if WALTSIG is set; wait for processes with pexitsig == + * SIGCHLD only if WALTSIG is clear. + */ + if ((SCARG(uap, options) & WALTSIG) ? + (p->p_exitsig == SIGCHLD) : (P_EXITSIG(p) != SIGCHLD)) + continue; + nfound++; if (p->p_stat == SZOMB) { retval[0] = p->p_pid; @@ -458,7 +477,8 @@ loop: if (p->p_oppid && (t = pfind(p->p_oppid))) { p->p_oppid = 0; proc_reparent(p, t); - psignal(t, SIGCHLD); + if (p->p_exitsig != 0) + psignal(t, P_EXITSIG(p)); wakeup((caddr_t)t); return (0); } @@ -509,6 +529,9 @@ proc_reparent(child, parent) if (child->p_pptr == parent) return; + if (parent == initproc) + child->p_exitsig = SIGCHLD; + LIST_REMOVE(child, p_sibling); LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); child->p_pptr = parent; diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 3179f7b07ae..094903ef13e 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.38 2001/03/23 18:42:06 art Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.39 2001/04/02 21:43:11 niklas Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -50,6 +50,7 @@ #include <sys/mount.h> #include <sys/proc.h> #include <sys/resourcevar.h> +#include <sys/signalvar.h> #include <sys/vnode.h> #include <sys/file.h> #include <sys/acct.h> @@ -81,7 +82,7 @@ sys_fork(p, v, retval) void *v; register_t *retval; { - return (fork1(p, FORK_FORK, NULL, 0, retval)); + return (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, retval)); } /*ARGSUSED*/ @@ -91,7 +92,7 @@ sys_vfork(p, v, retval) void *v; register_t *retval; { - return (fork1(p, FORK_VFORK|FORK_PPWAIT, NULL, 0, retval)); + return (fork1(p, SIGCHLD, FORK_VFORK|FORK_PPWAIT, NULL, 0, retval)); } int @@ -103,6 +104,7 @@ sys_rfork(p, v, retval) struct sys_rfork_args /* { syscallarg(int) flags; } */ *uap = v; + int rforkflags; int flags; @@ -131,12 +133,13 @@ sys_rfork(p, v, retval) if (rforkflags & RFMEM) flags |= FORK_VMNOSTACK; - return (fork1(p, flags, NULL, 0, retval)); + return (fork1(p, SIGCHLD, flags, NULL, 0, retval)); } int -fork1(p1, flags, stack, stacksize, retval) +fork1(p1, exitsig, flags, stack, stacksize, retval) register struct proc *p1; + int exitsig; int flags; void *stack; size_t stacksize; @@ -246,6 +249,7 @@ again: p2 = newproc; p2->p_stat = SIDL; /* protect against others */ p2->p_pid = lastpid; + p2->p_exitsig = exitsig; LIST_INSERT_HEAD(&allproc, p2, p_list); p2->p_forw = p2->p_back = NULL; /* shouldn't be necessary */ LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); @@ -338,6 +342,14 @@ again: scheduler_fork_hook(p1, p2); /* + * Create signal actions for the child process. + */ + if (flags & FORK_SIGHAND) + sigactsshare(p1, p2); + else + p2->p_sigacts = sigactsinit(p1); + + /* * This begins the section where we must prevent the parent * from being swapped. */ @@ -382,7 +394,7 @@ again: */ #if defined(UVM) uvm_fork(p1, p2, ((flags & FORK_SHAREVM) ? TRUE : FALSE), stack, - stacksize); + stacksize); #else /* UVM */ vm_fork(p1, p2, stack, stacksize); #endif /* UVM */ diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index 9652514957b..c81d2f7386e 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_kthread.c,v 1.10 2000/07/17 16:25:16 deraadt Exp $ */ +/* $OpenBSD: kern_kthread.c,v 1.11 2001/04/02 21:43:12 niklas Exp $ */ /* $NetBSD: kern_kthread.c,v 1.3 1998/12/22 21:21:36 kleink Exp $ */ /*- @@ -79,14 +79,16 @@ kthread_create(func, arg, newpp, fmt, va_alist) va_list ap; /* - * First, create the new process. Share the memory, copy file + * First, create the new process. Share the memory, file * descriptors and don't leave the exit status around for the * parent to wait for. */ #ifdef UVM - error = fork1(&proc0, FORK_SHAREVM|FORK_NOZOMBIE, NULL, 0, rv); + error = fork1(&proc0, 0, + FORK_SHAREVM|FORK_NOZOMBIE|FORK_SIGHAND, NULL, 0, rv); #else - error = fork1(&proc0, FORK_VMNOSTACK|FORK_NOZOMBIE, NULL, 0, rv); + error = fork1(&proc0, 0, + FORK_VMNOSTACK|FORK_NOZOMBIE|FORK_SIGHAND, NULL, 0, rv); #endif if (error) return (error); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 8dd275ecdb7..fb6239eedb6 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.41 2001/02/19 10:21:48 art Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.42 2001/04/02 21:43:12 niklas Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -63,6 +63,8 @@ #include <sys/syslog.h> #include <sys/stat.h> #include <sys/core.h> +#include <sys/malloc.h> +#include <sys/pool.h> #include <sys/ptrace.h> #include <sys/mount.h> @@ -73,9 +75,7 @@ #include <vm/vm.h> #include <sys/user.h> /* for coredump */ -#if defined(UVM) #include <uvm/uvm_extern.h> -#endif int filt_sigattach(struct knote *kn); void filt_sigdetach(struct knote *kn); @@ -88,6 +88,8 @@ void stop __P((struct proc *p)); void killproc __P((struct proc *, char *)); int cansignal __P((struct proc *, struct pcred *, struct proc *, int)); +struct pool sigacts_pool; /* memory pool for sigacts structures */ + /* * Can process p, with pcred pc, send the signal signum to process q? */ @@ -145,6 +147,79 @@ cansignal(p, pc, q, signum) } +/* + * Initialize signal-related data structures. + */ +void +signal_init() +{ + pool_init(&sigacts_pool, sizeof(struct sigacts), 0, 0, 0, "sigapl", + 0, pool_page_alloc_nointr, pool_page_free_nointr, M_SUBPROC); +} + +/* + * Create an initial sigacts structure, using the same signal state + * as p. + */ +struct sigacts * +sigactsinit(p) + struct proc *p; +{ + struct sigacts *ps; + + ps = pool_get(&sigacts_pool, PR_WAITOK); + memcpy(ps, p->p_sigacts, sizeof(struct sigacts)); + ps->ps_refcnt = 1; + return (ps); +} + +/* + * Make p2 share p1's sigacts. + */ +void +sigactsshare(p1, p2) + struct proc *p1, *p2; +{ + + p2->p_sigacts = p1->p_sigacts; + p1->p_sigacts->ps_refcnt++; +} + +/* + * Make this process not share its sigacts, maintaining all + * signal state. + */ +void +sigactsunshare(p) + struct proc *p; +{ + struct sigacts *newps; + + if (p->p_sigacts->ps_refcnt == 1) + return; + + newps = sigactsinit(p); + sigactsfree(p); + p->p_sigacts = newps; +} + +/* + * Release a sigacts structure. + */ +void +sigactsfree(p) + struct proc *p; +{ + struct sigacts *ps = p->p_sigacts; + + if (--ps->ps_refcnt > 0) + return; + + p->p_sigacts = NULL; + + pool_put(&sigacts_pool, ps); +} + /* ARGSUSED */ int sys_sigaction(p, v, retval) |