diff options
author | marcel <marcel@FreeBSD.org> | 2009-10-31 22:27:31 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2009-10-31 22:27:31 +0000 |
commit | 943e1b107a9100189f9c88ee1313ce81a7ed1ba5 (patch) | |
tree | cbe2460180af94e36765a193aa0c297777924c50 /sys/ia64/ia64/machdep.c | |
parent | 113d2ed8a6d71af32a5432b6d3892b57eaf4f0cc (diff) | |
download | FreeBSD-src-943e1b107a9100189f9c88ee1313ce81a7ed1ba5.zip FreeBSD-src-943e1b107a9100189f9c88ee1313ce81a7ed1ba5.tar.gz |
Reimplement the lazy FP context switching:
o Move all code into a single file for easier maintenance.
o Use a single global lock to avoid having to handle either
multiple locks or race conditions.
o Make sure to disable the high FP registers after saving
or dropping them.
o use msleep() to wait for the other CPU to save the high
FP registers.
This change fixes the high FP inconsistency panics.
A single global lock typically serializes too much, which may
be noticable when a lot of threads use the high FP registers,
but in that case it's probably better to switch the high FP
context synchronuously. Put differently: cpu_switch() should
switch the high FP registers if the incoming and outgoing
threads both use the high FP registers.
Diffstat (limited to 'sys/ia64/ia64/machdep.c')
-rw-r--r-- | sys/ia64/ia64/machdep.c | 75 |
1 files changed, 0 insertions, 75 deletions
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 299c9ec..e578e8b 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1461,81 +1461,6 @@ set_fpregs(struct thread *td, struct fpreg *fpregs) return (0); } -/* - * High FP register functions. - */ - -int -ia64_highfp_drop(struct thread *td) -{ - struct pcb *pcb; - struct pcpu *cpu; - struct thread *thr; - - mtx_lock_spin(&td->td_md.md_highfp_mtx); - pcb = td->td_pcb; - cpu = pcb->pcb_fpcpu; - if (cpu == NULL) { - mtx_unlock_spin(&td->td_md.md_highfp_mtx); - return (0); - } - pcb->pcb_fpcpu = NULL; - thr = cpu->pc_fpcurthread; - cpu->pc_fpcurthread = NULL; - mtx_unlock_spin(&td->td_md.md_highfp_mtx); - - /* Post-mortem sanity checking. */ - KASSERT(thr == td, ("Inconsistent high FP state")); - return (1); -} - -int -ia64_highfp_save(struct thread *td) -{ - struct pcb *pcb; - struct pcpu *cpu; - struct thread *thr; - - /* Don't save if the high FP registers weren't modified. */ - if ((td->td_frame->tf_special.psr & IA64_PSR_MFH) == 0) - return (ia64_highfp_drop(td)); - - mtx_lock_spin(&td->td_md.md_highfp_mtx); - pcb = td->td_pcb; - cpu = pcb->pcb_fpcpu; - if (cpu == NULL) { - mtx_unlock_spin(&td->td_md.md_highfp_mtx); - return (0); - } -#ifdef SMP - if (td == curthread) - sched_pin(); - if (cpu != pcpup) { - mtx_unlock_spin(&td->td_md.md_highfp_mtx); - ipi_send(cpu, IPI_HIGH_FP); - if (td == curthread) - sched_unpin(); - while (pcb->pcb_fpcpu == cpu) - DELAY(100); - return (1); - } else { - save_high_fp(&pcb->pcb_high_fp); - if (td == curthread) - sched_unpin(); - } -#else - save_high_fp(&pcb->pcb_high_fp); -#endif - pcb->pcb_fpcpu = NULL; - thr = cpu->pc_fpcurthread; - cpu->pc_fpcurthread = NULL; - mtx_unlock_spin(&td->td_md.md_highfp_mtx); - - /* Post-mortem sanity cxhecking. */ - KASSERT(thr == td, ("Inconsistent high FP state")); - return (1); -} - void ia64_sync_icache(vm_offset_t va, vm_offset_t sz) { |