summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_thr.c
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2015-07-17 22:26:45 +0000
committered <ed@FreeBSD.org>2015-07-17 22:26:45 +0000
commit79b276d8ba0543d918bc771672aeb0f8dc95a2c6 (patch)
tree69e72957e7d6db2cc8db15aae394db829449c0d6 /sys/kern/kern_thr.c
parentb6b17c200ad933a8f599b463810193a91d039d9c (diff)
downloadFreeBSD-src-79b276d8ba0543d918bc771672aeb0f8dc95a2c6.zip
FreeBSD-src-79b276d8ba0543d918bc771672aeb0f8dc95a2c6.tar.gz
Undo r285656.
It turns out that the CDDL sources already introduce a function called thread_create(). I'll investigate what we can do to make these functions coexist. Reported by: Ivan Klymenko
Diffstat (limited to 'sys/kern/kern_thr.c')
-rw-r--r--sys/kern/kern_thr.c125
1 files changed, 64 insertions, 61 deletions
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 9e878d8..7e7b88f 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -89,39 +89,29 @@ suword_lwpid(void *addr, lwpid_t lwpid)
#define suword_lwpid suword
#endif
+static int create_thread(struct thread *td, mcontext_t *ctx,
+ void (*start_func)(void *), void *arg,
+ char *stack_base, size_t stack_size,
+ char *tls_base,
+ long *child_tid, long *parent_tid,
+ int flags, struct rtprio *rtp);
+
/*
* System call interface.
*/
-
-struct thr_create_initthr_args {
- ucontext_t ctx;
- long *tid;
-};
-
-static int
-thr_create_initthr(struct thread *td, void *thunk)
-{
- struct thr_create_initthr_args *args;
-
- /* Copy out the child tid. */
- args = thunk;
- if (args->tid != NULL && suword_lwpid(args->tid, td->td_tid))
- return (EFAULT);
-
- return (set_mcontext(td, &args->ctx.uc_mcontext));
-}
-
int
sys_thr_create(struct thread *td, struct thr_create_args *uap)
/* ucontext_t *ctx, long *id, int flags */
{
- struct thr_create_initthr_args args;
+ ucontext_t ctx;
int error;
- if ((error = copyin(uap->ctx, &args.ctx, sizeof(args.ctx))))
+ if ((error = copyin(uap->ctx, &ctx, sizeof(ctx))))
return (error);
- args.tid = uap->id;
- return (thread_create(td, NULL, thr_create_initthr, &args));
+
+ error = create_thread(td, &ctx.uc_mcontext, NULL, NULL,
+ NULL, 0, NULL, uap->id, NULL, uap->flags, NULL);
+ return (error);
}
int
@@ -139,35 +129,6 @@ sys_thr_new(struct thread *td, struct thr_new_args *uap)
return (kern_thr_new(td, &param));
}
-static int
-thr_new_initthr(struct thread *td, void *thunk)
-{
- stack_t stack;
- struct thr_param *param;
-
- /*
- * Here we copy out tid to two places, one for child and one
- * for parent, because pthread can create a detached thread,
- * if parent wants to safely access child tid, it has to provide
- * its storage, because child thread may exit quickly and
- * memory is freed before parent thread can access it.
- */
- param = thunk;
- if ((param->child_tid != NULL &&
- suword_lwpid(param->child_tid, td->td_tid)) ||
- (param->parent_tid != NULL &&
- suword_lwpid(param->parent_tid, td->td_tid)))
- return (EFAULT);
-
- /* Set up our machine context. */
- stack.ss_sp = param->stack_base;
- stack.ss_size = param->stack_size;
- /* Set upcall address to user thread entry function. */
- cpu_set_upcall_kse(td, param->start_func, param->arg, &stack);
- /* Setup user TLS address and TLS pointer register. */
- return (cpu_set_user_tls(td, param->tls_base));
-}
-
int
kern_thr_new(struct thread *td, struct thr_param *param)
{
@@ -181,13 +142,22 @@ kern_thr_new(struct thread *td, struct thr_param *param)
return (error);
rtpp = &rtp;
}
- return (thread_create(td, rtpp, thr_new_initthr, param));
+ error = create_thread(td, NULL, param->start_func, param->arg,
+ param->stack_base, param->stack_size, param->tls_base,
+ param->child_tid, param->parent_tid, param->flags,
+ rtpp);
+ return (error);
}
-int
-thread_create(struct thread *td, struct rtprio *rtp,
- int (*initialize_thread)(struct thread *, void *), void *thunk)
+static int
+create_thread(struct thread *td, mcontext_t *ctx,
+ void (*start_func)(void *), void *arg,
+ char *stack_base, size_t stack_size,
+ char *tls_base,
+ long *child_tid, long *parent_tid,
+ int flags, struct rtprio *rtp)
{
+ stack_t stack;
struct thread *newtd;
struct proc *p;
int error;
@@ -229,6 +199,24 @@ thread_create(struct thread *td, struct rtprio *rtp,
cpu_set_upcall(newtd, td);
+ /*
+ * Try the copyout as soon as we allocate the td so we don't
+ * have to tear things down in a failure case below.
+ * Here we copy out tid to two places, one for child and one
+ * for parent, because pthread can create a detached thread,
+ * if parent wants to safely access child tid, it has to provide
+ * its storage, because child thread may exit quickly and
+ * memory is freed before parent thread can access it.
+ */
+ if ((child_tid != NULL &&
+ suword_lwpid(child_tid, newtd->td_tid)) ||
+ (parent_tid != NULL &&
+ suword_lwpid(parent_tid, newtd->td_tid))) {
+ thread_free(newtd);
+ error = EFAULT;
+ goto fail;
+ }
+
bzero(&newtd->td_startzero,
__rangeof(struct thread, td_startzero, td_endzero));
bcopy(&td->td_startcopy, &newtd->td_startcopy,
@@ -236,11 +224,26 @@ thread_create(struct thread *td, struct rtprio *rtp,
newtd->td_proc = td->td_proc;
thread_cow_get(newtd, td);
- error = initialize_thread(newtd, thunk);
- if (error != 0) {
- thread_cow_free(newtd);
- thread_free(newtd);
- goto fail;
+ if (ctx != NULL) { /* old way to set user context */
+ error = set_mcontext(newtd, ctx);
+ if (error != 0) {
+ thread_cow_free(newtd);
+ thread_free(newtd);
+ goto fail;
+ }
+ } else {
+ /* Set up our machine context. */
+ stack.ss_sp = stack_base;
+ stack.ss_size = stack_size;
+ /* Set upcall address to user thread entry function. */
+ cpu_set_upcall_kse(newtd, start_func, arg, &stack);
+ /* Setup user TLS address and TLS pointer register. */
+ error = cpu_set_user_tls(newtd, tls_base);
+ if (error != 0) {
+ thread_cow_free(newtd);
+ thread_free(newtd);
+ goto fail;
+ }
}
PROC_LOCK(p);
OpenPOWER on IntegriCloud