summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2011-10-15 23:35:30 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2011-10-15 23:35:30 +0000
commit67874eb615d7ff9c8ac1f262fa286e41e2e0e32f (patch)
treea4438f1bc677ce643f078f2bfaef615b6264844d /sys/kern
parentae0a9206a9212a9f09180c0e6c63b4973377fc50 (diff)
"TLS-lite": add kernel support for a per-thread userspace pointer,
for pointing to the thread-control-block. Support for mapping this to the correct hardware register can be added as it's finished; start with support for amd64, sparc, and sparc64. Includes syscalls for getting and setting it (for a portable __errno implementation) as well as creating a new thread with an initial value for it. discussed with miod@, kettenis@, deraadt@; committing to get the syscalls in with the impending libc bump and do further refinements in tree
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_fork.c55
-rw-r--r--sys/kern/kern_prot.c30
-rw-r--r--sys/kern/syscalls.master5
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), &param, 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); }