aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal.c
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2007-03-09 11:07:45 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-03-16 21:03:26 -0400
commit53dc80287da43b75df2fe2658651d3c5160dad8e (patch)
tree3c4c97534c379709cd2a1dae5b90df626349f21d /arch/mips/kernel/signal.c
parentc6a2f4679331206ef5d353fc9a6cda2fa4aef8c6 (diff)
[MIPS] FPU ownership management & preemption fixes
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r--arch/mips/kernel/signal.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index bf094fc4c7eb..8c3c5a5789b0 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -82,6 +82,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
82{ 82{
83 int err = 0; 83 int err = 0;
84 int i; 84 int i;
85 unsigned int used_math;
85 86
86 err |= __put_user(regs->cp0_epc, &sc->sc_pc); 87 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
87 88
@@ -104,22 +105,18 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
104 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); 105 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
105 } 106 }
106 107
107 err |= __put_user(!!used_math(), &sc->sc_used_math); 108 used_math = !!used_math();
109 err |= __put_user(used_math, &sc->sc_used_math);
108 110
109 if (used_math()) { 111 if (used_math) {
110 /* 112 /*
111 * Save FPU state to signal context. Signal handler 113 * Save FPU state to signal context. Signal handler
112 * will "inherit" current FPU state. 114 * will "inherit" current FPU state.
113 */ 115 */
114 preempt_disable(); 116 own_fpu(1);
115 117 enable_fp_in_kernel();
116 if (!is_fpu_owner()) {
117 own_fpu();
118 restore_fp(current);
119 }
120 err |= save_fp_context(sc); 118 err |= save_fp_context(sc);
121 119 disable_fp_in_kernel();
122 preempt_enable();
123 } 120 }
124 return err; 121 return err;
125} 122}
@@ -188,20 +185,18 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
188 err |= __get_user(used_math, &sc->sc_used_math); 185 err |= __get_user(used_math, &sc->sc_used_math);
189 conditional_used_math(used_math); 186 conditional_used_math(used_math);
190 187
191 preempt_disable(); 188 if (used_math) {
192
193 if (used_math()) {
194 /* restore fpu context if we have used it before */ 189 /* restore fpu context if we have used it before */
195 own_fpu(); 190 own_fpu(0);
191 enable_fp_in_kernel();
196 if (!err) 192 if (!err)
197 err = check_and_restore_fp_context(sc); 193 err = check_and_restore_fp_context(sc);
194 disable_fp_in_kernel();
198 } else { 195 } else {
199 /* signal handler may have used FPU. Give it up. */ 196 /* signal handler may have used FPU. Give it up. */
200 lose_fpu(); 197 lose_fpu(0);
201 } 198 }
202 199
203 preempt_enable();
204
205 return err; 200 return err;
206} 201}
207 202