linux-mips
[Top] [All Lists]

[PATCH 04/15] mips: don't require FPU on sigcontext setup/restore

To: <linux-mips@linux-mips.org>
Subject: [PATCH 04/15] mips: don't require FPU on sigcontext setup/restore
From: Paul Burton <paul.burton@imgtec.com>
Date: Mon, 27 Jan 2014 15:23:03 +0000
Cc: Paul Burton <paul.burton@imgtec.com>
In-reply-to: <1390836194-26286-1-git-send-email-paul.burton@imgtec.com>
List-archive: <http://www.linux-mips.org/archives/linux-mips/>
List-help: <mailto:ecartis@linux-mips.org?Subject=help>
List-id: linux-mips <linux-mips.eddie.linux-mips.org>
List-owner: <mailto:ralf@linux-mips.org>
List-post: <mailto:linux-mips@linux-mips.org>
List-software: Ecartis version 1.0.0
List-subscribe: <mailto:ecartis@linux-mips.org?subject=subscribe%20linux-mips>
List-unsubscribe: <mailto:ecartis@linux-mips.org?subject=unsubscribe%20linux-mips>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <1390836194-26286-1-git-send-email-paul.burton@imgtec.com>
Sender: linux-mips-bounce@linux-mips.org
When a task which has used the FPU at some point in its past takes a
signal the kernel would previously always require the task to take
ownership of the FPU whilst setting up or restoring from the sigcontext.
That means that if the task has not used the FPU within this timeslice
then the kernel would enable the FPU, restore the task's FP context into
FPU registers and then save them into the sigcontext. This seems
inefficient, and if the signal handler doesn't use FP then enabling the
FPU & the extra memory accesses are entirely wasted work.

This patch modifies the sigcontext setup & restore code to copy directly
between the tasks saved FP context & the sigcontext for any tasks which
have used FP in the past but are not currently the FPU owner (ie. have
not used FP in this timeslice).

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
---
 arch/mips/kernel/signal.c   | 22 ++++++++++++++--------
 arch/mips/kernel/signal32.c | 22 ++++++++++++++--------
 2 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index b7e4614..e0178e1 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -102,10 +102,13 @@ static int protected_save_fp_context(struct sigcontext 
__user *sc)
        int err;
        while (1) {
                lock_fpu_owner();
-               err = own_fpu_inatomic(1);
-               if (!err)
-                       err = save_fp_context(sc); /* this might fail */
-               unlock_fpu_owner();
+               if (is_fpu_owner()) {
+                       err = save_fp_context(sc);
+                       unlock_fpu_owner();
+               } else {
+                       unlock_fpu_owner();
+                       err = copy_fp_to_sigcontext(sc);
+               }
                if (likely(!err))
                        break;
                /* touch the sigcontext and try again */
@@ -123,10 +126,13 @@ static int protected_restore_fp_context(struct sigcontext 
__user *sc)
        int err, tmp __maybe_unused;
        while (1) {
                lock_fpu_owner();
-               err = own_fpu_inatomic(0);
-               if (!err)
-                       err = restore_fp_context(sc); /* this might fail */
-               unlock_fpu_owner();
+               if (is_fpu_owner()) {
+                       err = restore_fp_context(sc);
+                       unlock_fpu_owner();
+               } else {
+                       unlock_fpu_owner();
+                       err = copy_fp_from_sigcontext(sc);
+               }
                if (likely(!err))
                        break;
                /* touch the sigcontext and try again */
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index dc09206..aec5821 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -118,10 +118,13 @@ static int protected_save_fp_context32(struct 
sigcontext32 __user *sc)
        int err;
        while (1) {
                lock_fpu_owner();
-               err = own_fpu_inatomic(1);
-               if (!err)
-                       err = save_fp_context32(sc); /* this might fail */
-               unlock_fpu_owner();
+               if (is_fpu_owner()) {
+                       err = save_fp_context32(sc);
+                       unlock_fpu_owner();
+               } else {
+                       unlock_fpu_owner();
+                       err = copy_fp_to_sigcontext32(sc);
+               }
                if (likely(!err))
                        break;
                /* touch the sigcontext and try again */
@@ -139,10 +142,13 @@ static int protected_restore_fp_context32(struct 
sigcontext32 __user *sc)
        int err, tmp __maybe_unused;
        while (1) {
                lock_fpu_owner();
-               err = own_fpu_inatomic(0);
-               if (!err)
-                       err = restore_fp_context32(sc); /* this might fail */
-               unlock_fpu_owner();
+               if (is_fpu_owner()) {
+                       err = restore_fp_context32(sc);
+                       unlock_fpu_owner();
+               } else {
+                       unlock_fpu_owner();
+                       err = copy_fp_from_sigcontext32(sc);
+               }
                if (likely(!err))
                        break;
                /* touch the sigcontext and try again */
-- 
1.8.5.3



<Prev in Thread] Current Thread [Next in Thread>