From 6626c6045c38a22c2dc57621a840ae612da0e2e3 Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Sat, 19 Dec 1998 02:55:34 +0000 Subject: Reviewed by: Luoqi Chen, Jordan Hubbard Submitted by: "Richard Seaman, Jr." 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. --- bin/ps/keyword.c | 4 +- lib/libc/i386/sys/sigsuspend.S | 8 +- sys/alpha/linux/linux.h | 3 +- sys/alpha/linux/linux_dummy.c | 9 +-- sys/alpha/linux/linux_sysvec.c | 23 +++++- sys/alpha/linux/syscalls.master | 4 +- sys/compat/linux/linux_misc.c | 174 +++++++++++++++++++++++++++++++++++++++- sys/i386/linux/linux.h | 3 +- sys/i386/linux/linux_dummy.c | 9 +-- sys/i386/linux/linux_misc.c | 174 +++++++++++++++++++++++++++++++++++++++- sys/i386/linux/linux_proto.h | 5 +- sys/i386/linux/linux_syscall.h | 2 +- sys/i386/linux/linux_sysent.c | 4 +- sys/i386/linux/linux_sysvec.c | 23 +++++- sys/i386/linux/syscalls.master | 4 +- sys/kern/imgact_elf.c | 6 +- sys/kern/init_main.c | 20 ++++- sys/kern/kern_exit.c | 40 ++++++++- sys/kern/kern_fork.c | 24 +++++- sys/kern/kern_sig.c | 76 +++++++++++++++++- sys/sys/proc.h | 41 +++++++++- sys/sys/signalvar.h | 6 +- sys/sys/unistd.h | 5 +- sys/sys/user.h | 9 ++- sys/vm/vm_glue.c | 9 ++- 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 @@ -211,13 +211,6 @@ linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args) return ENOSYS; } -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) { 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 #include #include +#ifdef COMPAT_LINUX_THREADS +#include /* needed, for now, by vm_map.h */ +#include /* needed, for now, for VM_STACK defines */ +#endif /* COMPAT_LINUX_THREADS */ #include #include #include @@ -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 @@ -41,6 +41,9 @@ #include #include #include +#ifdef COMPAT_LINUX_THREADS +#include +#endif /* COMPAT_LINUX_THREADS */ #include #include #include @@ -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 @@ -211,13 +211,6 @@ linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args) return ENOSYS; } -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) { 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 @@ -41,6 +41,9 @@ #include #include #include +#ifdef COMPAT_LINUX_THREADS +#include +#endif /* COMPAT_LINUX_THREADS */ #include #include #include @@ -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 #include #include +#ifdef COMPAT_LINUX_THREADS +#include /* needed, for now, by vm_map.h */ +#include /* needed, for now, for VM_STACK defines */ +#endif /* COMPAT_LINUX_THREADS */ #include #include #include @@ -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 #include +#ifdef COMPAT_LINUX_THREADS +#include + +#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 /* For struct rtprio. */ #include /* For struct selinfo. */ #include +#ifdef COMPAT_LINUX_THREADS +#include +#endif /* COMPAT_LINUX_THREADS */ #ifndef KERNEL #include /* 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)); -- cgit v1.2.3