diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-09-22 15:04:28 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-09-22 15:04:28 +0000 |
commit | a2dd6344c030d244faa26914eef8b07174d8d17a (patch) | |
tree | 7d2bb2f3f83c1c91a2809fed7db73be3c84171ce /sys/kern/kern_thr.c | |
parent | 04676f904a987e62b1967615a3e4ded7d310562b (diff) | |
download | FreeBSD-src-a2dd6344c030d244faa26914eef8b07174d8d17a.zip FreeBSD-src-a2dd6344c030d244faa26914eef8b07174d8d17a.tar.gz |
Add compatible code to let 32bit libthr work on 64bit kernel.
Diffstat (limited to 'sys/kern/kern_thr.c')
-rw-r--r-- | sys/kern/kern_thr.c | 89 |
1 files changed, 64 insertions, 25 deletions
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index 5624d9d..7b65fbb 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -27,6 +27,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_posix.h" #include <sys/param.h> #include <sys/kernel.h> @@ -51,6 +52,26 @@ __FBSDID("$FreeBSD$"); #include <machine/frame.h> +#ifdef COMPAT_IA32 + +extern struct sysentvec ia32_freebsd_sysvec; + +static inline int +suword_lwpid(void *addr, lwpid_t lwpid) +{ + int error; + + if (curproc->p_sysent != &ia32_freebsd_sysvec) + error = suword(addr, lwpid); + else + error = suword32(addr, lwpid); + return (error); +} + +#else +#define suword_lwpid suword +#endif + extern int max_threads_per_proc; static int create_thread(struct thread *td, mcontext_t *ctx, @@ -83,22 +104,30 @@ thr_new(struct thread *td, struct thr_new_args *uap) /* struct thr_param * */ { struct thr_param param; - struct rtprio rtp, *rtpp; int error; - if (uap->param_size < sizeof(param)) + if (uap->param_size < 0 || uap->param_size > sizeof(param)) return (EINVAL); bzero(¶m, sizeof(param)); - if ((error = copyin(uap->param, ¶m, sizeof(param)))) + if ((error = copyin(uap->param, ¶m, uap->param_size))) return (error); + return (kern_thr_new(td, ¶m)); +} + +int +kern_thr_new(struct thread *td, struct thr_param *param) +{ + struct rtprio rtp, *rtpp; + int error; + rtpp = NULL; - if (param.rtp != 0) { - error = copyin(param.rtp, &rtp, sizeof(struct rtprio)); + if (param->rtp != 0) { + error = copyin(param->rtp, &rtp, sizeof(struct rtprio)); 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, + 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); } @@ -158,12 +187,13 @@ create_thread(struct thread *td, mcontext_t *ctx, */ id = newtd->td_tid; if ((child_tid != NULL && - (error = copyout(&id, child_tid, sizeof(long)))) || + suword_lwpid(child_tid, newtd->td_tid)) || (parent_tid != NULL && - (error = copyout(&id, parent_tid, sizeof(long))))) { - thread_free(newtd); - return (error); + suword_lwpid(parent_tid, newtd->td_tid))) { + thread_free(newtd); + return (EFAULT); } + bzero(&newtd->td_startzero, __rangeof(struct thread, td_startzero, td_endzero)); bcopy(&td->td_startcopy, &newtd->td_startcopy, @@ -231,13 +261,11 @@ int thr_self(struct thread *td, struct thr_self_args *uap) /* long *id */ { - long id; int error; - id = td->td_tid; - if ((error = copyout(&id, uap->id, sizeof(long)))) - return (error); - + error = suword_lwpid(uap->id, (unsigned)td->td_tid); + if (error == -1) + return (EFAULT); return (0); } @@ -251,7 +279,7 @@ thr_exit(struct thread *td, struct thr_exit_args *uap) /* Signal userland that it can free the stack. */ if ((void *)uap->state != NULL) { - suword((void *)uap->state, 1); + suword_lwpid(uap->state, 1); kern_umtx_wake(td, uap->state, INT_MAX); } @@ -320,23 +348,34 @@ int thr_suspend(struct thread *td, struct thr_suspend_args *uap) /* const struct timespec *timeout */ { - struct timespec ts; - struct timeval tv; + struct timespec ts, *tsp; int error; - int hz; - hz = 0; error = 0; + tsp = NULL; if (uap->timeout != NULL) { error = copyin((const void *)uap->timeout, (void *)&ts, sizeof(struct timespec)); if (error != 0) return (error); - if (ts.tv_nsec < 0 || ts.tv_nsec > 1000000000) + tsp = &ts; + } + + return (kern_thr_suspend(td, tsp)); +} + +int +kern_thr_suspend(struct thread *td, struct timespec *tsp) +{ + struct timeval tv; + int error = 0, hz = 0; + + if (tsp != NULL) { + if (tsp->tv_nsec < 0 || tsp->tv_nsec > 1000000000) return (EINVAL); - if (ts.tv_sec == 0 && ts.tv_nsec == 0) + if (tsp->tv_sec == 0 && tsp->tv_nsec == 0) return (ETIMEDOUT); - TIMESPEC_TO_TIMEVAL(&tv, &ts); + TIMESPEC_TO_TIMEVAL(&tv, tsp); hz = tvtohz(&tv); } PROC_LOCK(td->td_proc); |