Implent CLONE_PARENT_SETTID, CLONE_CHILD_CLEARTID, and CLONE_CHILD_SETTID
options to clone(). This makes fork() work on amd64. clone() prototype has changed and the changes is probably revelant on some other arches.
This commit is contained in:
parent
1341f2c732
commit
6593739f61
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_machdep.c,v 1.6 2005/05/22 19:31:15 fvdl Exp $ */
|
||||
/* $NetBSD: linux_machdep.c,v 1.7 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.6 2005/05/22 19:31:15 fvdl Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.7 2005/06/22 15:10:51 manu Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -188,7 +188,8 @@ linux_sendsig(ksi, mask)
|
|||
|
||||
bzero(&sigframe, sizeof(sigframe));
|
||||
if (ps->sa_sigdesc[sig].sd_vers != 0)
|
||||
sigframe.pretcode = (char *)ps->sa_sigdesc[sig].sd_tramp;
|
||||
sigframe.pretcode =
|
||||
(char *)(u_long)ps->sa_sigdesc[sig].sd_tramp;
|
||||
else
|
||||
sigframe.pretcode = NULL;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_syscall.h,v 1.4 2005/05/22 19:29:40 fvdl Exp $ */
|
||||
/* $NetBSD: linux_syscall.h,v 1.5 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*
|
||||
* System call numbers.
|
||||
|
@ -163,7 +163,7 @@
|
|||
/* syscall: "getsockopt" ret: "int" args: "int" "int" "int" "void *" "int *" */
|
||||
#define LINUX_SYS_getsockopt 55
|
||||
|
||||
/* syscall: "clone" ret: "int" args: "int" "void *" */
|
||||
/* syscall: "clone" ret: "int" args: "int" "void *" "void *" "void *" */
|
||||
#define LINUX_SYS_clone 56
|
||||
|
||||
/* syscall: "fork" ret: "int" args: */
|
||||
|
@ -496,6 +496,9 @@
|
|||
/* syscall: "getdents64" ret: "int" args: "int" "struct linux_dirent64 *" "unsigned int" */
|
||||
#define LINUX_SYS_getdents64 217
|
||||
|
||||
/* syscall: "set_tid_address" ret: "int" args: "int *" */
|
||||
#define LINUX_SYS_set_tid_address 218
|
||||
|
||||
/* syscall: "clock_settime" ret: "int" args: "clockid_t" "struct linux_timespec *" */
|
||||
#define LINUX_SYS_clock_settime 227
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_syscallargs.h,v 1.4 2005/05/22 19:29:40 fvdl Exp $ */
|
||||
/* $NetBSD: linux_syscallargs.h,v 1.5 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*
|
||||
* System call argument lists.
|
||||
|
@ -218,6 +218,8 @@ struct linux_sys_getsockopt_args {
|
|||
struct linux_sys_clone_args {
|
||||
syscallarg(int) flags;
|
||||
syscallarg(void *) stack;
|
||||
syscallarg(void *) parent_tidptr;
|
||||
syscallarg(void *) child_tidptr;
|
||||
};
|
||||
|
||||
struct linux_sys_execve_args {
|
||||
|
@ -608,6 +610,10 @@ struct linux_sys_getdents64_args {
|
|||
syscallarg(unsigned int) count;
|
||||
};
|
||||
|
||||
struct linux_sys_set_tid_address_args {
|
||||
syscallarg(int *) tid;
|
||||
};
|
||||
|
||||
struct linux_sys_clock_settime_args {
|
||||
syscallarg(clockid_t) which;
|
||||
syscallarg(struct linux_timespec *) tp;
|
||||
|
@ -964,6 +970,8 @@ int linux_sys_time(struct lwp *, void *, register_t *);
|
|||
|
||||
int linux_sys_getdents64(struct lwp *, void *, register_t *);
|
||||
|
||||
int linux_sys_set_tid_address(struct lwp *, void *, register_t *);
|
||||
|
||||
int linux_sys_clock_settime(struct lwp *, void *, register_t *);
|
||||
|
||||
int linux_sys_clock_gettime(struct lwp *, void *, register_t *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_syscalls.c,v 1.4 2005/05/22 19:29:40 fvdl Exp $ */
|
||||
/* $NetBSD: linux_syscalls.c,v 1.5 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*
|
||||
* System call names.
|
||||
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_syscalls.c,v 1.4 2005/05/22 19:29:40 fvdl Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_syscalls.c,v 1.5 2005/06/22 15:10:51 manu Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#if defined(_KERNEL_OPT)
|
||||
|
@ -248,7 +248,7 @@ const char *const linux_syscallnames[] = {
|
|||
"#215 (unimplemented epoll_wait_old)", /* 215 = unimplemented epoll_wait_old */
|
||||
"#216 (unimplemented remap_file_pages)", /* 216 = unimplemented remap_file_pages */
|
||||
"getdents64", /* 217 = getdents64 */
|
||||
"#218 (unimplemented set_tid_address)", /* 218 = unimplemented set_tid_address */
|
||||
"set_tid_address", /* 218 = set_tid_address */
|
||||
"#219 (unimplemented restart_syscall)", /* 219 = unimplemented restart_syscall */
|
||||
"#220 (unimplemented semtimedop)", /* 220 = unimplemented semtimedop */
|
||||
"#221 (unimplemented fadvise64)", /* 221 = unimplemented fadvise64 */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_sysent.c,v 1.4 2005/05/22 19:29:40 fvdl Exp $ */
|
||||
/* $NetBSD: linux_sysent.c,v 1.5 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*
|
||||
* System call switch table.
|
||||
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_sysent.c,v 1.4 2005/05/22 19:29:40 fvdl Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_sysent.c,v 1.5 2005/06/22 15:10:51 manu Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_compat_43.h"
|
||||
|
@ -142,7 +142,7 @@ struct sysent linux_sysent[] = {
|
|||
linux_sys_setsockopt }, /* 54 = setsockopt */
|
||||
{ 5, s(struct linux_sys_getsockopt_args), 0,
|
||||
linux_sys_getsockopt }, /* 55 = getsockopt */
|
||||
{ 2, s(struct linux_sys_clone_args), 0,
|
||||
{ 4, s(struct linux_sys_clone_args), 0,
|
||||
linux_sys_clone }, /* 56 = clone */
|
||||
{ 0, 0, 0,
|
||||
sys_fork }, /* 57 = fork */
|
||||
|
@ -466,8 +466,8 @@ struct sysent linux_sysent[] = {
|
|||
linux_sys_nosys }, /* 216 = unimplemented remap_file_pages */
|
||||
{ 3, s(struct linux_sys_getdents64_args), 0,
|
||||
linux_sys_getdents64 }, /* 217 = getdents64 */
|
||||
{ 0, 0, 0,
|
||||
linux_sys_nosys }, /* 218 = unimplemented set_tid_address */
|
||||
{ 1, s(struct linux_sys_set_tid_address_args), 0,
|
||||
linux_sys_set_tid_address }, /* 218 = set_tid_address */
|
||||
{ 0, 0, 0,
|
||||
linux_sys_nosys }, /* 219 = unimplemented restart_syscall */
|
||||
{ 0, 0, 0,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$NetBSD: syscalls.master,v 1.4 2005/05/22 19:29:15 fvdl Exp $
|
||||
$NetBSD: syscalls.master,v 1.5 2005/06/22 15:10:51 manu Exp $
|
||||
|
||||
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
|
||||
|
||||
|
@ -153,7 +153,8 @@
|
|||
int optname, void *optval, int optlen); }
|
||||
55 STD { int linux_sys_getsockopt(int s, int level, \
|
||||
int optname, void *optval, int *optlen); }
|
||||
56 STD { int linux_sys_clone(int flags, void *stack); }
|
||||
56 STD { int linux_sys_clone(int flags, void *stack, \
|
||||
void *parent_tidptr, void *child_tidptr); }
|
||||
57 NOARGS { int sys_fork(void); }
|
||||
58 NOARGS { int sys___vfork14(void); }
|
||||
59 STD { int linux_sys_execve(const char *path, char **argp, \
|
||||
|
@ -365,7 +366,7 @@
|
|||
216 UNIMPL remap_file_pages
|
||||
217 STD { int linux_sys_getdents64(int fd, \
|
||||
struct linux_dirent64 *dent, unsigned int count); }
|
||||
218 UNIMPL set_tid_address
|
||||
218 STD { int linux_sys_set_tid_address(int *tid); }
|
||||
219 UNIMPL restart_syscall
|
||||
220 UNIMPL semtimedop
|
||||
221 UNIMPL fadvise64
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_emuldata.h,v 1.7 2005/02/26 23:10:19 perry Exp $ */
|
||||
/* $NetBSD: linux_emuldata.h,v 1.8 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998,2002 The NetBSD Foundation, Inc.
|
||||
|
@ -48,6 +48,7 @@
|
|||
struct linux_emuldata_shared {
|
||||
caddr_t p_break; /* Processes' idea of break */
|
||||
int refs;
|
||||
pid_t group_pid; /* PID of Linux process (group of threads) */
|
||||
};
|
||||
|
||||
struct linux_emuldata {
|
||||
|
@ -57,6 +58,10 @@ struct linux_emuldata {
|
|||
int debugreg[8]; /* GDB information for ptrace - for use, */
|
||||
/* see ../arch/i386/linux_ptrace.c */
|
||||
struct linux_emuldata_shared *s;
|
||||
int *child_set_tid; /* in clone(): Child's TID to set on clone */
|
||||
int *child_clear_tid; /* in clone(): Child's TID to clear on exit */
|
||||
int *set_tid; /* in clone(): Own TID to set on clone */
|
||||
int *clear_tid; /* Own TID to clear on exit */
|
||||
};
|
||||
|
||||
#endif /* !_COMMON_LINUX_EMULDATA_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_exec.c,v 1.76 2005/06/02 16:54:52 tsutsui Exp $ */
|
||||
/* $NetBSD: linux_exec.c,v 1.77 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994, 1995, 1998, 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -38,7 +38,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.76 2005/06/02 16:54:52 tsutsui Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.77 2005/06/22 15:10:51 manu Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -81,6 +81,8 @@ static void linux_e_proc_fork __P((struct proc *, struct proc *, int));
|
|||
static void linux_e_proc_exit __P((struct proc *));
|
||||
static void linux_e_proc_init __P((struct proc *, struct proc *, int));
|
||||
|
||||
static void linux_userret_settid __P((struct lwp *, void *));
|
||||
|
||||
/*
|
||||
* Execve(2). Just check the alternate emulation path, and pass it on
|
||||
* to the NetBSD execve().
|
||||
|
@ -159,6 +161,7 @@ linux_e_proc_init(p, parent, forkflags)
|
|||
{
|
||||
struct linux_emuldata *e = p->p_emuldata;
|
||||
struct linux_emuldata_shared *s;
|
||||
struct linux_emuldata *ep = NULL;
|
||||
|
||||
if (!e) {
|
||||
/* allocate new Linux emuldata */
|
||||
|
@ -172,9 +175,17 @@ linux_e_proc_init(p, parent, forkflags)
|
|||
|
||||
memset(e, '\0', sizeof(struct linux_emuldata));
|
||||
|
||||
if (parent)
|
||||
ep = parent->p_emuldata;
|
||||
|
||||
if (forkflags & FORK_SHAREVM) {
|
||||
struct linux_emuldata *e2 = parent->p_emuldata;
|
||||
s = e2->s;
|
||||
#ifdef DIAGNOSTIC
|
||||
if (ep == NULL) {
|
||||
killproc(p, "FORK_SHAREVM while emuldata is NULL\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
s = ep->s;
|
||||
s->refs++;
|
||||
} else {
|
||||
struct vmspace *vm;
|
||||
|
@ -193,9 +204,33 @@ linux_e_proc_init(p, parent, forkflags)
|
|||
vm = (parent) ? parent->p_vmspace : p->p_vmspace;
|
||||
s->p_break = vm->vm_daddr + ctob(vm->vm_dsize);
|
||||
|
||||
/*
|
||||
* Linux threads are emulated as NetBSD processes (not lwp)
|
||||
* We use native PID for Linux TID. The Linux TID is the
|
||||
* PID of the first process in the group. It is stored
|
||||
* here
|
||||
*/
|
||||
s->group_pid = p->p_pid;
|
||||
}
|
||||
|
||||
e->s = s;
|
||||
|
||||
/*
|
||||
* initialize TID pointers. ep->child_clear_tid and
|
||||
* ep->child_set_tid will not be used beyond this point.
|
||||
*/
|
||||
e->child_clear_tid = NULL;
|
||||
e->child_set_tid = NULL;
|
||||
if (ep != NULL) {
|
||||
e->clear_tid = ep->child_clear_tid;
|
||||
e->set_tid = ep->child_set_tid;
|
||||
ep->child_clear_tid = NULL;
|
||||
ep->child_set_tid = NULL;
|
||||
} else {
|
||||
e->clear_tid = NULL;
|
||||
e->set_tid = NULL;
|
||||
}
|
||||
|
||||
p->p_emuldata = e;
|
||||
}
|
||||
|
||||
|
@ -222,6 +257,23 @@ linux_e_proc_exit(p)
|
|||
{
|
||||
struct linux_emuldata *e = p->p_emuldata;
|
||||
|
||||
/* Emulate LINUX_CLONE_CHILD_CLEARTID */
|
||||
if (e->clear_tid != NULL) {
|
||||
int error;
|
||||
int null = 0;
|
||||
|
||||
if ((error = copyout(&null,
|
||||
e->clear_tid,
|
||||
sizeof(null))) != 0)
|
||||
printf("linux_e_proc_exit: cannot clear TID\n");
|
||||
|
||||
#ifdef notyet /* Not yet implemented */
|
||||
if ((error = linux_sys_futex(e->clear_tid,
|
||||
LINUX_FUTEX_WAKE, 1, NULL, NULL, 0)) != 0)
|
||||
printf("linux_e_proc_exit: linux_sys_futex failed\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* free Linux emuldata and set the pointer to null */
|
||||
e->s->refs--;
|
||||
if (e->s->refs == 0)
|
||||
|
@ -238,6 +290,8 @@ linux_e_proc_fork(p, parent, forkflags)
|
|||
struct proc *p, *parent;
|
||||
int forkflags;
|
||||
{
|
||||
struct linux_emuldata *e;
|
||||
|
||||
/*
|
||||
* The new process might share some vmspace-related stuff
|
||||
* with parent, depending on fork flags (CLONE_VM et.al).
|
||||
|
@ -246,4 +300,36 @@ linux_e_proc_fork(p, parent, forkflags)
|
|||
*/
|
||||
p->p_emuldata = NULL;
|
||||
linux_e_proc_init(p, parent, forkflags);
|
||||
|
||||
/*
|
||||
* Emulate LINUX_CLONE_CHILD_SETTID: This cannot be done
|
||||
* right now because the child VM is not set up. We will
|
||||
* do it at userret time.
|
||||
*/
|
||||
e = p->p_emuldata;
|
||||
if (e->set_tid != NULL)
|
||||
p->p_userret = (*linux_userret_settid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
linux_userret_settid(l, arg)
|
||||
struct lwp *l;
|
||||
void *arg;
|
||||
{
|
||||
struct proc *p = l->l_proc;
|
||||
struct linux_emuldata *led = p->p_emuldata;
|
||||
int error;
|
||||
|
||||
p->p_userret = NULL;
|
||||
|
||||
/* Emulate LINUX_CLONE_CHILD_SETTID */
|
||||
if (led->set_tid != NULL) {
|
||||
if ((error = copyout(&p->p_pid,
|
||||
led->set_tid, sizeof(p->p_pid))) != 0)
|
||||
printf("linux_userret_settid: cannot set TID\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_sched.c,v 1.18 2004/09/10 22:22:20 wiz Exp $ */
|
||||
/* $NetBSD: linux_sched.c,v 1.19 2005/06/22 15:10:51 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.18 2004/09/10 22:22:20 wiz Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.19 2005/06/22 15:10:51 manu Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
|
@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.18 2004/09/10 22:22:20 wiz Exp $")
|
|||
|
||||
#include <compat/linux/common/linux_types.h>
|
||||
#include <compat/linux/common/linux_signal.h>
|
||||
#include <compat/linux/common/linux_emuldata.h>
|
||||
|
||||
#include <compat/linux/linux_syscallargs.h>
|
||||
|
||||
|
@ -70,8 +71,16 @@ linux_sys_clone(l, v, retval)
|
|||
struct linux_sys_clone_args /* {
|
||||
syscallarg(int) flags;
|
||||
syscallarg(void *) stack;
|
||||
#ifdef __amd64__
|
||||
syscallarg(void *) parent_tidptr;
|
||||
syscallarg(void *) child_tidptr;
|
||||
#endif
|
||||
} */ *uap = v;
|
||||
int flags, sig;
|
||||
int error;
|
||||
#ifdef __amd64__
|
||||
struct linux_emuldata *led;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We don't support the Linux CLONE_PID or CLONE_PTRACE flags.
|
||||
|
@ -108,14 +117,44 @@ linux_sys_clone(l, v, retval)
|
|||
return (EINVAL);
|
||||
sig = linux_to_native_signo[sig];
|
||||
|
||||
#ifdef __amd64__
|
||||
led = (struct linux_emuldata *)l->l_proc->p_emuldata;
|
||||
|
||||
if (SCARG(uap, flags) & LINUX_CLONE_PARENT_SETTID) {
|
||||
if (SCARG(uap, parent_tidptr) == NULL) {
|
||||
printf("linux_sys_clone: NULL parent_tidptr\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((error = copyout(&l->l_proc->p_pid,
|
||||
SCARG(uap, parent_tidptr),
|
||||
sizeof(l->l_proc->p_pid))) != 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* CLONE_CHILD_CLEARTID: TID clear in the child on exit() */
|
||||
if (SCARG(uap, flags) & LINUX_CLONE_CHILD_CLEARTID)
|
||||
led->child_clear_tid = SCARG(uap, child_tidptr);
|
||||
else
|
||||
led->child_clear_tid = NULL;
|
||||
|
||||
/* CLONE_CHILD_SETTID: TID set in the child on clone() */
|
||||
if (SCARG(uap, flags) & LINUX_CLONE_CHILD_SETTID)
|
||||
led->child_set_tid = SCARG(uap, child_tidptr);
|
||||
else
|
||||
led->child_set_tid = NULL;
|
||||
#endif
|
||||
/*
|
||||
* Note that Linux does not provide a portable way of specifying
|
||||
* the stack area; the caller must know if the stack grows up
|
||||
* or down. So, we pass a stack size of 0, so that the code
|
||||
* that makes this adjustment is a noop.
|
||||
*/
|
||||
return (fork1(l, flags, sig, SCARG(uap, stack), 0,
|
||||
NULL, NULL, retval, NULL));
|
||||
if ((error = fork1(l, flags, sig, SCARG(uap, stack), 0,
|
||||
NULL, NULL, retval, NULL)) != 0)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -367,3 +406,24 @@ linux_sys_exit_group(l, v, retval)
|
|||
return 0;
|
||||
}
|
||||
#endif /* !__m68k__ */
|
||||
|
||||
#ifdef __amd64__
|
||||
int
|
||||
linux_sys_set_tid_address(l, v, retval)
|
||||
struct lwp *l;
|
||||
void *v;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_sys_set_tid_address_args /* {
|
||||
syscallarg(int *) tidptr;
|
||||
} */ *uap = v;
|
||||
struct linux_emuldata *led;
|
||||
|
||||
led = (struct linux_emuldata *)l->l_proc->p_emuldata;
|
||||
led->clear_tid = SCARG(uap, tid);
|
||||
|
||||
*retval = l->l_proc->p_pid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* __amd64__ */
|
||||
|
|
Loading…
Reference in New Issue