diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2006-04-06 15:27:09 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2006-04-06 15:27:09 +0000 |
commit | d8c358abd593fb8b8b617f4c7ce2f993c0dae841 (patch) | |
tree | 6ecd2876630fea5bbd8c60d4cf5b47117190f964 /lib | |
parent | 8b3aa91606f1bfd08b3f0d13f6751920bff9500d (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.c | 21 |
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); - + } |