summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/freebsd32/freebsd32.h14
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c56
-rw-r--r--sys/compat/freebsd32/syscalls.master11
-rw-r--r--sys/kern/kern_thr.c89
-rw-r--r--sys/sys/thr.h4
5 files changed, 144 insertions, 30 deletions
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index cea8687..f740d89 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -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_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 8076d23..2c56687 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -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
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 93e63e9..7afe985 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -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
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(&param, sizeof(param));
- if ((error = copyin(uap->param, &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;
+
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);
diff --git a/sys/sys/thr.h b/sys/sys/thr.h
index bd2723e..216ef6f 100644
--- a/sys/sys/thr.h
+++ b/sys/sys/thr.h
@@ -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_ */
OpenPOWER on IntegriCloud