diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_fork.c | 55 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 30 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 5 |
3 files changed, 85 insertions, 5 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 59334cfdd03..39c2249638b 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.128 2011/07/07 18:00:33 guenther Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.129 2011/10/15 23:35:29 guenther Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -65,12 +65,17 @@ #include <uvm/uvm_extern.h> #include <uvm/uvm_map.h> +#ifdef __HAVE_MD_TCB +# include <machine/tcb.h> +#endif + int nprocs = 1; /* process 0 */ int randompid; /* when set to 1, pid's go random */ pid_t lastpid; struct forkstat forkstat; void fork_return(void *); +void tfork_child_return(void *); int pidtaken(pid_t); void process_new(struct proc *, struct proc *); @@ -148,6 +153,39 @@ sys_rfork(struct proc *p, void *v, register_t *retval) return (fork1(p, SIGCHLD, flags, NULL, 0, NULL, NULL, retval, NULL)); } +int +sys___tfork(struct proc *p, void *v, register_t *retval) +{ + struct sys___tfork_args /* { + syscallarg(struct __tfork) *param; + } */ *uap = v; + struct __tfork param; + int flags; + int error; + + if ((error = copyin(SCARG(uap, param), ¶m, sizeof(param)))) + return (error); + + /* XXX will supersede rfork at some point... */ + if (param.tf_flags != 0) + return (EINVAL); + + flags = FORK_TFORK | FORK_THREAD | FORK_SIGHAND | FORK_SHAREVM + | FORK_NOZOMBIE | FORK_SHAREFILES; + + return (fork1(p, 0, flags, NULL, param.tf_tid, tfork_child_return, + param.tf_tcb, retval, NULL)); +} + +void +tfork_child_return(void *arg) +{ + struct proc *p = curproc; + + TCB_SET(p, arg); + child_return(p); +} + /* * Allocate and initialize a new process. */ @@ -196,7 +234,7 @@ process_new(struct proc *newproc, struct proc *parentproc) struct timeval fork_tfmrate = { 10, 0 }; int -fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, +fork1(struct proc *p1, int exitsig, int flags, void *stack, pid_t *tidptr, void (*func)(void *), void *arg, register_t *retval, struct proc **rnewprocp) { @@ -364,7 +402,7 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, * different path later. */ uvm_fork(p1, p2, ((flags & FORK_SHAREVM) ? TRUE : FALSE), stack, - stacksize, func ? func : child_return, arg ? arg : p2); + 0, func ? func : child_return, arg ? arg : p2); timeout_set(&p2->p_stats->p_virt_to, virttimer_trampoline, p2); timeout_set(&p2->p_stats->p_prof_to, proftimer_trampoline, p2); @@ -377,6 +415,10 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, } else if (flags & FORK_VFORK) { forkstat.cntvfork++; forkstat.sizvfork += vm->vm_dsize + vm->vm_ssize; +#if 0 + } else if (flags & FORK_TFORK) { + forkstat.cnttfork++; +#endif } else if (flags & FORK_RFORK) { forkstat.cntrfork++; forkstat.sizrfork += vm->vm_dsize + vm->vm_ssize; @@ -425,6 +467,13 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, systrace_fork(p1, p2, newstrp); #endif + if (tidptr != NULL) { + pid_t pid = p2->p_pid + THREAD_PID_OFFSET; + + if (copyout(&pid, tidptr, sizeof(pid))) + psignal(p1, SIGSEGV); + } + /* * Make child runnable, set start time, and add to run queue. */ diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 1a0f724db41..e936e44970e 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_prot.c,v 1.50 2011/07/25 20:32:06 tedu Exp $ */ +/* $OpenBSD: kern_prot.c,v 1.51 2011/10/15 23:35:29 guenther Exp $ */ /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ /* @@ -54,6 +54,10 @@ #include <sys/mount.h> #include <sys/syscallargs.h> +#ifdef __HAVE_MD_TCB +# include <machine/tcb.h> +#endif + /* ARGSUSED */ int sys_getpid(struct proc *p, void *v, register_t *retval) @@ -890,3 +894,27 @@ proc_cansugid(struct proc *p) /* Allow. */ return (1); } + +/* + * Set address of the proc's thread-control-block + */ +int +sys___set_tcb(struct proc *p, void *v, register_t *retval) +{ + struct sys___set_tcb_args /* { + syscallarg(void *) tcb; + } */ *uap = v; + + TCB_SET(p, SCARG(uap, tcb)); + return (0); +} + +/* + * Get address of the proc's thread-control-block + */ +int +sys___get_tcb(struct proc *p, void *v, register_t *retval) +{ + *retval = (register_t)TCB_GET(p); + return (0); +} diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index cd4a7899bcb..c8011d97d42 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ -; $OpenBSD: syscalls.master,v 1.118 2011/07/18 00:16:54 matthew Exp $ +; $OpenBSD: syscalls.master,v 1.119 2011/10/15 23:35:29 guenther Exp $ ; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -574,3 +574,6 @@ const struct timespec *times, int flag); } 327 STD { int sys_futimens(int fd, \ const struct timespec *times); } +328 STD { int sys___tfork(struct __tfork *param); } +329 STD NOLOCK { void sys___set_tcb(void *tcb); } +330 STD NOLOCK { void *sys___get_tcb(void); } |