Add compatible code to let 32bit libthr work on 64bit kernel.

This commit is contained in:
David Xu 2006-09-22 15:04:28 +00:00
parent e58b17ea53
commit cda9a0d1c2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162551
5 changed files with 146 additions and 32 deletions

View File

@ -103,4 +103,18 @@ struct statfs32 {
int32_t f_spare[2];
};
struct thr_param32 {
uint32_t start_func;
uint32_t arg;
uint32_t stack_base;
uint32_t stack_size;
uint32_t tls_base;
uint32_t tls_size;
uint32_t child_tid;
uint32_t parent_tid;
int32_t flags;
uint32_t rtp;
uint32_t spare[3];
};
#endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */

View File

@ -67,7 +67,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/thr.h>
#include <sys/unistd.h>
#include <sys/ucontext.h>
#include <sys/vnode.h>
#include <sys/wait.h>
#include <sys/ipc.h>
@ -2121,6 +2123,60 @@ freebsd32_clock_getres(struct thread *td,
return (error);
}
int
freebsd32_thr_new(struct thread *td,
struct freebsd32_thr_new_args *uap)
{
struct thr_param32 param32;
struct thr_param param;
int error;
if (uap->param_size < 0 ||
uap->param_size > sizeof(struct thr_param32))
return (EINVAL);
bzero(&param, sizeof(struct thr_param));
bzero(&param32, sizeof(struct thr_param32));
error = copyin(uap->param, &param32, uap->param_size);
if (error != 0)
return (error);
param.start_func = PTRIN(param32.start_func);
param.arg = PTRIN(param32.arg);
param.stack_base = PTRIN(param32.stack_base);
param.stack_size = param32.stack_size;
param.tls_base = PTRIN(param32.tls_base);
param.tls_size = param32.tls_size;
param.child_tid = PTRIN(param32.child_tid);
param.parent_tid = PTRIN(param32.parent_tid);
param.flags = param32.flags;
param.rtp = PTRIN(param32.rtp);
param.spare[0] = PTRIN(param32.spare[0]);
param.spare[1] = PTRIN(param32.spare[1]);
param.spare[2] = PTRIN(param32.spare[2]);
return (kern_thr_new(td, &param));
}
int
freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
{
struct timespec32 ts32;
struct timespec ts, *tsp;
int error;
error = 0;
tsp = NULL;
if (uap->timeout != NULL) {
error = copyin((const void *)uap->timeout, (void *)&ts32,
sizeof(struct timespec32));
if (error != 0)
return (error);
ts.tv_sec = ts32.tv_sec;
ts.tv_nsec = ts32.tv_nsec;
tsp = &ts;
}
return (kern_thr_suspend(td, tsp));
}
#if 0
int

View File

@ -715,8 +715,7 @@
428 AUE_NULL UNIMPL __acl_aclcheck_link
; XXX implement
429 AUE_SIGWAIT UNIMPL sigwait
430 AUE_NULL NOPROTO { int thr_create(ucontext_t *ctx, long *id, \
int flag s); }
430 AUE_NULL UNIMPL thr_create;
431 AUE_NULL NOPROTO { void thr_exit(long *state); }
432 AUE_NULL NOPROTO { int thr_self(long *id); }
433 AUE_NULL NOPROTO { int thr_kill(long id, int sig); }
@ -728,8 +727,8 @@
439 AUE_EXTATTR_LIST_LINK UNIMPL extattr_list_link
440 AUE_NULL UNIMPL kse_switchin
441 AUE_NULL UNIMPL ksem_timedwait
442 AUE_NULL NOPROTO { int thr_suspend( \
const struct timespec *timeout); }
442 AUE_NULL STD { int freebsd32_thr_suspend( \
const struct timespec32 *timeout); }
443 AUE_NULL NOPROTO { int thr_wake(long id); }
444 AUE_MODUNLOAD NOPROTO { int kldunloadf(int fileid, int flags); }
445 AUE_AUDIT UNIMPL audit
@ -744,7 +743,9 @@
454 AUE_NULL STD { int freebsd32_umtx_op(void *obj, int op,\
uintptr_t val, void *uaddr, \
void *uaddr2); }
455 AUE_NULL UNIMPL thr_new
455 AUE_NULL STD { int freebsd32_thr_new( \
struct thr_param32 *param, \
int param_size); }
456 AUE_NULL NOPROTO { int sigqueue(pid_t pid, int signum, \
void *value); }
457 AUE_NULL UNIMPL kmq_open

View File

@ -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;
int error;
if (uap->param_size < 0 || uap->param_size > sizeof(param))
return (EINVAL);
bzero(&param, sizeof(param));
if ((error = copyin(uap->param, &param, uap->param_size)))
return (error);
return (kern_thr_new(td, &param));
}
int
kern_thr_new(struct thread *td, struct thr_param *param)
{
struct rtprio rtp, *rtpp;
int error;
if (uap->param_size < sizeof(param))
return (EINVAL);
bzero(&param, sizeof(param));
if ((error = copyin(uap->param, &param, sizeof(param))))
return (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);

View File

@ -64,6 +64,10 @@ int thr_kill(long id, int sig);
int thr_suspend(const struct timespec *timeout);
int thr_wake(long id);
int thr_set_name(long id, const char *name);
#else
struct thread;
int kern_thr_new(struct thread *td, struct thr_param *param);
int kern_thr_suspend(struct thread *, struct timespec *);
#endif /* !_KERNEL */
#endif /* ! _SYS_THR_H_ */