summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2006-04-06 15:27:09 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2006-04-06 15:27:09 +0000
commitd8c358abd593fb8b8b617f4c7ce2f993c0dae841 (patch)
tree6ecd2876630fea5bbd8c60d4cf5b47117190f964 /lib
parent8b3aa91606f1bfd08b3f0d13f6751920bff9500d (diff)
- due to the fninit() in _thread_machdep_save_float_state() all calls to
it need to be matched with a call to _thread_machdep_restore_float_state(), so add missing one in _thread_machdep_init(). - 16-byte align fp frame - call fwait() before save and and after restoring fp state. lots of guidance and ok mickey@
Diffstat (limited to 'lib')
-rw-r--r--lib/libpthread/arch/i386/uthread_machdep.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/libpthread/arch/i386/uthread_machdep.c b/lib/libpthread/arch/i386/uthread_machdep.c
index c8d55941300..42c8f52774a 100644
--- a/lib/libpthread/arch/i386/uthread_machdep.c
+++ b/lib/libpthread/arch/i386/uthread_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_machdep.c,v 1.4 2004/02/21 22:55:20 deraadt Exp $ */
+/* $OpenBSD: uthread_machdep.c,v 1.5 2006/04/06 15:27:08 kurt Exp $ */
/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
/*
@@ -66,7 +66,7 @@ _thread_machdep_init(struct _machdep_state* statep, void *base, int len,
struct frame *f;
/* Locate the initial frame, aligned at the top of the stack */
- f = (struct frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+ f = (struct frame *)(((int)base + len - sizeof *f) & ~15);
/* Set up initial frame */
f->fr_esp = (int)&f->fr_edi;
@@ -81,6 +81,15 @@ _thread_machdep_init(struct _machdep_state* statep, void *base, int len,
statep->esp = (int)f;
_thread_machdep_save_float_state(statep);
+ /*
+ * The current thread float state is saved into the new thread stack.
+ * Later pthread_create calls _thread_kern_sched which saves the current
+ * thread float state again into its own stack. However all float state
+ * saves must be balanced with a restore on i386 due to the fninit().
+ * Restore the current thread float state here so that the next save
+ * gets the correct state.
+ */
+ _thread_machdep_restore_float_state(statep);
}
/*
@@ -101,6 +110,7 @@ _thread_machdep_save_float_state(struct _machdep_state *ms)
union savefpu *addr = &ms->fpreg;
if (_thread_machdep_osfxsr()) {
+ fwait();
fxsave(&addr->sv_xmm);
fninit();
} else
@@ -113,9 +123,10 @@ _thread_machdep_restore_float_state(struct _machdep_state *ms)
{
union savefpu *addr = &ms->fpreg;
- if (_thread_machdep_osfxsr())
+ if (_thread_machdep_osfxsr()) {
fxrstor(&addr->sv_xmm);
- else
+ fwait();
+ } else
frstor(&addr->sv_87);
-
+
}