Module: xenomai-gch Branch: for-forge Commit: dec18d7dfa7981ff7c2d7414ea30db968a86136c URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=dec18d7dfa7981ff7c2d7414ea30db968a86136c
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Fri Oct 25 21:53:56 2013 +0200 cobalt/x86: lazy FPU switching Only enable XNFPU on first FPU use. Skip context restore with fxsr when context allows it. --- kernel/cobalt/arch/x86/thread.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/kernel/cobalt/arch/x86/thread.c b/kernel/cobalt/arch/x86/thread.c index 1bbac8a..d181d60 100644 --- a/kernel/cobalt/arch/x86/thread.c +++ b/kernel/cobalt/arch/x86/thread.c @@ -225,7 +225,7 @@ int xnarch_handle_fpu_fault(struct xnthread *from, struct xnarchtcb *tcb = xnthread_archtcb(to); struct task_struct *p = tcb->core.host_task; - if (tsk_used_math(p)) + if (wrap_test_fpu_used(p)) return 0; /* @@ -243,6 +243,7 @@ int xnarch_handle_fpu_fault(struct xnthread *from, set_stopped_child_used_math(p); wrap_set_fpu_used(p); + xnthread_set_state(to, XNFPU); return 1; } @@ -273,10 +274,9 @@ void xnarch_save_fpu(struct xnthread *thread) struct task_struct *p = tcb->core.host_task; if (wrap_test_fpu_used(p) == 0) - /* Common case: already saved by __switch_to */ + /* Saved by last __switch_to */ return; - /* Exceptional case: a migrating thread */ clts(); __do_save_i387(x86_fpustate_ptr(&p->thread)); @@ -287,11 +287,24 @@ void xnarch_switch_fpu(struct xnthread *from, struct xnthread *thread) { struct xnarchtcb *tcb = xnthread_archtcb(thread); struct task_struct *p = tcb->core.host_task; + const unsigned root_kfpu = tcb->root_kfpu; + unsigned do_restore; - if (tcb->root_kfpu == 0 && - (tsk_used_math(p) == 0 || xnthread_test_state(thread, XNROOT))) + if (root_kfpu == 0) { /* Restore lazy mode */ - return; + if (xnthread_test_state(thread, XNROOT)) + return; + + /* + * If we never switched fpu, and the cpu has fxsr, the + * last context switch saved fpu but did not + * reinitialize it, so we can simply reenable fpu + */ + do_restore = (from != thread && + (!from || from->tcb.fpup != thread->tcb.fpup)) || + cpu_has_fxsr == 0; + } else + do_restore = 1; /* * Restore the FPU hardware with valid fp registers from a @@ -299,8 +312,9 @@ void xnarch_switch_fpu(struct xnthread *from, struct xnthread *thread) */ clts(); - __do_restore_i387(x86_fpustate_ptr(&p->thread)); - if (tcb->root_kfpu) { + if (do_restore) + __do_restore_i387(x86_fpustate_ptr(&p->thread)); + if (root_kfpu) { x86_fpustate_ptr(&p->thread) = tcb->fpup; wrap_clear_fpu_used(p); if (tcb->root_used_math == 0) @@ -335,6 +349,9 @@ void xnarch_init_shadow_tcb(struct xnthread *thread) #endif tcb->fpup = x86_fpustate_ptr(&p->thread); tcb->root_kfpu = 0; + + /* XNFPU is set upon first FPU fault */ + xnthread_clear_state(thread, XNFPU); } int xnarch_escalate(void) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git