aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Elischer <julian@FreeBSD.org>1998-12-19 02:55:34 +0000
committerJulian Elischer <julian@FreeBSD.org>1998-12-19 02:55:34 +0000
commit6626c6045c38a22c2dc57621a840ae612da0e2e3 (patch)
treeb5baf90edc2cac8af964657b46d2d820dce40d35
parent02489dd7373f6eb94fc23050f36acaaa2b71167e (diff)
downloadsrc-6626c6045c38a22c2dc57621a840ae612da0e2e3.tar.gz
src-6626c6045c38a22c2dc57621a840ae612da0e2e3.zip
Reviewed by: Luoqi Chen, Jordan Hubbard
Submitted by: "Richard Seaman, Jr." <lists@tar.com> Obtained from: linux :-) Code to allow Linux Threads to run under FreeBSD. By default not enabled This code is dependent on the conditional COMPAT_LINUX_THREADS (suggested by Garret) This is not yet a 'real' option but will be within some number of hours.
Notes
Notes: svn path=/head/; revision=41931
-rw-r--r--bin/ps/keyword.c4
-rw-r--r--lib/libc/i386/sys/sigsuspend.S8
-rw-r--r--sys/alpha/linux/linux.h3
-rw-r--r--sys/alpha/linux/linux_dummy.c9
-rw-r--r--sys/alpha/linux/linux_sysvec.c23
-rw-r--r--sys/alpha/linux/syscalls.master4
-rw-r--r--sys/compat/linux/linux_misc.c174
-rw-r--r--sys/i386/linux/linux.h3
-rw-r--r--sys/i386/linux/linux_dummy.c9
-rw-r--r--sys/i386/linux/linux_misc.c174
-rw-r--r--sys/i386/linux/linux_proto.h5
-rw-r--r--sys/i386/linux/linux_syscall.h2
-rw-r--r--sys/i386/linux/linux_sysent.c4
-rw-r--r--sys/i386/linux/linux_sysvec.c23
-rw-r--r--sys/i386/linux/syscalls.master4
-rw-r--r--sys/kern/imgact_elf.c6
-rw-r--r--sys/kern/init_main.c20
-rw-r--r--sys/kern/kern_exit.c40
-rw-r--r--sys/kern/kern_fork.c24
-rw-r--r--sys/kern/kern_sig.c76
-rw-r--r--sys/sys/proc.h41
-rw-r--r--sys/sys/signalvar.h6
-rw-r--r--sys/sys/unistd.h5
-rw-r--r--sys/sys/user.h9
-rw-r--r--sys/vm/vm_glue.c9
25 files changed, 639 insertions, 46 deletions
diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c
index a0c60b11b9f1..023c55df3ff6 100644
--- a/bin/ps/keyword.c
+++ b/bin/ps/keyword.c
@@ -36,7 +36,7 @@
static char sccsid[] = "@(#)keyword.c 8.5 (Berkeley) 4/2/94";
#else
static const char rcsid[] =
- "$Id: keyword.c,v 1.19 1998/05/25 05:07:17 steve Exp $";
+ "$Id: keyword.c,v 1.20 1998/09/14 08:32:20 dfr Exp $";
#endif
#endif /* not lint */
@@ -157,10 +157,12 @@ VAR var[] = {
{"ruser", "RUSER", NULL, LJUST|DSIZ, runame, s_runame, USERLEN},
{"sess", "SESS", NULL, 0, evar, NULL, 6, EOFF(e_sess), KPTR, "lx"},
{"sig", "PENDING", NULL, 0, pvar, NULL, 8, POFF(p_siglist), INT, "x"},
+#ifndef COMPAT_LINUX_THREADS
{"sigcatch", "CAUGHT",
NULL, 0, pvar, NULL, 8, POFF(p_sigcatch), UINT, "x"},
{"sigignore", "IGNORED",
NULL, 0, pvar, NULL, 8, POFF(p_sigignore), UINT, "x"},
+#endif /* COMPAT_LINUX_THREADS */
{"sigmask", "BLOCKED",
NULL, 0, pvar, NULL, 8, POFF(p_sigmask), UINT, "x"},
{"sl", "SL", NULL, 0, pvar, NULL, 3, POFF(p_slptime), UINT, "d"},
diff --git a/lib/libc/i386/sys/sigsuspend.S b/lib/libc/i386/sys/sigsuspend.S
index 660eabf85411..f85b2e1929f1 100644
--- a/lib/libc/i386/sys/sigsuspend.S
+++ b/lib/libc/i386/sys/sigsuspend.S
@@ -33,12 +33,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sigsuspend.S,v 1.6 1997/02/22 14:59:40 peter Exp $
*/
#if defined(SYSLIBC_RCS) && !defined(lint)
.text
- .asciz "$Id$"
+ .asciz "$Id: sigsuspend.S,v 1.6 1997/02/22 14:59:40 peter Exp $"
#endif /* SYSLIBC_RCS and not lint */
#include "SYS.h"
@@ -50,7 +50,9 @@ err:
#ifdef _THREAD_SAFE
ENTRY(_thread_sys_sigsuspend)
#else
-ENTRY(sigsuspend)
+ENTRY(_sigsuspend)
+ .weak CNAME(sigsuspend) ;
+ .set CNAME(sigsuspend), CNAME(_sigsuspend) ;
#endif
movl 4(%esp),%eax # fetch mask arg
movl (%eax),%eax # indirect to mask arg
diff --git a/sys/alpha/linux/linux.h b/sys/alpha/linux/linux.h
index 691ed550f336..820028fb5d06 100644
--- a/sys/alpha/linux/linux.h
+++ b/sys/alpha/linux/linux.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux.h,v 1.23 1998/10/05 16:37:36 jfieber Exp $
+ * $Id: linux.h,v 1.24 1998/11/12 00:42:08 jkh Exp $
*/
#ifndef _I386_LINUX_LINUX_H_
@@ -418,6 +418,7 @@ struct trapframe;
#define LINUX_MAP_PRIVATE 0x0002
#define LINUX_MAP_FIXED 0x0010
#define LINUX_MAP_ANON 0x0020
+#define LINUX_MAP_GROWSDOWN 0x0100
/* SystemV ipc defines */
#define LINUX_SEMOP 1
diff --git a/sys/alpha/linux/linux_dummy.c b/sys/alpha/linux/linux_dummy.c
index 30a0dba49449..6a7ce1e82802 100644
--- a/sys/alpha/linux/linux_dummy.c
+++ b/sys/alpha/linux/linux_dummy.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_dummy.c,v 1.7 1997/10/29 08:17:09 kato Exp $
+ * $Id: linux_dummy.c,v 1.8 1997/11/06 19:28:52 phk Exp $
*/
#include <sys/param.h>
@@ -212,13 +212,6 @@ linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args)
}
int
-linux_clone(struct proc *p, struct linux_clone_args *args)
-{
- printf("Linux-emul(%d): clone() not supported\n", p->p_pid);
- return ENOSYS;
-}
-
-int
linux_uname(struct proc *p, struct linux_uname_args *args)
{
printf("Linux-emul(%d): uname() not supported\n", p->p_pid);
diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c
index 188e3d5a5b69..b8639516ef86 100644
--- a/sys/alpha/linux/linux_sysvec.c
+++ b/sys/alpha/linux/linux_sysvec.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_sysvec.c,v 1.39 1998/12/14 18:54:01 dt Exp $
+ * $Id: linux_sysvec.c,v 1.40 1998/12/16 16:28:57 bde Exp $
*/
/* XXX we use functions that might not exist. */
@@ -50,6 +50,10 @@
#include <vm/vm_prot.h>
#include <vm/vm_page.h>
#include <vm/vm_extern.h>
+#ifdef COMPAT_LINUX_THREADS
+#include <sys/lock.h> /* needed, for now, by vm_map.h */
+#include <vm/vm_map.h> /* needed, for now, for VM_STACK defines */
+#endif /* COMPAT_LINUX_THREADS */
#include <sys/exec.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -217,7 +221,24 @@ linux_sendsig(sig_t catcher, int sig, int mask, u_long code)
* and the stack can not be grown. useracc will return FALSE
* if access is denied.
*/
+#ifdef COMPAT_LINUX_THREADS
+#ifdef USE_VM_STACK
+#ifndef USE_VM_STACK_FOR_EXEC
+ if ((((caddr_t)fp > p->p_vmspace->vm_maxsaddr &&
+ (caddr_t)fp < (caddr_t)USRSTACK &&
+ grow(p, (int)fp) == FALSE) ||
+ (((caddr_t)fp <= p->p_vmspace->vm_maxsaddr ||
+ (caddr_t)fp >= (caddr_t)USRSTACK) &&
+ grow_stack (p, (int)fp) == FALSE)) ||
+#else
+ if ((grow_stack (p, (int)fp) == FALSE) ||
+#endif
+#else
+#endif /* COMPAT_LINUX_THREADS */
if ((grow(p, (int)fp) == FALSE) ||
+#ifdef COMPAT_LINUX_THREADS
+#endif
+#endif /* COMPAT_LINUX_THREADS */
(useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) {
/*
* Process has trashed its stack; give it an illegal
diff --git a/sys/alpha/linux/syscalls.master b/sys/alpha/linux/syscalls.master
index 912cb3244597..3b24f1384627 100644
--- a/sys/alpha/linux/syscalls.master
+++ b/sys/alpha/linux/syscalls.master
@@ -1,4 +1,4 @@
- $Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp $
+ $Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh Exp $
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
; System call name/number master file (or rather, slave, from LINUX).
@@ -171,7 +171,7 @@
caddr_t ptr); }
118 NOPROTO LINUX { int fsync(int fd); }
119 STD LINUX { int linux_sigreturn(struct linux_sigcontext *scp); }
-120 STD LINUX { int linux_clone(void); }
+120 STD LINUX { int linux_clone(int flags, void *stack); }
121 NOPROTO LINUX { int setdomainname(char *name, \
int len); }
122 STD LINUX { int linux_newuname(struct linux_newuname_t *buf); }
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 68fee0f657d6..4b441fd81370 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_misc.c,v 1.46 1998/12/04 22:54:50 archie Exp $
+ * $Id: linux_misc.c,v 1.47 1998/12/10 13:47:18 jkh Exp $
*/
#include <sys/param.h>
@@ -41,6 +41,9 @@
#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
+#ifdef COMPAT_LINUX_THREADS
+#include <sys/unistd.h>
+#endif /* COMPAT_LINUX_THREADS */
#include <sys/vnode.h>
#include <sys/wait.h>
#include <sys/time.h>
@@ -560,6 +563,84 @@ linux_fork(struct proc *p, struct linux_fork_args *args)
return 0;
}
+#ifndef COMPAT_LINUX_THREADS
+int
+linux_clone(struct proc *p, struct linux_clone_args *args)
+{
+ printf("linux_clone(%d): Not enabled\n", p->p_pid);
+ return (EOPNOTSUPP);
+}
+
+#else
+#define CLONE_VM 0x100
+#define CLONE_FS 0x200
+#define CLONE_FILES 0x400
+#define CLONE_SIGHAND 0x800
+#define CLONE_PID 0x1000
+
+int
+linux_clone(struct proc *p, struct linux_clone_args *args)
+{
+ int error, ff = RFPROC;
+ struct proc *p2;
+ int growable;
+ int initstacksize;
+ int maxstacksize;
+ int exit_signal;
+ vm_map_entry_t entry;
+ vm_map_t map;
+ vm_offset_t start;
+ struct rfork_args rf_args;
+
+#ifdef SMP
+ printf("linux_clone(%d): does not work with SMP yet\n", p->p_pid);
+ return (EOPNOTSUPP);
+#endif
+#ifdef DEBUG
+ if (args->flags & CLONE_PID)
+ printf("linux_clone(%d): CLONE_PID not yet supported\n", p->p_pid);
+ printf ("linux_clone(%d): invoked with flags %x and stack %x\n", p->p_pid,
+ (unsigned int)args->flags, (unsigned int)args->stack);
+#endif
+
+ if (!args->stack)
+ return (EINVAL);
+ exit_signal = args->flags & 0x000000ff;
+ if (exit_signal >= LINUX_NSIG)
+ return EINVAL;
+ exit_signal = linux_to_bsd_signal[exit_signal];
+
+ /* RFTHREAD probably not necessary here, but it shouldn't hurt either */
+ ff |= RFTHREAD;
+
+ if (args->flags & CLONE_VM)
+ ff |= RFMEM;
+ if (args->flags & CLONE_SIGHAND)
+ ff |= RFSIGSHARE;
+ if (!(args->flags & CLONE_FILES))
+ ff |= RFFDG;
+
+ error = 0;
+ start = 0;
+
+ rf_args.flags = ff;
+ if (error = rfork(p, &rf_args))
+ return error;
+
+ p2 = pfind(p->p_retval[0]);
+ if (p2 == 0)
+ return ESRCH;
+
+ p2->p_sigparent = exit_signal;
+ p2->p_md.md_regs->tf_esp = (unsigned int)args->stack;
+
+#ifdef DEBUG
+ printf ("linux_clone(%d): successful rfork to %d\n", p->p_pid, p2->p_pid);
+#endif
+ return 0;
+}
+
+#endif /* COMPAT_LINUX_THREADS */
/* XXX move */
struct linux_mmap_argv {
linux_caddr_t addr;
@@ -570,6 +651,11 @@ struct linux_mmap_argv {
int pos;
};
+#ifdef COMPAT_LINUX_THREADS
+#define STACK_SIZE (2 * 1024 * 1024)
+#define GUARD_SIZE (4 * PAGE_SIZE)
+
+#endif /* COMPAT_LINUX_THREADS */
int
linux_mmap(struct proc *p, struct linux_mmap_args *args)
{
@@ -602,8 +688,70 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args)
bsd_args.flags |= MAP_FIXED;
if (linux_args.flags & LINUX_MAP_ANON)
bsd_args.flags |= MAP_ANON;
+#ifndef COMPAT_LINUX_THREADS
bsd_args.addr = linux_args.addr;
bsd_args.len = linux_args.len;
+#else
+
+#if !defined(USE_VM_STACK) && !defined(USE_VM_STACK_FOR_EXEC)
+ /* Linux Threads will map into the proc stack space, unless
+ we prevent it. This causes problems if we're not using
+ our VM_STACK options.
+ */
+ if ((unsigned int)linux_args.addr + linux_args.len > (USRSTACK - MAXSSIZ))
+ return (EINVAL);
+#endif
+
+ if (linux_args.flags & LINUX_MAP_GROWSDOWN) {
+
+#ifdef USE_VM_STACK
+ /* USE_VM_STACK is defined (or not) in vm/vm_map.h */
+ bsd_args.flags |= MAP_STACK;
+#endif
+
+ /* The linux MAP_GROWSDOWN option does not limit auto
+ growth of the region. Linux mmap with this option
+ takes as addr the inital BOS, and as len, the initial
+ region size. It can then grow down from addr without
+ limit. However, linux threads has an implicit internal
+ limit to stack size of STACK_SIZE. Its just not
+ enforced explicitly in linux. But, here we impose
+ a limit of (STACK_SIZE - GUARD_SIZE) on the stack
+ region, since we can do this with our mmap.
+
+ Our mmap with MAP_STACK takes addr as the maximum
+ downsize limit on BOS, and as len the max size of
+ the region. It them maps the top SGROWSIZ bytes,
+ and autgrows the region down, up to the limit
+ in addr.
+
+ If we don't use the MAP_STACK option, the effect
+ of this code is to allocate a stack region of a
+ fixed size of (STACK_SIZE - GUARD_SIZE).
+ */
+
+ /* This gives us TOS */
+ bsd_args.addr = linux_args.addr + linux_args.len;
+
+ /* This gives us our maximum stack size */
+ if (linux_args.len > STACK_SIZE - GUARD_SIZE)
+ bsd_args.len = linux_args.len;
+ else
+ bsd_args.len = STACK_SIZE - GUARD_SIZE;
+
+ /* This gives us a new BOS. If we're using VM_STACK, then
+ mmap will just map the top SGROWSIZ bytes, and let
+ the stack grow down to the limit at BOS. If we're
+ not using VM_STACK we map the full stack, since we
+ don't have a way to autogrow it.
+ */
+ bsd_args.addr -= bsd_args.len;
+
+ } else {
+ bsd_args.addr = linux_args.addr;
+ bsd_args.len = linux_args.len;
+ }
+#endif /* COMPAT_LINUX_THREADS */
bsd_args.prot = linux_args.prot | PROT_READ; /* always required */
bsd_args.fd = linux_args.fd;
bsd_args.pos = linux_args.pos;
@@ -830,11 +978,25 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args)
#endif
tmp.pid = args->pid;
tmp.status = args->status;
+#ifndef COMPAT_LINUX_THREADS
tmp.options = args->options;
+#else
+ /* This filters out the linux option _WCLONE. I don't
+ think we need it, but I could be wrong. If we need
+ it, we need to fix wait4, since it will give us an
+ error return of EINVAL if we pass in _WCLONE, and
+ of course, it won't do anything with it.
+ */
+ tmp.options = (args->options & (WNOHANG | WUNTRACED));
+#endif /* COMPAT_LINUX_THREADS */
tmp.rusage = NULL;
if (error = wait4(p, &tmp))
+#ifndef COMPAT_LINUX_THREADS
return error;
+#else
+ return error;
+#endif /* COMPAT_LINUX_THREADS */
if (args->status) {
if (error = copyin(args->status, &tmpstat, sizeof(int)))
return error;
@@ -867,7 +1029,17 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args)
#endif
tmp.pid = args->pid;
tmp.status = args->status;
+#ifndef COMPAT_LINUX_THREADS
tmp.options = args->options;
+#else
+ /* This filters out the linux option _WCLONE. I don't
+ think we need it, but I could be wrong. If we need
+ it, we need to fix wait4, since it will give us an
+ error return of EINVAL if we pass in _WCLONE, and
+ of course, it won't do anything with it.
+ */
+ tmp.options = (args->options & (WNOHANG | WUNTRACED));
+#endif /* COMPAT_LINUX_THREADS */
tmp.rusage = args->rusage;
if (error = wait4(p, &tmp))
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 691ed550f336..820028fb5d06 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux.h,v 1.23 1998/10/05 16:37:36 jfieber Exp $
+ * $Id: linux.h,v 1.24 1998/11/12 00:42:08 jkh Exp $
*/
#ifndef _I386_LINUX_LINUX_H_
@@ -418,6 +418,7 @@ struct trapframe;
#define LINUX_MAP_PRIVATE 0x0002
#define LINUX_MAP_FIXED 0x0010
#define LINUX_MAP_ANON 0x0020
+#define LINUX_MAP_GROWSDOWN 0x0100
/* SystemV ipc defines */
#define LINUX_SEMOP 1
diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c
index 30a0dba49449..6a7ce1e82802 100644
--- a/sys/i386/linux/linux_dummy.c
+++ b/sys/i386/linux/linux_dummy.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_dummy.c,v 1.7 1997/10/29 08:17:09 kato Exp $
+ * $Id: linux_dummy.c,v 1.8 1997/11/06 19:28:52 phk Exp $
*/
#include <sys/param.h>
@@ -212,13 +212,6 @@ linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args)
}
int
-linux_clone(struct proc *p, struct linux_clone_args *args)
-{
- printf("Linux-emul(%d): clone() not supported\n", p->p_pid);
- return ENOSYS;
-}
-
-int
linux_uname(struct proc *p, struct linux_uname_args *args)
{
printf("Linux-emul(%d): uname() not supported\n", p->p_pid);
diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c
index 68fee0f657d6..4b441fd81370 100644
--- a/sys/i386/linux/linux_misc.c
+++ b/sys/i386/linux/linux_misc.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_misc.c,v 1.46 1998/12/04 22:54:50 archie Exp $
+ * $Id: linux_misc.c,v 1.47 1998/12/10 13:47:18 jkh Exp $
*/
#include <sys/param.h>
@@ -41,6 +41,9 @@
#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
+#ifdef COMPAT_LINUX_THREADS
+#include <sys/unistd.h>
+#endif /* COMPAT_LINUX_THREADS */
#include <sys/vnode.h>
#include <sys/wait.h>
#include <sys/time.h>
@@ -560,6 +563,84 @@ linux_fork(struct proc *p, struct linux_fork_args *args)
return 0;
}
+#ifndef COMPAT_LINUX_THREADS
+int
+linux_clone(struct proc *p, struct linux_clone_args *args)
+{
+ printf("linux_clone(%d): Not enabled\n", p->p_pid);
+ return (EOPNOTSUPP);
+}
+
+#else
+#define CLONE_VM 0x100
+#define CLONE_FS 0x200
+#define CLONE_FILES 0x400
+#define CLONE_SIGHAND 0x800
+#define CLONE_PID 0x1000
+
+int
+linux_clone(struct proc *p, struct linux_clone_args *args)
+{
+ int error, ff = RFPROC;
+ struct proc *p2;
+ int growable;
+ int initstacksize;
+ int maxstacksize;
+ int exit_signal;
+ vm_map_entry_t entry;
+ vm_map_t map;
+ vm_offset_t start;
+ struct rfork_args rf_args;
+
+#ifdef SMP
+ printf("linux_clone(%d): does not work with SMP yet\n", p->p_pid);
+ return (EOPNOTSUPP);
+#endif
+#ifdef DEBUG
+ if (args->flags & CLONE_PID)
+ printf("linux_clone(%d): CLONE_PID not yet supported\n", p->p_pid);
+ printf ("linux_clone(%d): invoked with flags %x and stack %x\n", p->p_pid,
+ (unsigned int)args->flags, (unsigned int)args->stack);
+#endif
+
+ if (!args->stack)
+ return (EINVAL);
+ exit_signal = args->flags & 0x000000ff;
+ if (exit_signal >= LINUX_NSIG)
+ return EINVAL;
+ exit_signal = linux_to_bsd_signal[exit_signal];
+
+ /* RFTHREAD probably not necessary here, but it shouldn't hurt either */
+ ff |= RFTHREAD;
+
+ if (args->flags & CLONE_VM)
+ ff |= RFMEM;
+ if (args->flags & CLONE_SIGHAND)
+ ff |= RFSIGSHARE;
+ if (!(args->flags & CLONE_FILES))
+ ff |= RFFDG;
+
+ error = 0;
+ start = 0;
+
+ rf_args.flags = ff;
+ if (error = rfork(p, &rf_args))
+ return error;
+
+ p2 = pfind(p->p_retval[0]);
+ if (p2 == 0)
+ return ESRCH;
+
+ p2->p_sigparent = exit_signal;
+ p2->p_md.md_regs->tf_esp = (unsigned int)args->stack;
+
+#ifdef DEBUG
+ printf ("linux_clone(%d): successful rfork to %d\n", p->p_pid, p2->p_pid);
+#endif
+ return 0;
+}
+
+#endif /* COMPAT_LINUX_THREADS */
/* XXX move */
struct linux_mmap_argv {
linux_caddr_t addr;
@@ -570,6 +651,11 @@ struct linux_mmap_argv {
int pos;
};
+#ifdef COMPAT_LINUX_THREADS
+#define STACK_SIZE (2 * 1024 * 1024)
+#define GUARD_SIZE (4 * PAGE_SIZE)
+
+#endif /* COMPAT_LINUX_THREADS */
int
linux_mmap(struct proc *p, struct linux_mmap_args *args)
{
@@ -602,8 +688,70 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args)
bsd_args.flags |= MAP_FIXED;
if (linux_args.flags & LINUX_MAP_ANON)
bsd_args.flags |= MAP_ANON;
+#ifndef COMPAT_LINUX_THREADS
bsd_args.addr = linux_args.addr;
bsd_args.len = linux_args.len;
+#else
+
+#if !defined(USE_VM_STACK) && !defined(USE_VM_STACK_FOR_EXEC)
+ /* Linux Threads will map into the proc stack space, unless
+ we prevent it. This causes problems if we're not using
+ our VM_STACK options.
+ */
+ if ((unsigned int)linux_args.addr + linux_args.len > (USRSTACK - MAXSSIZ))
+ return (EINVAL);
+#endif
+
+ if (linux_args.flags & LINUX_MAP_GROWSDOWN) {
+
+#ifdef USE_VM_STACK
+ /* USE_VM_STACK is defined (or not) in vm/vm_map.h */
+ bsd_args.flags |= MAP_STACK;
+#endif
+
+ /* The linux MAP_GROWSDOWN option does not limit auto
+ growth of the region. Linux mmap with this option
+ takes as addr the inital BOS, and as len, the initial
+ region size. It can then grow down from addr without
+ limit. However, linux threads has an implicit internal
+ limit to stack size of STACK_SIZE. Its just not
+ enforced explicitly in linux. But, here we impose
+ a limit of (STACK_SIZE - GUARD_SIZE) on the stack
+ region, since we can do this with our mmap.
+
+ Our mmap with MAP_STACK takes addr as the maximum
+ downsize limit on BOS, and as len the max size of
+ the region. It them maps the top SGROWSIZ bytes,
+ and autgrows the region down, up to the limit
+ in addr.
+
+ If we don't use the MAP_STACK option, the effect
+ of this code is to allocate a stack region of a
+ fixed size of (STACK_SIZE - GUARD_SIZE).
+ */
+
+ /* This gives us TOS */
+ bsd_args.addr = linux_args.addr + linux_args.len;
+
+ /* This gives us our maximum stack size */
+ if (linux_args.len > STACK_SIZE - GUARD_SIZE)
+ bsd_args.len = linux_args.len;
+ else
+ bsd_args.len = STACK_SIZE - GUARD_SIZE;
+
+ /* This gives us a new BOS. If we're using VM_STACK, then
+ mmap will just map the top SGROWSIZ bytes, and let
+ the stack grow down to the limit at BOS. If we're
+ not using VM_STACK we map the full stack, since we
+ don't have a way to autogrow it.
+ */
+ bsd_args.addr -= bsd_args.len;
+
+ } else {
+ bsd_args.addr = linux_args.addr;
+ bsd_args.len = linux_args.len;
+ }
+#endif /* COMPAT_LINUX_THREADS */
bsd_args.prot = linux_args.prot | PROT_READ; /* always required */
bsd_args.fd = linux_args.fd;
bsd_args.pos = linux_args.pos;
@@ -830,11 +978,25 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args)
#endif
tmp.pid = args->pid;
tmp.status = args->status;
+#ifndef COMPAT_LINUX_THREADS
tmp.options = args->options;
+#else
+ /* This filters out the linux option _WCLONE. I don't
+ think we need it, but I could be wrong. If we need
+ it, we need to fix wait4, since it will give us an
+ error return of EINVAL if we pass in _WCLONE, and
+ of course, it won't do anything with it.
+ */
+ tmp.options = (args->options & (WNOHANG | WUNTRACED));
+#endif /* COMPAT_LINUX_THREADS */
tmp.rusage = NULL;
if (error = wait4(p, &tmp))
+#ifndef COMPAT_LINUX_THREADS
return error;
+#else
+ return error;
+#endif /* COMPAT_LINUX_THREADS */
if (args->status) {
if (error = copyin(args->status, &tmpstat, sizeof(int)))
return error;
@@ -867,7 +1029,17 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args)
#endif
tmp.pid = args->pid;
tmp.status = args->status;
+#ifndef COMPAT_LINUX_THREADS
tmp.options = args->options;
+#else
+ /* This filters out the linux option _WCLONE. I don't
+ think we need it, but I could be wrong. If we need
+ it, we need to fix wait4, since it will give us an
+ error return of EINVAL if we pass in _WCLONE, and
+ of course, it won't do anything with it.
+ */
+ tmp.options = (args->options & (WNOHANG | WUNTRACED));
+#endif /* COMPAT_LINUX_THREADS */
tmp.rusage = args->rusage;
if (error = wait4(p, &tmp))
diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h
index eedb56606a4c..395d907e4ccb 100644
--- a/sys/i386/linux/linux_proto.h
+++ b/sys/i386/linux/linux_proto.h
@@ -2,7 +2,7 @@
* System call prototypes.
*
* DO NOT EDIT-- this file is automatically generated.
- * created from Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp
+ * created from Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh Exp
*/
#ifndef _LINUX_SYSPROTO_H_
@@ -301,7 +301,8 @@ struct linux_sigreturn_args {
struct linux_sigcontext * scp; char scp_[PAD_(struct linux_sigcontext *)];
};
struct linux_clone_args {
- register_t dummy;
+ int flags; char flags_[PAD_(int)];
+ void * stack; char stack_[PAD_(void *)];
};
struct linux_newuname_args {
struct linux_newuname_t * buf; char buf_[PAD_(struct linux_newuname_t *)];
diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h
index c0b714753156..c88cc7c86623 100644
--- a/sys/i386/linux/linux_syscall.h
+++ b/sys/i386/linux/linux_syscall.h
@@ -2,7 +2,7 @@
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
- * created from Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp
+ * created from Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh Exp
*/
#define LINUX_SYS_linux_setup 0
diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c
index da9ac246a517..709fffb6d032 100644
--- a/sys/i386/linux/linux_sysent.c
+++ b/sys/i386/linux/linux_sysent.c
@@ -2,7 +2,7 @@
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * created from Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp
+ * created from Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh Exp
*/
#include "opt_compat.h"
@@ -134,7 +134,7 @@ struct sysent linux_sysent[] = {
{ 5, (sy_call_t *)linux_ipc }, /* 117 = linux_ipc */
{ 1, (sy_call_t *)fsync }, /* 118 = fsync */
{ 1, (sy_call_t *)linux_sigreturn }, /* 119 = linux_sigreturn */
- { 0, (sy_call_t *)linux_clone }, /* 120 = linux_clone */
+ { 2, (sy_call_t *)linux_clone }, /* 120 = linux_clone */
{ 2, (sy_call_t *)setdomainname }, /* 121 = setdomainname */
{ 1, (sy_call_t *)linux_newuname }, /* 122 = linux_newuname */
{ 3, (sy_call_t *)linux_modify_ldt }, /* 123 = linux_modify_ldt */
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 188e3d5a5b69..b8639516ef86 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_sysvec.c,v 1.39 1998/12/14 18:54:01 dt Exp $
+ * $Id: linux_sysvec.c,v 1.40 1998/12/16 16:28:57 bde Exp $
*/
/* XXX we use functions that might not exist. */
@@ -50,6 +50,10 @@
#include <vm/vm_prot.h>
#include <vm/vm_page.h>
#include <vm/vm_extern.h>
+#ifdef COMPAT_LINUX_THREADS
+#include <sys/lock.h> /* needed, for now, by vm_map.h */
+#include <vm/vm_map.h> /* needed, for now, for VM_STACK defines */
+#endif /* COMPAT_LINUX_THREADS */
#include <sys/exec.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -217,7 +221,24 @@ linux_sendsig(sig_t catcher, int sig, int mask, u_long code)
* and the stack can not be grown. useracc will return FALSE
* if access is denied.
*/
+#ifdef COMPAT_LINUX_THREADS
+#ifdef USE_VM_STACK
+#ifndef USE_VM_STACK_FOR_EXEC
+ if ((((caddr_t)fp > p->p_vmspace->vm_maxsaddr &&
+ (caddr_t)fp < (caddr_t)USRSTACK &&
+ grow(p, (int)fp) == FALSE) ||
+ (((caddr_t)fp <= p->p_vmspace->vm_maxsaddr ||
+ (caddr_t)fp >= (caddr_t)USRSTACK) &&
+ grow_stack (p, (int)fp) == FALSE)) ||
+#else
+ if ((grow_stack (p, (int)fp) == FALSE) ||
+#endif
+#else
+#endif /* COMPAT_LINUX_THREADS */
if ((grow(p, (int)fp) == FALSE) ||
+#ifdef COMPAT_LINUX_THREADS
+#endif
+#endif /* COMPAT_LINUX_THREADS */
(useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) {
/*
* Process has trashed its stack; give it an illegal
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index 912cb3244597..3b24f1384627 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -1,4 +1,4 @@
- $Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp $
+ $Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh Exp $
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
; System call name/number master file (or rather, slave, from LINUX).
@@ -171,7 +171,7 @@
caddr_t ptr); }
118 NOPROTO LINUX { int fsync(int fd); }
119 STD LINUX { int linux_sigreturn(struct linux_sigcontext *scp); }
-120 STD LINUX { int linux_clone(void); }
+120 STD LINUX { int linux_clone(int flags, void *stack); }
121 NOPROTO LINUX { int setdomainname(char *name, \
int len); }
122 STD LINUX { int linux_newuname(struct linux_newuname_t *buf); }
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 25b7031fe03d..a0a228466784 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: imgact_elf.c,v 1.42 1998/10/25 17:44:50 phk Exp $
+ * $Id: imgact_elf.c,v 1.43 1998/12/04 22:54:51 archie Exp $
*/
#include "opt_rlimit.h"
@@ -854,7 +854,11 @@ elf_corehdr(p, vp, cred, numsegs, hdr, hdrsize)
status.pr_gregsetsz = sizeof(gregset_t);
status.pr_fpregsetsz = sizeof(fpregset_t);
status.pr_osreldate = osreldate;
+#ifndef COMPAT_LINUX_THREADS
status.pr_cursig = p->p_sigacts->ps_sig;
+#else
+ status.pr_cursig = p->p_sig;
+#endif /* COMPAT_LINUX_THREADS */
status.pr_pid = p->p_pid;
fill_regs(p, &status.pr_reg);
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index fffe109924d8..ae0ad3361b1d 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -39,7 +39,7 @@
* SUCH DAMAGE.
*
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
- * $Id: init_main.c,v 1.98 1998/10/09 23:42:47 peter Exp $
+ * $Id: init_main.c,v 1.99 1998/10/15 17:09:19 peter Exp $
*/
#include "opt_devfs.h"
@@ -83,6 +83,9 @@ static struct session session0;
static struct pgrp pgrp0;
struct proc proc0;
static struct pcred cred0;
+#ifdef COMPAT_LINUX_THREADS
+static struct procsig procsig0;
+#endif /* COMPAT_LINUX_THREADS */
static struct filedesc0 filedesc0;
static struct plimit limit0;
static struct vmspace vmspace0;
@@ -415,6 +418,12 @@ proc0_init(dummy)
p->p_ucred = crget();
p->p_ucred->cr_ngroups = 1; /* group 0 */
+#ifdef COMPAT_LINUX_THREADS
+ /* Create procsig. */
+ p->p_procsig = &procsig0;
+ p->p_procsig->ps_refcnt = 2;
+
+#endif /* COMPAT_LINUX_THREADS */
/* Create the file descriptor table. */
fdp = &filedesc0;
p->p_fd = &fdp->fd_fd;
@@ -461,11 +470,20 @@ proc0_init(dummy)
#endif
/*
+#ifndef COMPAT_LINUX_THREADS
* We continue to place resource usage info and signal
* actions in the user struct so they're pageable.
*/
p->p_stats = &p->p_addr->u_stats;
p->p_sigacts = &p->p_addr->u_sigacts;
+#else
+ * We continue to place resource usage info in the user struct so
+ * it's pageable.
+ */
+ p->p_stats = &p->p_addr->u_stats;
+
+ p->p_sigacts = &p->p_procsig->ps_sigacts;
+#endif /* COMPAT_LINUX_THREADS */
/*
* Charge root for one process.
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index fd5e23ef7189..7de0c480ebc7 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
- * $Id: kern_exit.c,v 1.68 1998/11/10 09:16:29 peter Exp $
+ * $Id: kern_exit.c,v 1.69 1998/11/11 10:03:54 truckman Exp $
*/
#include "opt_compat.h"
@@ -181,7 +181,9 @@ exit1(p, rv)
*/
p->p_flag &= ~(P_TRACED | P_PPWAIT);
p->p_flag |= P_WEXIT;
+#ifndef COMPAT_LINUX_THREADS
p->p_sigignore = ~0;
+#endif /* COMPAT_LINUX_THREADS */
p->p_siglist = 0;
if (timevalisset(&p->p_realtimer.it_value))
untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
@@ -282,6 +284,9 @@ exit1(p, rv)
LIST_REMOVE(q, p_sibling);
LIST_INSERT_HEAD(&initproc->p_children, q, p_sibling);
q->p_pptr = initproc;
+#ifdef COMPAT_LINUX_THREADS
+ q->p_sigparent = 0;
+#endif /* COMPAT_LINUX_THREADS */
/*
* Traced processes are killed
* since their existence means someone is screwing up.
@@ -306,7 +311,11 @@ exit1(p, rv)
* flag set, notify process 1 instead (and hope it will handle
* this situation).
*/
+#ifndef COMPAT_LINUX_THREADS
if (p->p_pptr->p_flag & P_NOCLDWAIT) {
+#else
+ if (p->p_pptr->p_procsig->ps_flag & P_NOCLDWAIT) {
+#endif /* COMPAT_LINUX_THREADS */
struct proc *pp = p->p_pptr;
proc_reparent(p, initproc);
/*
@@ -318,7 +327,15 @@ exit1(p, rv)
wakeup((caddr_t)pp);
}
+#ifndef COMPAT_LINUX_THREADS
psignal(p->p_pptr, SIGCHLD);
+#else
+ if (p->p_sigparent && p->p_pptr != initproc) {
+ psignal(p->p_pptr, p->p_sigparent);
+ } else {
+ psignal(p->p_pptr, SIGCHLD);
+ }
+#endif /* COMPAT_LINUX_THREADS */
wakeup((caddr_t)p->p_pptr);
#if defined(tahoe)
/* move this to cpu_exit */
@@ -421,6 +438,14 @@ loop:
if (uap->pid != WAIT_ANY &&
p->p_pid != uap->pid && p->p_pgid != -uap->pid)
continue;
+#ifdef COMPAT_LINUX_THREADS
+ #if 0
+ if ((p->p_sigparent != 0) ^ ((uap->options & WLINUXCLONE) != 0)) {
+ continue;
+ }
+ #endif
+
+#endif /* COMPAT_LINUX_THREADS */
nfound++;
if (p->p_stat == SZOMB) {
/* charge childs scheduling cpu usage to parent */
@@ -488,6 +513,14 @@ loop:
LIST_REMOVE(p, p_list); /* off zombproc */
LIST_REMOVE(p, p_sibling);
+#ifdef COMPAT_LINUX_THREADS
+ if (--p->p_procsig->ps_refcnt == 0) {
+ free(p->p_procsig, M_TEMP);
+ p->p_procsig = NULL;
+ p->p_sigacts = NULL;
+ }
+
+#endif /* COMPAT_LINUX_THREADS */
/*
* Give machine-dependent layer a chance
* to free anything that cpu_exit couldn't
@@ -543,6 +576,11 @@ proc_reparent(child, parent)
LIST_REMOVE(child, p_sibling);
LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
child->p_pptr = parent;
+#ifdef COMPAT_LINUX_THREADS
+ #if 0
+ child->p_sigparent = 0;
+ #endif
+#endif /* COMPAT_LINUX_THREADS */
}
/*
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index a1f6c859fe89..ef38e011908e 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_fork.c 8.6 (Berkeley) 4/8/94
- * $Id: kern_fork.c,v 1.51 1998/01/22 17:29:46 dyson Exp $
+ * $Id: kern_fork.c,v 1.52 1998/11/09 15:07:41 truckman Exp $
*/
#include "opt_ktrace.h"
@@ -62,6 +62,10 @@
#include <vm/vm_extern.h>
#include <vm/vm_zone.h>
+#ifdef COMPAT_LINUX_THREADS
+#include <machine/frame.h>
+
+#endif /* COMPAT_LINUX_THREADS */
#ifdef SMP
static int fast_vfork = 0; /* Doesn't work on SMP yet. */
#else
@@ -325,6 +329,24 @@ again:
p2->p_cred->p_refcnt = 1;
crhold(p1->p_ucred);
+#ifdef COMPAT_LINUX_THREADS
+ if (flags & RFSIGSHARE) {
+ p2->p_procsig->ps_refcnt++;
+ } else {
+ p2->p_procsig = malloc(sizeof(struct procsig), M_TEMP, M_WAITOK);
+ p2->p_procsig->ps_refcnt = 1;
+ p2->p_procsig->ps_posix = 0;
+ bcopy(&p1->p_procsig->ps_begincopy, &p2->p_procsig->ps_begincopy,
+ (unsigned)&p1->p_procsig->ps_endcopy -
+ (unsigned)&p1->p_procsig->ps_begincopy);
+ }
+ if (flags & RFLINUXTHPN) {
+ p2->p_sigparent = SIGUSR1;
+ }
+ p2->p_sigacts = &p2->p_procsig->ps_sigacts;
+ if((flags & RFTHREAD) != 0 && (flags & RFPOSIXSIG) != 0)
+ p2->p_procsig->ps_posix = 1;
+#endif /* COMPAT_LINUX_THREADS */
/* bump references to the text vnode (for procfs) */
p2->p_textvp = p1->p_textvp;
if (p2->p_textvp)
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 41b4e0918866..dd4a4318ae3d 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_sig.c 8.7 (Berkeley) 4/18/94
- * $Id: kern_sig.c,v 1.49 1998/11/11 10:03:55 truckman Exp $
+ * $Id: kern_sig.c,v 1.50 1998/12/02 01:53:48 eivind Exp $
*/
#include "opt_compat.h"
@@ -135,9 +135,17 @@ sigaction(p, uap)
sa->sa_flags |= SA_RESETHAND;
if ((ps->ps_signodefer & bit) != 0)
sa->sa_flags |= SA_NODEFER;
+#ifndef COMPAT_LINUX_THREADS
if (signum == SIGCHLD && p->p_flag & P_NOCLDSTOP)
+#else
+ if (signum == SIGCHLD && p->p_procsig->ps_flag & P_NOCLDSTOP)
+#endif /* COMPAT_LINUX_THREADS */
sa->sa_flags |= SA_NOCLDSTOP;
+#ifndef COMPAT_LINUX_THREADS
if (signum == SIGCHLD && p->p_flag & P_NOCLDWAIT)
+#else
+ if (signum == SIGCHLD && p->p_procsig->ps_flag & P_NOCLDWAIT)
+#endif /* COMPAT_LINUX_THREADS */
sa->sa_flags |= SA_NOCLDWAIT;
if ((error = copyout((caddr_t)sa, (caddr_t)uap->osa,
sizeof (vec))))
@@ -195,9 +203,15 @@ setsigvec(p, signum, sa)
#endif
if (signum == SIGCHLD) {
if (sa->sa_flags & SA_NOCLDSTOP)
+#ifndef COMPAT_LINUX_THREADS
p->p_flag |= P_NOCLDSTOP;
else
p->p_flag &= ~P_NOCLDSTOP;
+#else
+ p->p_procsig->ps_flag |= P_NOCLDSTOP;
+ else
+ p->p_procsig->ps_flag &= ~P_NOCLDSTOP;
+#endif /* COMPAT_LINUX_THREADS */
if (sa->sa_flags & SA_NOCLDWAIT) {
/*
* Paranoia: since SA_NOCLDWAIT is implemented by
@@ -206,11 +220,21 @@ setsigvec(p, signum, sa)
* forbidden to set SA_NOCLDWAIT.
*/
if (p->p_pid == 1)
+#ifndef COMPAT_LINUX_THREADS
p->p_flag &= ~P_NOCLDWAIT;
else
p->p_flag |= P_NOCLDWAIT;
+#else
+ p->p_procsig->ps_flag &= ~P_NOCLDWAIT;
+ else
+ p->p_procsig->ps_flag |= P_NOCLDWAIT;
+#endif /* COMPAT_LINUX_THREADS */
} else
+#ifndef COMPAT_LINUX_THREADS
p->p_flag &= ~P_NOCLDWAIT;
+#else
+ p->p_procsig->ps_flag &= ~P_NOCLDWAIT;
+#endif /* COMPAT_LINUX_THREADS */
}
/*
* Set bit in p_sigignore for signals that are set to SIG_IGN,
@@ -385,7 +409,11 @@ osigvec(p, uap)
if ((ps->ps_signodefer & bit) != 0)
sv->sv_flags |= SV_NODEFER;
#ifndef COMPAT_SUNOS
+#ifndef COMPAT_LINUX_THREADS
if (signum == SIGCHLD && p->p_flag & P_NOCLDSTOP)
+#else
+ if (signum == SIGCHLD && p->p_procsig->ps_flag & P_NOCLDSTOP)
+#endif /* COMPAT_LINUX_THREADS */
sv->sv_flags |= SV_NOCLDSTOP;
#endif
if ((error = copyout((caddr_t)sv, (caddr_t)uap->osv,
@@ -470,8 +498,12 @@ sigsuspend(p, uap)
* save it here and mark the sigacts structure
* to indicate this.
*/
+#ifndef COMPAT_LINUX_THREADS
ps->ps_oldmask = p->p_sigmask;
ps->ps_flags |= SAS_OLDMASK;
+#else
+ p->p_oldsigmask = p->p_sigmask;
+#endif /* COMPAT_LINUX_THREADS */
p->p_sigmask = uap->mask &~ sigcantmask;
while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0)
/* void */;
@@ -730,8 +762,13 @@ trapsignal(p, signum, code)
ps->ps_sigact[signum] = SIG_DFL;
}
} else {
+#ifndef COMPAT_LINUX_THREADS
ps->ps_code = code; /* XXX for core dump/debugger */
ps->ps_sig = signum; /* XXX to verify code */
+#else
+ p->p_code = code; /* XXX for core dump/debugger */
+ p->p_sig = signum; /* XXX to verify code */
+#endif /* COMPAT_LINUX_THREADS */
psignal(p, signum);
}
}
@@ -780,7 +817,11 @@ psignal(p, signum)
* and if it is set to SIG_IGN,
* action will be SIG_DFL here.)
*/
+#ifndef COMPAT_LINUX_THREADS
if (p->p_sigignore & mask)
+#else
+ if ((p->p_sigignore & mask) || (p->p_flag & P_WEXIT))
+#endif /* COMPAT_LINUX_THREADS */
return;
if (p->p_sigmask & mask)
action = SIG_HOLD;
@@ -862,7 +903,11 @@ psignal(p, signum)
goto out;
p->p_siglist &= ~mask;
p->p_xstat = signum;
+#ifndef COMPAT_LINUX_THREADS
if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)
+#else
+ if ((p->p_pptr->p_procsig->ps_flag & P_NOCLDSTOP) == 0)
+#endif /* COMPAT_LINUX_THREADS */
psignal(p->p_pptr, SIGCHLD);
stop(p);
goto out;
@@ -1069,7 +1114,11 @@ issignal(p)
break; /* == ignore */
p->p_xstat = signum;
stop(p);
+#ifndef COMPAT_LINUX_THREADS
if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)
+#else
+ if ((p->p_pptr->p_procsig->ps_flag & P_NOCLDSTOP) == 0)
+#endif /* COMPAT_LINUX_THREADS */
psignal(p->p_pptr, SIGCHLD);
mi_switch();
break;
@@ -1144,8 +1193,13 @@ postsig(signum)
#ifdef KTRACE
if (KTRPOINT(p, KTR_PSIG))
ktrpsig(p->p_tracep,
+#ifndef COMPAT_LINUX_THREADS
signum, action, ps->ps_flags & SAS_OLDMASK ?
ps->ps_oldmask : p->p_sigmask, 0);
+#else
+ signum, action, p->p_oldsigmask ?
+ p->p_oldsigmask : p->p_sigmask, 0);
+#endif /* COMPAT_LINUX_THREADS */
#endif
STOPEVENT(p, S_SIG, signum);
@@ -1174,9 +1228,15 @@ postsig(signum)
* restored after the signal processing is completed.
*/
(void) splhigh();
+#ifndef COMPAT_LINUX_THREADS
if (ps->ps_flags & SAS_OLDMASK) {
returnmask = ps->ps_oldmask;
ps->ps_flags &= ~SAS_OLDMASK;
+#else
+ if (p->p_oldsigmask) {
+ returnmask = p->p_oldsigmask;
+ p->p_oldsigmask = 0;
+#endif /* COMPAT_LINUX_THREADS */
} else
returnmask = p->p_sigmask;
p->p_sigmask |= ps->ps_catchmask[signum] |
@@ -1192,12 +1252,22 @@ postsig(signum)
}
(void) spl0();
p->p_stats->p_ru.ru_nsignals++;
+#ifndef COMPAT_LINUX_THREADS
if (ps->ps_sig != signum) {
+#else
+ if (p->p_sig != signum) {
+#endif /* COMPAT_LINUX_THREADS */
code = 0;
} else {
+#ifndef COMPAT_LINUX_THREADS
code = ps->ps_code;
ps->ps_code = 0;
ps->ps_sig = 0;
+#else
+ code = p->p_code;
+ p->p_code = 0;
+ p->p_sig = 0;
+#endif /* COMPAT_LINUX_THREADS */
}
(*p->p_sysent->sv_sendsig)(action, signum, returnmask, code);
}
@@ -1232,7 +1302,11 @@ sigexit(p, signum)
p->p_acflag |= AXSIG;
if (sigprop[signum] & SA_CORE) {
+#ifndef COMPAT_LINUX_THREADS
p->p_sigacts->ps_sig = signum;
+#else
+ p->p_sig = signum;
+#endif /* COMPAT_LINUX_THREADS */
/*
* Log signals which would cause core dumps
* (Log as LOG_INFO to appease those who don't want
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 7ee6020b0000..d4fd1e2403e2 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)proc.h 8.15 (Berkeley) 5/19/95
- * $Id: proc.h,v 1.61 1998/11/11 10:56:05 truckman Exp $
+ * $Id: proc.h,v 1.62 1998/11/13 17:53:55 dg Exp $
*/
#ifndef _SYS_PROC_H_
@@ -47,6 +47,9 @@
#include <sys/rtprio.h> /* For struct rtprio. */
#include <sys/select.h> /* For struct selinfo. */
#include <sys/signal.h>
+#ifdef COMPAT_LINUX_THREADS
+#include <sys/signalvar.h>
+#endif /* COMPAT_LINUX_THREADS */
#ifndef KERNEL
#include <sys/time.h> /* For structs itimerval, timeval. */
#endif
@@ -78,6 +81,19 @@ struct pgrp {
int pg_jobc; /* # procs qualifying pgrp for job control */
};
+#ifdef COMPAT_LINUX_THREADS
+struct procsig {
+#define ps_begincopy ps_sigignore
+ sigset_t ps_sigignore; /* Signals being ignored. */
+ sigset_t ps_sigcatch; /* Signals being caught by user. */
+ int ps_flag;
+ struct sigacts ps_sigacts;
+#define ps_endcopy ps_refcnt
+ int ps_refcnt;
+ int ps_posix;
+};
+
+#endif /* COMPAT_LINUX_THREADS */
/*
* Description of a process.
*
@@ -164,17 +180,34 @@ struct proc {
char p_pad3[2]; /* padding for alignment */
register_t p_retval[2]; /* syscall aux returns */
struct sigiolst p_sigiolst; /* list of sigio sources */
+#ifdef COMPAT_LINUX_THREADS
+ int p_sigparent; /* signal to parent on exit */
+ sigset_t p_oldsigmask; /* saved mask from before sigpause */
+ int p_sig; /* for core dump/debugger XXX */
+ u_long p_code; /* for core dump/debugger XXX */
+#endif /* COMPAT_LINUX_THREADS */
/* End area that is zeroed on creation. */
#define p_endzero p_startcopy
/* The following fields are all copied upon creation in fork. */
+#ifndef COMPAT_LINUX_THREADS
#define p_startcopy p_sigmask
-
+#else
+#define p_startcopy p_procsig
+#endif /* COMPAT_LINUX_THREADS */
+
+#ifdef COMPAT_LINUX_THREADS
+ struct procsig *p_procsig;
+#define p_sigignore p_procsig->ps_sigignore
+#define p_sigcatch p_procsig->ps_sigcatch
+#endif /* COMPAT_LINUX_THREADS */
sigset_t p_sigmask; /* Current signal mask. */
+#ifndef COMPAT_LINUX_THREADS
sigset_t p_sigignore; /* Signals being ignored. */
sigset_t p_sigcatch; /* Signals being caught by user. */
+#endif /* COMPAT_LINUX_THREADS */
u_char p_priority; /* Process priority. */
u_char p_usrpri; /* User-priority based on p_cpu and p_nice. */
char p_nice; /* Process "nice" value. */
@@ -349,7 +382,11 @@ void wakeup_one __P((void *chan));
void cpu_exit __P((struct proc *)) __dead2;
void exit1 __P((struct proc *, int)) __dead2;
void cpu_fork __P((struct proc *, struct proc *));
+#ifndef COMPAT_LINUX_THREADS
int fork1 __P((struct proc *, int));
+#else
+int fork1 __P((struct proc *, int));
+#endif /* COMPAT_LINUX_THREADS */
int trace_req __P((struct proc *));
void cpu_wait __P((struct proc *));
int cpu_coredump __P((struct proc *, struct vnode *, struct ucred *));
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 1ca6bedb2e76..a97f950b5477 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)signalvar.h 8.6 (Berkeley) 2/19/95
- * $Id: signalvar.h,v 1.19 1998/09/14 05:36:51 jdp Exp $
+ * $Id: signalvar.h,v 1.20 1998/11/11 10:04:13 truckman Exp $
*/
#ifndef _SYS_SIGNALVAR_H_ /* tmp for user.h */
@@ -55,11 +55,15 @@ struct sigacts {
sigset_t ps_sigintr; /* signals that interrupt syscalls */
sigset_t ps_sigreset; /* signals that reset when caught */
sigset_t ps_signodefer; /* signals not masked while handled */
+#ifndef COMPAT_LINUX_THREADS
sigset_t ps_oldmask; /* saved mask from before sigpause */
+#endif /* COMPAT_LINUX_THREADS */
int ps_flags; /* signal flags, below */
struct sigaltstack ps_sigstk; /* sp & on stack state variable */
+#ifndef COMPAT_LINUX_THREADS
int ps_sig; /* for core dump/debugger XXX */
u_long ps_code; /* for core dump/debugger XXX */
+#endif /* COMPAT_LINUX_THREADS */
sigset_t ps_usertramp; /* SunOS compat; libc sigtramp XXX */
};
diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h
index b96572d6f8e1..17b2028a99a4 100644
--- a/sys/sys/unistd.h
+++ b/sys/sys/unistd.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)unistd.h 8.2 (Berkeley) 1/7/94
- * $Id: unistd.h,v 1.16 1998/03/08 17:25:38 dufault Exp $
+ * $Id: unistd.h,v 1.17 1998/03/28 11:51:01 dufault Exp $
*/
#ifndef _SYS_UNISTD_H_
@@ -186,6 +186,9 @@
#define RFCENVG (1<<11) /* UNIMPL zero plan9 `env space' */
#define RFCFDG (1<<12) /* zero fd table */
#define RFTHREAD (1<<13) /* enable kernel thread support */
+#define RFSIGSHARE (1<<14) /* share signal handlers */
+#define RFPOSIXSIG (1<<15) /* UNIMPL posix thread signal delivery */
+#define RFLINUXTHPN (1<<16) /* do linux clone exit parent notification */
#define RFPPWAIT (1<<31) /* parent sleeps until child exits (vfork) */
#endif /* !_POSIX_SOURCE */
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 9a34940977b2..f97891cbfb2a 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)user.h 8.2 (Berkeley) 9/23/93
- * $Id: user.h,v 1.15 1998/03/28 10:33:24 bde Exp $
+ * $Id: user.h,v 1.16 1998/07/15 20:18:00 dfr Exp $
*/
#ifndef _SYS_USER_H_
@@ -102,7 +102,9 @@ void fill_eproc __P((struct proc *, struct eproc *));
struct user {
struct pcb u_pcb;
+#ifndef COMPAT_LINUX_THREADS
struct sigacts u_sigacts; /* p_sigacts points here (use it!) */
+#endif /* COMPAT_LINUX_THREADS */
struct pstats u_stats; /* p_stats points here (use it!) */
/*
@@ -127,8 +129,13 @@ struct user {
#define U_tsize u_kproc.kp_eproc.e_vm.vm_tsize
#define U_dsize u_kproc.kp_eproc.e_vm.vm_dsize
#define U_ssize u_kproc.kp_eproc.e_vm.vm_ssize
+#ifndef COMPAT_LINUX_THREADS
#define U_sig u_sigacts.ps_sig
#define U_code u_sigacts.ps_code
+#else
+#define U_sig u_kproc.kp_proc.p_sig
+#define U_code u_kproc.kp_proc.p_code
+#endif /* COMPAT_LINUX_THREADS */
#ifndef KERNEL
#define u_ar0 U_ar0
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index e73862d9fa9c..33131499a007 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -59,7 +59,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_glue.c,v 1.76 1998/09/29 17:33:59 abial Exp $
+ * $Id: vm_glue.c,v 1.77 1998/10/13 08:24:43 dg Exp $
*/
#include "opt_rlimit.h"
@@ -230,13 +230,20 @@ vm_fork(p1, p2, flags)
up = p2->p_addr;
/*
+#ifndef COMPAT_LINUX_THREADS
* p_stats and p_sigacts currently point at fields in the user struct
* but not at &u, instead at p_addr. Copy p_sigacts and parts of
+#else
+ * p_stats currently points at fields in the user struct
+ * but not at &u, instead at p_addr. Copy parts of
+#endif /* COMPAT_LINUX_THREADS */
* p_stats; zero the rest of p_stats (statistics).
*/
p2->p_stats = &up->u_stats;
+#ifndef COMPAT_LINUX_THREADS
p2->p_sigacts = &up->u_sigacts;
up->u_sigacts = *p1->p_sigacts;
+#endif /* COMPAT_LINUX_THREADS */
bzero(&up->u_stats.pstat_startzero,
(unsigned) ((caddr_t) &up->u_stats.pstat_endzero -
(caddr_t) &up->u_stats.pstat_startzero));