summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-05-28 02:03:13 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-05-28 02:03:13 +0000
commitbf6b4844d33a45b13bd4ffe69857c1b47fba93b4 (patch)
treea9d0c54100cd9435a1b34d1ae77128d74763952c /sys/i386
parentfecc90c6467c0c3892b79f81ed9501a4672c8815 (diff)
downloadFreeBSD-src-bf6b4844d33a45b13bd4ffe69857c1b47fba93b4.zip
FreeBSD-src-bf6b4844d33a45b13bd4ffe69857c1b47fba93b4.tar.gz
When creating a new thread, inherit floating-point environment from
current thread, this is required by POSIX pthread_create document.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/vm_machdep.c1
-rw-r--r--sys/i386/include/npx.h4
-rw-r--r--sys/i386/isa/npx.c30
3 files changed, 35 insertions, 0 deletions
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 26ed735..8ddc0a3 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -394,6 +394,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
*/
bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
pcb2->pcb_flags &= ~(PCB_NPXTRAP|PCB_NPXINITDONE);
+ npx_fork_thread(td0, td);
/*
* Create a new fresh stack for the new thread.
diff --git a/sys/i386/include/npx.h b/sys/i386/include/npx.h
index 894b06d..792f75a 100644
--- a/sys/i386/include/npx.h
+++ b/sys/i386/include/npx.h
@@ -138,6 +138,8 @@ union savefpu {
#ifdef _KERNEL
+struct thread;
+
#define IO_NPX 0x0F0 /* Numeric Coprocessor */
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
@@ -155,6 +157,8 @@ void npxinit(u_short control);
void npxsave(union savefpu *addr);
void npxsetregs(struct thread *td, union savefpu *addr);
int npxtrap(void);
+void npx_fork_thread(struct thread *td, struct thread *newtd);
+
#endif
#endif /* !_MACHINE_NPX_H_ */
diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c
index bc39629..7b7f3a5 100644
--- a/sys/i386/isa/npx.c
+++ b/sys/i386/isa/npx.c
@@ -942,6 +942,36 @@ npxsetregs(td, addr)
curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE;
}
+/*
+ * POSIX requires new thread to inherit floating-point environment.
+ */
+void
+npx_fork_thread(struct thread *td, struct thread *newtd)
+{
+ union savefpu *state;
+ u_int32_t mxcsr;
+ u_int32_t cw;
+
+ state = &newtd->td_pcb->pcb_save;
+ /* get control word */
+ if (npxgetregs(td, &newtd->td_pcb->pcb_save))
+ return;
+ if (cpu_fxsr) {
+ mxcsr = state->sv_xmm.sv_env.en_mxcsr;
+ cw = state->sv_xmm.sv_env.en_cw;
+ } else {
+ cw = state->sv_87.sv_env.en_cw;
+ mxcsr = 0;
+ }
+ bcopy(&npx_cleanstate, state, sizeof(*state));
+ if (cpu_fxsr) {
+ state->sv_xmm.sv_env.en_cw = cw;
+ state->sv_xmm.sv_env.en_mxcsr = mxcsr;
+ } else
+ state->sv_87.sv_env.en_cw = cw;
+ newtd->td_pcb->pcb_flags |= PCB_NPXINITDONE;
+}
+
static void
fpusave(addr)
union savefpu *addr;
OpenPOWER on IntegriCloud