summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2001-04-02 21:43:13 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2001-04-02 21:43:13 +0000
commitaf30415b0b2928465e43e6cf1262e7275d8dd1c5 (patch)
treec0943d31f2c4f5f6770363b2596da79e506bfc31 /sys/kern
parent92d3551f6f3379d9e9e7a6e3652ca50686373a1d (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.c12
-rw-r--r--sys/kern/kern_exit.c27
-rw-r--r--sys/kern/kern_fork.c24
-rw-r--r--sys/kern/kern_kthread.c10
-rw-r--r--sys/kern/kern_sig.c81
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)