Add getcontext, setcontext, and swapcontext as system calls.
Previously these were libc functions but were requested to be made into system calls for atomicity and to coalesce what might be two entrances into the kernel (signal mask setting and floating point trap) into one. A few style nits and comments from bde are also included. Tested on alpha by: gallatin
This commit is contained in:
parent
3d8ce33a50
commit
2be05b70c9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=106977
@ -210,7 +210,9 @@ static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask,
|
||||
u_long code);
|
||||
#endif
|
||||
|
||||
static void get_fpcontext(struct thread *td, mcontext_t *mcp);
|
||||
static void identifycpu(void);
|
||||
static int set_fpcontext(struct thread *td, const mcontext_t *mcp);
|
||||
|
||||
struct kva_md_info kmi;
|
||||
|
||||
@ -1405,7 +1407,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
frame->tf_regs[FRAME_TRAPARG_A1];
|
||||
sf.sf_uc.uc_mcontext.mc_regs[R_TRAPARG_A2] =
|
||||
frame->tf_regs[FRAME_TRAPARG_A2];
|
||||
sf.sf_uc.uc_mcontext.mc_format = __UC_REV0_SIGFRAME;
|
||||
sf.sf_uc.uc_mcontext.mc_format = _MC_REV0_SIGFRAME;
|
||||
|
||||
/*
|
||||
* Allocate and validate space for the signal handler
|
||||
@ -1664,13 +1666,15 @@ sigreturn(struct thread *td,
|
||||
return (error);
|
||||
}
|
||||
#ifdef COMPAT_43
|
||||
if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE)
|
||||
return osigreturn(td, (struct osigreturn_args *)uap);
|
||||
if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE)
|
||||
return osigreturn(td, (struct osigreturn_args *)uap);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Restore the user-supplied information
|
||||
*/
|
||||
if ((error = set_fpcontext(td, &uc.uc_mcontext)) != 0)
|
||||
return (error);
|
||||
set_regs(td, (struct reg *)uc.uc_mcontext.mc_regs);
|
||||
val = (uc.uc_mcontext.mc_regs[R_PS] | ALPHA_PSL_USERSET) &
|
||||
~ALPHA_PSL_USERCLR;
|
||||
@ -1692,12 +1696,6 @@ sigreturn(struct thread *td,
|
||||
signotify(p);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
/* XXX ksc.sc_ownedfp ? */
|
||||
alpha_fpstate_drop(td);
|
||||
bcopy((struct fpreg *)uc.uc_mcontext.mc_fpregs,
|
||||
&td->td_pcb->pcb_fp, sizeof(struct fpreg));
|
||||
td->td_pcb->pcb_fp_control = uc.uc_mcontext.mc_fp_control;
|
||||
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
|
||||
@ -2010,6 +2008,133 @@ set_regs(td, regs)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
/*
|
||||
* Use a trapframe for getsetcontext, so just copy the
|
||||
* threads trapframe.
|
||||
*/
|
||||
bcopy(&td->td_frame, &mcp->mc_regs, sizeof(td->td_frame));
|
||||
|
||||
/*
|
||||
* When the thread is the current thread, the user stack pointer
|
||||
* is not in the PCB; it must be read from the PAL.
|
||||
*/
|
||||
if (td == curthread)
|
||||
mcp->mc_regs[FRAME_SP] = alpha_pal_rdusp();
|
||||
|
||||
mcp->mc_format = _MC_REV0_TRAPFRAME;
|
||||
mcp->mc_onstack = sigonstack(alpha_pal_rdusp()) ? 1 : 0;
|
||||
get_fpcontext(td, mcp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_mcontext(struct thread *td, const mcontext_t *mcp)
|
||||
{
|
||||
int ret;
|
||||
unsigned long val;
|
||||
|
||||
if ((mcp->mc_format != _MC_REV0_TRAPFRAME) &&
|
||||
(mcp->mc_format != _MC_REV0_SIGFRAME))
|
||||
return (EINVAL);
|
||||
else if ((ret = set_fpcontext(td, mcp)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (mcp->mc_format == _MC_REV0_SIGFRAME) {
|
||||
set_regs(td, (struct reg *)&mcp->mc_regs);
|
||||
val = (mcp->mc_regs[R_PS] | ALPHA_PSL_USERSET) &
|
||||
~ALPHA_PSL_USERCLR;
|
||||
td->td_frame->tf_regs[FRAME_PS] = val;
|
||||
td->td_frame->tf_regs[FRAME_PC] = mcp->mc_regs[R_PC];
|
||||
td->td_frame->tf_regs[FRAME_FLAGS] = 0;
|
||||
if (td == curthread)
|
||||
alpha_pal_wrusp(mcp->mc_regs[R_SP]);
|
||||
|
||||
} else {
|
||||
if (td == curthread)
|
||||
alpha_pal_wrusp(mcp->mc_regs[FRAME_SP]);
|
||||
/*
|
||||
* The context is a trapframe, so just copy it over the
|
||||
* threads frame.
|
||||
*/
|
||||
bcopy(&mcp->mc_regs, &td->td_frame, sizeof(td->td_frame));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
get_fpcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
register_t s;
|
||||
|
||||
s = intr_disable();
|
||||
if ((td->td_md.md_flags & MDTD_FPUSED) == 0) {
|
||||
intr_restore(s);
|
||||
mcp->mc_ownedfp = _MC_FPOWNED_NONE;
|
||||
} else if (PCPU_GET(fpcurthread) == td) {
|
||||
/* See comments in alpha_fpstate_save() regarding FEN. */
|
||||
if (td != curthread)
|
||||
alpha_pal_wrfen(1);
|
||||
/*
|
||||
* The last field (fpr_cr) of struct fpreg isn't
|
||||
* included in mc_fpregs, but it immediately follows
|
||||
* it in mcontext_t.
|
||||
*/
|
||||
savefpstate((struct fpreg *)&mcp->mc_fpregs);
|
||||
if (td != curthread)
|
||||
alpha_pal_wrfen(0);
|
||||
intr_restore(s);
|
||||
mcp->mc_ownedfp = _MC_FPOWNED_FPU;
|
||||
} else {
|
||||
/*
|
||||
* The thread doesn't own the FPU so get the state from
|
||||
* the PCB.
|
||||
*/
|
||||
intr_restore(s);
|
||||
bcopy(&td->td_pcb->pcb_fp, &mcp->mc_fpregs,
|
||||
sizeof(td->td_pcb->pcb_fp));
|
||||
mcp->mc_ownedfp = _MC_FPOWNED_PCB;
|
||||
}
|
||||
/* There's no harm in always doing the following. */
|
||||
mcp->mc_fp_control = td->td_pcb->pcb_fp_control;
|
||||
}
|
||||
|
||||
static int
|
||||
set_fpcontext(struct thread *td, const mcontext_t *mcp)
|
||||
{
|
||||
register_t s;
|
||||
|
||||
if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) {
|
||||
/* XXX - Drop fpu state so we get a clean state? */
|
||||
alpha_fpstate_drop(td);
|
||||
}
|
||||
else if ((mcp->mc_ownedfp != _MC_FPOWNED_FPU) &&
|
||||
(mcp->mc_ownedfp != _MC_FPOWNED_PCB))
|
||||
return (EINVAL);
|
||||
else {
|
||||
s = intr_disable();
|
||||
if (PCPU_GET(fpcurthread) == td) {
|
||||
/*
|
||||
* The last field (fpr_cr) of struct fpreg isn't
|
||||
* included in mc_fpregs, but it immediately follows
|
||||
* it in mcontext_t.
|
||||
*/
|
||||
restorefpstate((struct fpreg *)&mcp->mc_fpregs);
|
||||
intr_restore(s);
|
||||
}
|
||||
else {
|
||||
/* Just save the state in the PCB. */
|
||||
intr_restore(s);
|
||||
bcopy(&mcp->mc_fpregs, &td->td_pcb->pcb_fp,
|
||||
sizeof (td->td_pcb->pcb_fp));
|
||||
}
|
||||
td->td_pcb->pcb_fp_control = mcp->mc_fp_control;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
fill_dbregs(struct thread *td, struct dbreg *dbregs)
|
||||
{
|
||||
|
@ -115,11 +115,11 @@ void XentRestart(void); /* MAGIC */
|
||||
void XentSys(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
|
||||
void XentUna(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
|
||||
void alpha_init(u_long, u_long, u_long, u_long, u_long);
|
||||
void alpha_fpstate_check(struct thread *td);
|
||||
void alpha_fpstate_drop(struct thread *td);
|
||||
void alpha_fpstate_save(struct thread *td, int write);
|
||||
void alpha_fpstate_switch(struct thread *td);
|
||||
int alpha_pa_access(u_long);
|
||||
void alpha_fpstate_check(struct thread *p);
|
||||
void alpha_fpstate_save(struct thread *p, int write);
|
||||
void alpha_fpstate_drop(struct thread *p);
|
||||
void alpha_fpstate_switch(struct thread *p);
|
||||
int badaddr (void *, size_t);
|
||||
int badaddr_read(void *, size_t, void *);
|
||||
u_int64_t console_restart(u_int64_t, u_int64_t, u_int64_t);
|
||||
|
@ -116,9 +116,7 @@
|
||||
__asm__("trapb")
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
extern int fp_software_completion(u_int64_t regmask, struct thread *p);
|
||||
|
||||
extern int fp_software_completion(u_int64_t regmask, struct thread *td);
|
||||
#endif
|
||||
|
||||
#endif /* ! _MACHINE_FPU_H_ */
|
||||
|
@ -94,10 +94,9 @@ struct sigcontext {
|
||||
unsigned long sc_fpregs[32]; /* FP register set (see above) */
|
||||
unsigned long sc_fpcr; /* FP control register (see above) */
|
||||
unsigned long sc_fp_control; /* FP software control word */
|
||||
long sc_ownedfp; /* fp has been used */
|
||||
long sc_xxx1[2]; /* sc_ssize, sc_sbase on DUX */
|
||||
long sc_xxx2[3]; /* sc_fp_trap_pc, sc_fp_trigger_sum, sc_fp_trigger_inst */
|
||||
long sc_reserved[2]; /* XXX */
|
||||
long sc_ownedfp; /* fp has been used; see mcontext_t */
|
||||
long sc_format; /* see mcontext_t */
|
||||
long sc_spare[6]; /* XXX */
|
||||
};
|
||||
|
||||
#define sc_sp sc_regs[R_SP]
|
||||
|
@ -43,11 +43,14 @@ typedef struct __mcontext {
|
||||
unsigned long mc_fpregs[32];
|
||||
unsigned long mc_fpcr;
|
||||
unsigned long mc_fp_control;
|
||||
#define _MC_FPOWNED_NONE 0 /* FP state not used */
|
||||
#define _MC_FPOWNED_FPU 1 /* FP state came from FPU */
|
||||
#define _MC_FPOWNED_PCB 2 /* FP state came from PCB */
|
||||
long mc_ownedfp;
|
||||
#define __UC_REV0_SIGFRAME 1 /* context is a signal frame */
|
||||
#define __UC_REV0_TRAPFRAME 2 /* context is a trap frame */
|
||||
#define _MC_REV0_SIGFRAME 1 /* context is a signal frame */
|
||||
#define _MC_REV0_TRAPFRAME 2 /* context is a trap frame */
|
||||
long mc_format;
|
||||
long __spare__[6];
|
||||
long mc_spare[6];
|
||||
} mcontext_t;
|
||||
|
||||
#if defined(_KERNEL) && defined(COMPAT_FREEBSD4)
|
||||
|
@ -161,14 +161,14 @@ void stop_emulating(void);
|
||||
|
||||
typedef u_char bool_t;
|
||||
|
||||
static void fpusave(union savefpu *);
|
||||
static void fpurstor(union savefpu *);
|
||||
static int npx_attach(device_t dev);
|
||||
static void npx_identify(driver_t *driver, device_t parent);
|
||||
#ifndef SMP
|
||||
static void npx_intr(void *);
|
||||
#endif
|
||||
static int npx_probe(device_t dev);
|
||||
static void fpusave(union savefpu *);
|
||||
static void fpurstor(union savefpu *);
|
||||
#ifdef I586_CPU_XXX
|
||||
static long timezero(const char *funcname,
|
||||
void (*func)(void *buf, size_t len));
|
||||
|
@ -2317,7 +2317,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
|
||||
/*
|
||||
* Get machine context.
|
||||
*/
|
||||
void
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
struct trapframe *tp;
|
||||
@ -2344,6 +2344,7 @@ get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
mcp->mc_ss = tp->tf_ss;
|
||||
mcp->mc_len = sizeof(*mcp);
|
||||
get_fpcontext(td, mcp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -119,7 +119,7 @@ struct sigcontext {
|
||||
int sc_efl;
|
||||
int sc_esp;
|
||||
int sc_ss;
|
||||
int sc_len; /* sizeof(struct mcontext_t) */
|
||||
int sc_len; /* sizeof(mcontext_t) */
|
||||
/*
|
||||
* XXX - See <machine/ucontext.h> and <machine/npx.h> for
|
||||
* the following fields.
|
||||
@ -127,7 +127,7 @@ struct sigcontext {
|
||||
int sc_fpformat;
|
||||
int sc_ownedfp;
|
||||
int sc_spare1[1];
|
||||
int sc_fpregs[128];
|
||||
int sc_fpstate[128];
|
||||
int sc_spare2[8];
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,7 @@ typedef struct __mcontext {
|
||||
* and ucontext_t at the same time.
|
||||
*/
|
||||
int mc_onstack; /* XXX - sigcontext compat. */
|
||||
int mc_gs;
|
||||
int mc_gs; /* machine state (trapframe) */
|
||||
int mc_fs;
|
||||
int mc_es;
|
||||
int mc_ds;
|
||||
@ -55,7 +55,7 @@ typedef struct __mcontext {
|
||||
int mc_eip;
|
||||
int mc_cs;
|
||||
int mc_eflags;
|
||||
int mc_esp; /* machine state */
|
||||
int mc_esp;
|
||||
int mc_ss;
|
||||
|
||||
int mc_len; /* sizeof(mcontext_t) */
|
||||
@ -72,8 +72,7 @@ typedef struct __mcontext {
|
||||
int mc_spare2[8];
|
||||
} mcontext_t;
|
||||
|
||||
#ifdef _KERNEL
|
||||
#ifdef COMPAT_FREEBSD4
|
||||
#if defined(_KERNEL) && defined(COMPAT_FREEBSD4)
|
||||
/* For 4.x binaries */
|
||||
struct mcontext4 {
|
||||
int mc_onstack; /* XXX - sigcontext compat. */
|
||||
@ -101,10 +100,4 @@ struct mcontext4 {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct thread;
|
||||
|
||||
void get_mcontext(struct thread *td, mcontext_t *mcp);
|
||||
int set_mcontext(struct thread *td, const mcontext_t *mcp);
|
||||
#endif
|
||||
|
||||
#endif /* !_MACHINE_UCONTEXT_H_ */
|
||||
|
@ -161,14 +161,14 @@ void stop_emulating(void);
|
||||
|
||||
typedef u_char bool_t;
|
||||
|
||||
static void fpusave(union savefpu *);
|
||||
static void fpurstor(union savefpu *);
|
||||
static int npx_attach(device_t dev);
|
||||
static void npx_identify(driver_t *driver, device_t parent);
|
||||
#ifndef SMP
|
||||
static void npx_intr(void *);
|
||||
#endif
|
||||
static int npx_probe(device_t dev);
|
||||
static void fpusave(union savefpu *);
|
||||
static void fpurstor(union savefpu *);
|
||||
#ifdef I586_CPU_XXX
|
||||
static long timezero(const char *funcname,
|
||||
void (*func)(void *buf, size_t len));
|
||||
|
@ -975,6 +975,7 @@ kern/kern_alq.c optional alq
|
||||
kern/kern_clock.c standard
|
||||
kern/kern_condvar.c standard
|
||||
kern/kern_conf.c standard
|
||||
kern/kern_context.c standard
|
||||
kern/kern_descrip.c standard
|
||||
kern/kern_poll.c optional device_polling
|
||||
kern/kern_environment.c standard
|
||||
|
@ -2317,7 +2317,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
|
||||
/*
|
||||
* Get machine context.
|
||||
*/
|
||||
void
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
struct trapframe *tp;
|
||||
@ -2344,6 +2344,7 @@ get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
mcp->mc_ss = tp->tf_ss;
|
||||
mcp->mc_len = sizeof(*mcp);
|
||||
get_fpcontext(td, mcp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -119,7 +119,7 @@ struct sigcontext {
|
||||
int sc_efl;
|
||||
int sc_esp;
|
||||
int sc_ss;
|
||||
int sc_len; /* sizeof(struct mcontext_t) */
|
||||
int sc_len; /* sizeof(mcontext_t) */
|
||||
/*
|
||||
* XXX - See <machine/ucontext.h> and <machine/npx.h> for
|
||||
* the following fields.
|
||||
@ -127,7 +127,7 @@ struct sigcontext {
|
||||
int sc_fpformat;
|
||||
int sc_ownedfp;
|
||||
int sc_spare1[1];
|
||||
int sc_fpregs[128];
|
||||
int sc_fpstate[128];
|
||||
int sc_spare2[8];
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,7 @@ typedef struct __mcontext {
|
||||
* and ucontext_t at the same time.
|
||||
*/
|
||||
int mc_onstack; /* XXX - sigcontext compat. */
|
||||
int mc_gs;
|
||||
int mc_gs; /* machine state (trapframe) */
|
||||
int mc_fs;
|
||||
int mc_es;
|
||||
int mc_ds;
|
||||
@ -55,7 +55,7 @@ typedef struct __mcontext {
|
||||
int mc_eip;
|
||||
int mc_cs;
|
||||
int mc_eflags;
|
||||
int mc_esp; /* machine state */
|
||||
int mc_esp;
|
||||
int mc_ss;
|
||||
|
||||
int mc_len; /* sizeof(mcontext_t) */
|
||||
@ -72,8 +72,7 @@ typedef struct __mcontext {
|
||||
int mc_spare2[8];
|
||||
} mcontext_t;
|
||||
|
||||
#ifdef _KERNEL
|
||||
#ifdef COMPAT_FREEBSD4
|
||||
#if defined(_KERNEL) && defined(COMPAT_FREEBSD4)
|
||||
/* For 4.x binaries */
|
||||
struct mcontext4 {
|
||||
int mc_onstack; /* XXX - sigcontext compat. */
|
||||
@ -101,10 +100,4 @@ struct mcontext4 {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct thread;
|
||||
|
||||
void get_mcontext(struct thread *td, mcontext_t *mcp);
|
||||
int set_mcontext(struct thread *td, const mcontext_t *mcp);
|
||||
#endif
|
||||
|
||||
#endif /* !_MACHINE_UCONTEXT_H_ */
|
||||
|
@ -161,14 +161,14 @@ void stop_emulating(void);
|
||||
|
||||
typedef u_char bool_t;
|
||||
|
||||
static void fpusave(union savefpu *);
|
||||
static void fpurstor(union savefpu *);
|
||||
static int npx_attach(device_t dev);
|
||||
static void npx_identify(driver_t *driver, device_t parent);
|
||||
#ifndef SMP
|
||||
static void npx_intr(void *);
|
||||
#endif
|
||||
static int npx_probe(device_t dev);
|
||||
static void fpusave(union savefpu *);
|
||||
static void fpurstor(union savefpu *);
|
||||
#ifdef I586_CPU_XXX
|
||||
static long timezero(const char *funcname,
|
||||
void (*func)(void *buf, size_t len));
|
||||
|
@ -1038,6 +1038,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
int
|
||||
set_mcontext(struct thread *td, const mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Machine dependent boot() routine
|
||||
*/
|
||||
|
134
sys/kern/kern_context.c
Normal file
134
sys/kern/kern_context.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*-
|
||||
* Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
/*
|
||||
* The first two fields of a ucontext_t are the signal mask and
|
||||
* the machine context. The next field is uc_link; we want to
|
||||
* avoid destroying the link when copying out contexts.
|
||||
*/
|
||||
#define UC_COPY_SIZE (sizeof(sigset_t) + sizeof(mcontext_t))
|
||||
|
||||
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct getcontext_args {
|
||||
struct __ucontext *ucp;
|
||||
}
|
||||
struct setcontext_args {
|
||||
const struct __ucontext_t *ucp;
|
||||
}
|
||||
struct swapcontext_args {
|
||||
struct __ucontext *oucp;
|
||||
const struct __ucontext_t *ucp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MPSAFE
|
||||
*/
|
||||
int
|
||||
getcontext(struct thread *td, struct getcontext_args *uap)
|
||||
{
|
||||
ucontext_t uc;
|
||||
int ret;
|
||||
|
||||
if (uap->ucp == NULL)
|
||||
ret = EINVAL;
|
||||
else {
|
||||
get_mcontext(td, &uc.uc_mcontext);
|
||||
uc.uc_sigmask = td->td_proc->p_sigmask;
|
||||
ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPSAFE
|
||||
*/
|
||||
int
|
||||
setcontext(struct thread *td, struct setcontext_args *uap)
|
||||
{
|
||||
ucontext_t uc;
|
||||
int ret;
|
||||
|
||||
if (uap->ucp == NULL)
|
||||
ret = EINVAL;
|
||||
else {
|
||||
ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
|
||||
if (ret == 0) {
|
||||
ret = set_mcontext(td, &uc.uc_mcontext);
|
||||
if (ret == 0) {
|
||||
SIG_CANTMASK(uc.uc_sigmask);
|
||||
PROC_LOCK(td->td_proc);
|
||||
td->td_proc->p_sigmask = uc.uc_sigmask;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
swapcontext(struct thread *td, struct swapcontext_args *uap)
|
||||
{
|
||||
ucontext_t uc;
|
||||
int ret;
|
||||
|
||||
if (uap->oucp == NULL || uap->ucp == NULL)
|
||||
ret = EINVAL;
|
||||
else {
|
||||
get_mcontext(td, &uc.uc_mcontext);
|
||||
uc.uc_sigmask = td->td_proc->p_sigmask;
|
||||
ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
|
||||
if (ret == 0) {
|
||||
ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
|
||||
if (ret == 0) {
|
||||
ret = set_mcontext(td, &uc.uc_mcontext);
|
||||
if (ret == 0) {
|
||||
SIG_CANTMASK(uc.uc_sigmask);
|
||||
PROC_LOCK(td->td_proc);
|
||||
td->td_proc->p_sigmask = uc.uc_sigmask;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
@ -608,6 +608,10 @@
|
||||
418 UNIMPL BSD __xstat
|
||||
419 UNIMPL BSD __xfstat
|
||||
420 UNIMPL BSD __xlstat
|
||||
421 MSTD BSD { int getcontext(struct __ucontext *ucp); }
|
||||
422 MSTD BSD { int setcontext(const struct __ucontext *ucp); }
|
||||
423 MSTD BSD { int swapcontext(struct __ucontext *oucp, \
|
||||
const struct __ucontext *ucp); }
|
||||
|
||||
; Please copy any additions and changes to the following compatability tables:
|
||||
; sys/ia64/ia32/syscalls.master (take a best guess)
|
||||
|
@ -638,6 +638,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
int
|
||||
set_mcontext(struct thread *td, const mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
void
|
||||
cpu_boot(int howto)
|
||||
{
|
||||
|
@ -638,6 +638,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
int
|
||||
set_mcontext(struct thread *td, const mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
void
|
||||
cpu_boot(int howto)
|
||||
{
|
||||
|
@ -504,6 +504,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
get_mcontext(struct thread *td, mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
int
|
||||
set_mcontext(struct thread *td, const mcontext_t *mcp)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit the kernel and execute a firmware call that will not return, as
|
||||
* specified by the arguments.
|
||||
|
@ -79,6 +79,14 @@ int swapcontext(ucontext_t *, const ucontext_t *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#else /* _KERNEL */
|
||||
|
||||
struct thread;
|
||||
|
||||
/* Machine-dependent functions: */
|
||||
int get_mcontext(struct thread *td, mcontext_t *mcp);
|
||||
int set_mcontext(struct thread *td, const mcontext_t *mcp);
|
||||
|
||||
#endif /* !_KERNEL */
|
||||
|
||||
#endif /* !_SYS_UCONTEXT_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user