linux-mips-fnet
[Top] [All Lists]

FPU context management problem

To: linux-mips@oss.sgi.com, linux-mips@fnet.fr
Subject: FPU context management problem
From: Atsushi Nemoto <nemoto@toshiba-tops.co.jp>
Date: Tue, 19 Sep 2000 14:52:07 +0900
Organization: TOSHIBA Personal Computer System Corporation
I'm running kernel 2.2.14 (based on linux-2.2.14-000715.tar.gz) and
found a floating point calculation sometimes results an incorrect
value.

I think the problem is last 'if' statement in setup_sigcontext().

        owned_fp = (current == last_task_used_math);
        err |= __put_user(owned_fp, &sc->sc_ownedfp);

        if (current->used_math) {       /* fp is active.  */
                set_cp0_status(ST0_CU1, ST0_CU1);
                err |= save_fp_context(sc);
                last_task_used_math = NULL;
                regs->cp0_status &= ~ST0_CU1;
                current->used_math = 0;
        }

This code can discard other task's FPU context in certain situations.
The scenario is:

(-2) Task_A executes FP insns.
(-1) Task_B executes FP insns.
(0) Task_C executes FP insns.
# save Task_B's FPU context.
# init Task_C's FPU context.
(1) Context switch (Task_C to Task_A).
(2) Task_A catch a signal.
    setup_sigcontext() and restore_sigcontext() is called.
# Task_A's used_math was 1 and owned_fp was 0,
# so last_task_used_math becomes NULL.
(3) Context switch (Task_A to Task_B).
(4) Task_B executes FP insns.
# restore Task_B's FPU context. (discard Task_C's FPU context)
(5) Context switch (Task_B to Task_C).
(6) Task_C execute FP insns.  (with Task_B's FPU context!)


I modified the 'if' statement as follows and the problem seems to be
fixed.

        if (owned_fp) { /* fp is active.  */
                ...
        }

Is this the right fix?

---
Atsushi Nemoto

<Prev in Thread] Current Thread [Next in Thread>
  • FPU context management problem, Atsushi Nemoto <=