Rework the _lwp* and sa_* families of syscalls so some details can be

handled differently depending on the emulation.  This paves the way for
COMPAT_NETBSD32 support of our pthread system.
This commit is contained in:
cube 2006-03-29 23:02:31 +00:00
parent 562d0d89a2
commit 699fe710fb
6 changed files with 150 additions and 53 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_exec.c,v 1.215 2006/03/22 01:14:46 matt Exp $ */
/* $NetBSD: kern_exec.c,v 1.216 2006/03/29 23:02:31 cube Exp $ */
/*-
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.215 2006/03/22 01:14:46 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.216 2006/03/29 23:02:31 cube Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@ -142,6 +142,17 @@ struct uvm_object *emul_netbsd_object;
void syscall(void);
#endif
static const struct sa_emul saemul_netbsd = {
sizeof(ucontext_t),
sizeof(struct sa_t),
sizeof(struct sa_t *),
NULL,
NULL,
cpu_upcall,
(void (*)(struct lwp *, void *))getucontext,
sa_ucsp
};
/* NetBSD emul struct */
const struct emul emul_netbsd = {
"netbsd",
@ -185,6 +196,8 @@ const struct emul emul_netbsd = {
NULL,
uvm_default_mapaddr,
NULL,
&saemul_netbsd,
};
#ifdef LKM

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_lwp.c,v 1.33 2005/11/12 02:28:31 chs Exp $ */
/* $NetBSD: kern_lwp.c,v 1.34 2006/03/29 23:02:31 cube Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.33 2005/11/12 02:28:31 chs Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.34 2006/03/29 23:02:31 cube Exp $");
#include "opt_multiprocessor.h"
@ -87,7 +87,8 @@ sys__lwp_create(struct lwp *l, void *v, register_t *retval)
newuc = pool_get(&lwp_uc_pool, PR_WAITOK);
error = copyin(SCARG(uap, ucp), newuc, sizeof(*newuc));
error = copyin(SCARG(uap, ucp), newuc,
l->l_proc->p_emul->e_sa->sae_ucsize);
if (error)
return (error);

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_sa.c,v 1.70 2005/12/24 19:12:23 perry Exp $ */
/* $NetBSD: kern_sa.c,v 1.71 2006/03/29 23:02:31 cube Exp $ */
/*-
* Copyright (c) 2001, 2004, 2005 The NetBSD Foundation, Inc.
@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#include "opt_ktrace.h"
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.70 2005/12/24 19:12:23 perry Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.71 2006/03/29 23:02:31 cube Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -187,10 +187,26 @@ sys_sa_register(struct lwp *l, void *v, register_t *retval)
syscallarg(int) flags;
syscallarg(ssize_t) stackinfo_offset;
} */ *uap = v;
int error;
sa_upcall_t prev;
error = dosa_register(l, SCARG(uap, new), &prev, SCARG(uap, flags),
SCARG(uap, stackinfo_offset));
if (error)
return error;
if (SCARG(uap, old))
return copyout(&prev, SCARG(uap, old),
sizeof(prev));
return 0;
}
int
dosa_register(struct lwp *l, sa_upcall_t new, sa_upcall_t *prev, int flags,
ssize_t stackinfo_offset)
{
struct proc *p = l->l_proc;
struct sadata *sa;
sa_upcall_t prev;
int error;
if (p->p_sa == NULL) {
/* Allocate scheduler activations data structure */
@ -198,13 +214,13 @@ sys_sa_register(struct lwp *l, void *v, register_t *retval)
/* Initialize. */
memset(sa, 0, sizeof(*sa));
simple_lock_init(&sa->sa_lock);
sa->sa_flag = SCARG(uap, flags) & SA_FLAG_ALL;
sa->sa_flag = flags & SA_FLAG_ALL;
sa->sa_maxconcurrency = 1;
sa->sa_concurrency = 1;
SPLAY_INIT(&sa->sa_stackstree);
sa->sa_stacknext = NULL;
if (SCARG(uap, flags) & SA_FLAG_STACKINFO)
sa->sa_stackinfo_offset = SCARG(uap, stackinfo_offset);
if (flags & SA_FLAG_STACKINFO)
sa->sa_stackinfo_offset = stackinfo_offset;
else
sa->sa_stackinfo_offset = 0;
sa->sa_nstacks = 0;
@ -217,14 +233,8 @@ sys_sa_register(struct lwp *l, void *v, register_t *retval)
sa_newcachelwp(l);
}
prev = p->p_sa->sa_upcall;
p->p_sa->sa_upcall = SCARG(uap, new);
if (SCARG(uap, old)) {
error = copyout(&prev, SCARG(uap, old),
sizeof(prev));
if (error)
return (error);
}
*prev = p->p_sa->sa_upcall;
p->p_sa->sa_upcall = new;
return (0);
}
@ -268,6 +278,7 @@ sa_stackused(struct sastack *sast, struct sadata *sa)
{
unsigned int gen;
/* COMPAT_NETBSD32: believe it or not, but the following is ok */
if (copyin((void *)&((struct sa_stackinfo_t *)
((char *)sast->sast_stack.ss_sp +
sa->sa_stackinfo_offset))->sasi_stackgen,
@ -285,6 +296,7 @@ static inline void
sa_setstackfree(struct sastack *sast, struct sadata *sa)
{
/* COMPAT_NETBSD32: believe it or not, but the following is ok */
if (copyin((void *)&((struct sa_stackinfo_t *)
((char *)sast->sast_stack.ss_sp +
sa->sa_stackinfo_offset))->sasi_stackgen,
@ -354,6 +366,12 @@ sast_compare(struct sastack *a, struct sastack *b)
return (0);
}
static int
sa_copyin_stack(stack_t *stacks, int index, stack_t *dest)
{
return copyin(stacks + index, dest, sizeof(stack_t));
}
int
sys_sa_stacks(struct lwp *l, void *v, register_t *retval)
{
@ -361,6 +379,14 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval)
syscallarg(int) num;
syscallarg(stack_t *) stacks;
} */ *uap = v;
return sa_stacks1(l, retval, SCARG(uap, num), SCARG(uap, stacks), sa_copyin_stack);
}
int
sa_stacks1(struct lwp *l, register_t *retval, int num, stack_t *stacks,
sa_copyin_stack_t do_sa_copyin_stack)
{
struct sadata *sa = l->l_proc->p_sa;
struct sastack *sast, newsast;
int count, error, f, i;
@ -369,7 +395,7 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval)
if (sa == NULL)
return (EINVAL);
count = SCARG(uap, num);
count = num;
if (count < 0)
return (EINVAL);
@ -378,8 +404,7 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval)
error = 0;
for (i = 0; i < count; i++) {
error = copyin(SCARG(uap, stacks) + i, &newsast.sast_stack,
sizeof(stack_t));
error = do_sa_copyin_stack(stacks, i, &newsast.sast_stack);
if (error) {
count = i;
break;
@ -736,7 +761,7 @@ sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
struct sadata *sa = l->l_proc->p_sa;
struct sadata_vp *vp = l->l_savp;
struct sastack *sast;
int f;
int f, error;
/* XXX prevent recursive upcalls if we sleep for memory */
SA_LWP_STATE_LOCK(l, f);
@ -748,6 +773,13 @@ sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
DPRINTFN(9,("sa_upcall(%d.%d) using stack %p\n",
l->l_proc->p_pid, l->l_lid, sast->sast_stack.ss_sp));
if (l->l_proc->p_emul->e_sa->sae_upcallconv) {
error = (*l->l_proc->p_emul->e_sa->sae_upcallconv)(l, type,
&argsize, &arg, &func);
if (error)
return error;
}
SA_LWP_STATE_LOCK(l, f);
sau = sadata_upcall_alloc(1);
SA_LWP_STATE_UNLOCK(l, f);
@ -786,6 +818,13 @@ sa_upcall0(struct sadata_upcall *sau, int type, struct lwp *event,
sau->sau_argfreefunc = func;
}
void *
sa_ucsp(void *arg)
{
ucontext_t *uc = arg;
return (void *)(uintptr_t)_UC_MACHINE_SP(uc);
}
static void
sa_upcall_getstate(union sau_state *ss, struct lwp *l)
@ -795,12 +834,15 @@ sa_upcall_getstate(union sau_state *ss, struct lwp *l)
if (l) {
l->l_flag |= L_SA_SWITCHING;
getucontext(l, &ss->ss_captured.ss_ctx);
(*l->l_proc->p_emul->e_sa->sae_getucontext)(l,
(void *)&ss->ss_captured.ss_ctx);
l->l_flag &= ~L_SA_SWITCHING;
sp = (void *)
((intptr_t)_UC_MACHINE_SP(&ss->ss_captured.ss_ctx));
sp = (*l->l_proc->p_emul->e_sa->sae_ucsp)
(&ss->ss_captured.ss_ctx);
/* XXX COMPAT_NETBSD32: _UC_UCONTEXT_ALIGN */
sp = STACK_ALIGN(sp, ~_UC_UCONTEXT_ALIGN);
ucsize = roundup(sizeof(ucontext_t), (~_UC_UCONTEXT_ALIGN) + 1);
ucsize = roundup(l->l_proc->p_emul->e_sa->sae_ucsize,
(~_UC_UCONTEXT_ALIGN) + 1);
ss->ss_captured.ss_sa.sa_context = (ucontext_t *)
STACK_ALLOC(sp, ucsize);
ss->ss_captured.ss_sa.sa_id = l->l_lid;
@ -837,7 +879,7 @@ sa_pagefault(struct lwp *l, ucontext_t *l_ctx)
return 1;
}
sast.sast_stack.ss_sp = (void *)(intptr_t)_UC_MACHINE_SP(l_ctx);
sast.sast_stack.ss_sp = (*p->p_emul->e_sa->sae_ucsp)(l_ctx);
sast.sast_stack.ss_size = 1;
if (SPLAY_FIND(sasttree, &sa->sa_stackstree, &sast)) {
@ -1307,21 +1349,24 @@ sa_makeupcalls(struct lwp *l)
{
struct lwp *l2, *eventq;
struct proc *p;
const struct sa_emul *sae;
struct sadata *sa;
struct sadata_vp *vp;
struct sa_t **sapp, *sap;
uintptr_t sapp, sap;
struct sa_t self_sa;
struct sa_t *sas[3], *sasp;
struct sadata_upcall *sau;
union sau_state e_ss;
void *stack, *ap;
ucontext_t u, *up;
size_t sz;
int i, nint, nevents, s, type;
size_t sz, ucsize;
int i, nint, nevents, s, type, error;
p = l->l_proc;
sae = p->p_emul->e_sa;
sa = p->p_sa;
vp = l->l_savp;
ucsize = sae->sae_ucsize;
sau = SIMPLEQ_FIRST(&vp->savp_upcalls);
SIMPLEQ_REMOVE_HEAD(&vp->savp_upcalls, sau_next);
@ -1348,7 +1393,7 @@ sa_makeupcalls(struct lwp *l)
if (sau->sau_event.ss_captured.ss_sa.sa_context != NULL) {
if (copyout(&sau->sau_event.ss_captured.ss_ctx,
sau->sau_event.ss_captured.ss_sa.sa_context,
sizeof(ucontext_t)) != 0) {
ucsize) != 0) {
#ifdef DIAGNOSTIC
printf("sa_makeupcalls(%d.%d): couldn't copyout"
" context of event LWP %d\n",
@ -1366,7 +1411,7 @@ sa_makeupcalls(struct lwp *l)
sau->sau_event.ss_captured.ss_sa.sa_context);
if (copyout(&sau->sau_interrupted.ss_captured.ss_ctx,
sau->sau_interrupted.ss_captured.ss_sa.sa_context,
sizeof(ucontext_t)) != 0) {
ucsize) != 0) {
#ifdef DIAGNOSTIC
printf("sa_makeupcalls(%d.%d): couldn't copyout"
" context of interrupted LWP %d\n",
@ -1396,10 +1441,14 @@ sa_makeupcalls(struct lwp *l)
u.uc_stack = sau->sau_stack;
u.uc_flags = _UC_STACK;
up = (void *)STACK_ALLOC(stack, sizeof(ucontext_t));
stack = STACK_GROW(stack, sizeof(ucontext_t));
up = (void *)STACK_ALLOC(stack, ucsize);
stack = STACK_GROW(stack, ucsize);
if (copyout(&u, up, sizeof(ucontext_t)) != 0) {
if (sae->sae_sacopyout != NULL)
error = (*sae->sae_sacopyout)(SAOUT_UCONTEXT, &u, up);
else
error = copyout(&u, up, ucsize);
if (error) {
sadata_upcall_free(sau);
#ifdef DIAGNOSTIC
printf("sa_makeupcalls: couldn't copyout activation"
@ -1413,20 +1462,20 @@ sa_makeupcalls(struct lwp *l)
/* Next, copy out the sa_t's and pointers to them. */
sz = (1 + nevents + nint) * sizeof(struct sa_t);
sap = (void *)STACK_ALLOC(stack, sz);
sap += 1 + nevents + nint;
sz = (1 + nevents + nint) * sae->sae_sasize;
sap = (uintptr_t)STACK_ALLOC(stack, sz);
sap += sz;
stack = STACK_GROW(stack, sz);
sz = (1 + nevents + nint) * sizeof(struct sa_t *);
sapp = (void *)STACK_ALLOC(stack, sz);
sapp += 1 + nevents + nint;
sz = (1 + nevents + nint) * sae->sae_sapsize;
sapp = (uintptr_t)STACK_ALLOC(stack, sz);
sapp += sz;
stack = STACK_GROW(stack, sz);
KDASSERT(nint <= 1);
for (i = nevents + nint; i >= 0; i--) {
sap--;
sapp--;
sap -= sae->sae_sasize;
sapp -= sae->sae_sapsize;
if (i == 1 + nevents) /* interrupted sa */
sasp = sas[2];
else if (i <= 1) /* self_sa and event sa */
@ -1447,7 +1496,7 @@ sa_makeupcalls(struct lwp *l)
if (copyout(&e_ss.ss_captured.ss_ctx,
e_ss.ss_captured.ss_sa.sa_context,
sizeof(ucontext_t)) != 0) {
ucsize) != 0) {
#ifdef DIAGNOSTIC
printf("sa_makeupcalls(%d.%d): couldn't copyout"
" context of event LWP %d\n",
@ -1458,8 +1507,12 @@ sa_makeupcalls(struct lwp *l)
}
sasp = &e_ss.ss_captured.ss_sa;
}
if ((copyout(sasp, sap, sizeof(struct sa_t)) != 0) ||
(copyout(&sap, sapp, sizeof(struct sa_t *)) != 0)) {
if ((sae->sae_sacopyout != NULL &&
((*sae->sae_sacopyout)(SAOUT_SA_T, sasp, (void *)sap) ||
(*sae->sae_sacopyout)(SAOUT_SAP_T, &sap, (void *)sapp))) ||
(sae->sae_sacopyout == NULL &&
(copyout(sasp, (void *)sap, sizeof(struct sa_t)) ||
copyout(&sap, (void *)sapp, sizeof(struct sa_t *))))) {
/* Copying onto the stack didn't work. Die. */
sadata_upcall_free(sau);
#ifdef DIAGNOSTIC
@ -1506,9 +1559,10 @@ sa_makeupcalls(struct lwp *l)
#ifdef KTRACE
if (KTRPOINT(p, KTR_SAUPCALL))
ktrsaupcall(l, type, nevents, nint, sapp, ap);
ktrsaupcall(l, type, nevents, nint, (void *)sapp, ap);
#endif
cpu_upcall(l, type, nevents, nint, sapp, ap, stack, sa->sa_upcall);
(*sae->sae_upcall)(l, type, nevents, nint, (void *)sapp, ap, stack,
sa->sa_upcall);
l->l_flag &= ~L_SA_YIELD;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: lwp.h,v 1.33 2006/02/16 20:17:20 perry Exp $ */
/* $NetBSD: lwp.h,v 1.34 2006/03/29 23:02:31 cube Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -180,6 +180,7 @@ void lwp_exit (struct lwp *);
void lwp_exit2 (struct lwp *);
struct lwp *proc_representative_lwp(struct proc *);
__inline int lwp_suspend(struct lwp *, struct lwp *);
int lwp_create1(struct lwp *, const void *, size_t, u_long, lwpid_t *);
#endif /* _KERNEL */
/* Flags for _lwp_create(), as per Solaris. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.217 2006/03/20 13:14:37 drochner Exp $ */
/* $NetBSD: proc.h,v 1.218 2006/03/29 23:02:31 cube Exp $ */
/*-
* Copyright (c) 1986, 1989, 1991, 1993
@ -86,6 +86,7 @@ struct pgrp {
struct exec_package;
struct ps_strings;
struct ras;
struct sa_emul;
struct emul {
const char *e_name; /* Symbolic name */
@ -131,6 +132,9 @@ struct emul {
/* Emulation-specific hook for userspace page faults */
int (*e_usertrap)(struct lwp *, vaddr_t, void *);
/* SA-related information */
const struct sa_emul *e_sa;
};
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: savar.h,v 1.17 2005/12/03 17:10:46 christos Exp $ */
/* $NetBSD: savar.h,v 1.18 2006/03/29 23:02:31 cube Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -57,6 +57,19 @@ union sau_state {
} ss_deferred;
};
struct sa_emul {
size_t sae_ucsize; /* Size of ucontext_t */
size_t sae_sasize; /* Size of sa_t */
size_t sae_sapsize; /* Size of (sa_t *) */
int (*sae_sacopyout)(int, const void *, void *);
int (*sae_upcallconv)(struct lwp *, int, size_t *, void **,
void (**)(void *));
void (*sae_upcall)(struct lwp *, int, int, int, void *,
void *, void *, sa_upcall_t);
void (*sae_getucontext)(struct lwp *, void *);
void *(*sae_ucsp)(void *); /* Stack ptr from an ucontext_t */
};
struct sadata_upcall {
SIMPLEQ_ENTRY(sadata_upcall) sau_next;
int sau_flags;
@ -146,4 +159,15 @@ void sa_unblock_userret(struct lwp *);
void sa_upcall_userret(struct lwp *);
void cpu_upcall(struct lwp *, int, int, int, void *, void *, void *, sa_upcall_t);
typedef int (*sa_copyin_stack_t)(stack_t *, int, stack_t *);
int sa_stacks1(struct lwp *, register_t *, int, stack_t *,
sa_copyin_stack_t);
int dosa_register(struct lwp *, sa_upcall_t, sa_upcall_t *, int, ssize_t);
void *sa_ucsp(void *);
#define SAOUT_UCONTEXT 0
#define SAOUT_SA_T 1
#define SAOUT_SAP_T 2
#endif /* !_SYS_SAVAR_H_ */