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.
This commit is contained in:
parent
02489dd737
commit
6626c6045c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41931
@ -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"},
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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))
|
||||
|
@ -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 *)];
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 @@ wait1(q, uap, compat)
|
||||
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 @@ wait1(q, uap, compat)
|
||||
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 */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 @@ fork1(p1, flags)
|
||||
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)
|
||||
|
@ -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
|
||||
|
@ -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 *));
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user