Module: xenomai-gch
Branch: for-forge
Commit: a25a33d0e033d76e6d3dcd0533f96fd8977a441f
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=a25a33d0e033d76e6d3dcd0533f96fd8977a441f

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

Reply via email to