From owner-svn-src-all@freebsd.org Mon Jul 20 10:20:06 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 945699A515D; Mon, 20 Jul 2015 10:20:06 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6CD012D70; Mon, 20 Jul 2015 10:20:06 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t6KAK6uH092825; Mon, 20 Jul 2015 10:20:06 GMT (envelope-from ed@FreeBSD.org) Received: (from ed@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t6KAK5St092822; Mon, 20 Jul 2015 10:20:05 GMT (envelope-from ed@FreeBSD.org) Message-Id: <201507201020.t6KAK5St092822@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ed set sender to ed@FreeBSD.org using -f From: Ed Schouten Date: Mon, 20 Jul 2015 10:20:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r285715 - in head/sys: cddl/compat/opensolaris/sys kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Jul 2015 10:20:06 -0000 Author: ed Date: Mon Jul 20 10:20:04 2015 New Revision: 285715 URL: https://svnweb.freebsd.org/changeset/base/285715 Log: Add an API for easily creating userspace threads in kernelspace. This change refactors the existing create_thread() function to be more generic. It replaces almost all of its arguments by a callback that can be used to extract the thread ID and copy it out to the right place, but also to perform additional initialization steps, such as setting the trapframe. This also makes the difference between thr_new() and thr_create() more clear in my opinion. This function is going to be used by the CloudABI compatibility layer. It looks like the OpenSolaris compatibility framework already provides a function called thread_create(). Rename this function to do_thread_create() and use a macro to deal with the namespacing conflict. A similar approach is already used for thread_exit(). MFC after: 1 month Modified: head/sys/cddl/compat/opensolaris/sys/proc.h head/sys/kern/kern_thr.c head/sys/sys/proc.h Modified: head/sys/cddl/compat/opensolaris/sys/proc.h ============================================================================== --- head/sys/cddl/compat/opensolaris/sys/proc.h Mon Jul 20 09:37:42 2015 (r285714) +++ head/sys/cddl/compat/opensolaris/sys/proc.h Mon Jul 20 10:20:04 2015 (r285715) @@ -63,7 +63,7 @@ typedef struct proc proc_t; extern struct proc *zfsproc; static __inline kthread_t * -thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg, +do_thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg, size_t len, proc_t *pp, int state, pri_t pri) { kthread_t *td = NULL; @@ -88,6 +88,8 @@ thread_create(caddr_t stk, size_t stksiz return (td); } +#define thread_create(stk, stksize, proc, arg, len, pp, state, pri) \ + do_thread_create(stk, stksize, proc, arg, len, pp, state, pri) #define thread_exit() kthread_exit() #endif /* _KERNEL */ Modified: head/sys/kern/kern_thr.c ============================================================================== --- head/sys/kern/kern_thr.c Mon Jul 20 09:37:42 2015 (r285714) +++ head/sys/kern/kern_thr.c Mon Jul 20 10:20:04 2015 (r285715) @@ -89,29 +89,39 @@ 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 */ { - ucontext_t ctx; + struct thr_create_initthr_args args; int error; - if ((error = copyin(uap->ctx, &ctx, sizeof(ctx)))) + if ((error = copyin(uap->ctx, &args.ctx, sizeof(args.ctx)))) return (error); - - error = create_thread(td, &ctx.uc_mcontext, NULL, NULL, - NULL, 0, NULL, uap->id, NULL, uap->flags, NULL); - return (error); + args.tid = uap->id; + return (thread_create(td, NULL, thr_create_initthr, &args)); } int @@ -129,6 +139,35 @@ sys_thr_new(struct thread *td, struct th return (kern_thr_new(td, ¶m)); } +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) { @@ -142,22 +181,13 @@ kern_thr_new(struct thread *td, struct t return (error); rtpp = &rtp; } - 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); + return (thread_create(td, rtpp, thr_new_initthr, param)); } -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) +int +thread_create(struct thread *td, struct rtprio *rtp, + int (*initialize_thread)(struct thread *, void *), void *thunk) { - stack_t stack; struct thread *newtd; struct proc *p; int error; @@ -199,24 +229,6 @@ create_thread(struct thread *td, mcontex 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, @@ -224,26 +236,11 @@ create_thread(struct thread *td, mcontex newtd->td_proc = td->td_proc; thread_cow_get(newtd, td); - 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; - } + error = initialize_thread(newtd, thunk); + if (error != 0) { + thread_cow_free(newtd); + thread_free(newtd); + goto fail; } PROC_LOCK(p); Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Mon Jul 20 09:37:42 2015 (r285714) +++ head/sys/sys/proc.h Mon Jul 20 10:20:04 2015 (r285715) @@ -992,6 +992,8 @@ void thread_cow_get_proc(struct thread * void thread_cow_get(struct thread *newtd, struct thread *td); void thread_cow_free(struct thread *td); void thread_cow_update(struct thread *td); +int thread_create(struct thread *td, struct rtprio *rtp, + int (*initialize_thread)(struct thread *, void *), void *thunk); void thread_exit(void) __dead2; void thread_free(struct thread *td); void thread_link(struct thread *td, struct proc *p);