From bb459c6567e40d45ddb220fcea82296810094f19 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli <andrea@suse.de> Date: Tue, 1 Feb 2005 16:33:59 -0800 Subject: [PATCH] [PATCH] make used_math SMP-safe Convert the unsafe signed (16bit) used_math to a safe and optimal PF_USED_MATH I might have broken arm, see the very first change in the patch to asm-offsets.c, rest looks ok at first glance. If you want used_math to return 0 or 1 (instead of 0 or PF_USED_MATH), just s/!!// in the below patch and place !! in sched.h::*used_math() accordingly after applying the patch, it should work just fine. Using !! only when necessary as the below is optimal. From: Yoichi Yuasa <yuasa@hh.iij4u.or.jp> This patch had fixed restore_sigcontext/restore_sigcontext32 about MIPS. Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp> Signed-off-by: Andrea Arcangeli <andrea@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org> --- arch/arm26/kernel/asm-offsets.c | 1 - arch/arm26/kernel/process.c | 4 +-- arch/arm26/kernel/ptrace.c | 2 +- arch/i386/kernel/cpu/common.c | 2 +- arch/i386/kernel/i387.c | 15 ++++++------ arch/i386/kernel/process.c | 2 +- arch/i386/kernel/ptrace.c | 8 +++--- arch/i386/kernel/signal.c | 4 +-- arch/i386/kernel/traps.c | 2 +- arch/i386/math-emu/fpu_entry.c | 4 +-- arch/ia64/ia32/elfcore32.h | 4 +-- arch/m32r/kernel/ptrace.c | 8 +++--- arch/m32r/kernel/setup.c | 2 +- arch/mips/kernel/irixsig.c | 4 +-- arch/mips/kernel/process.c | 2 +- arch/mips/kernel/ptrace.c | 4 +-- arch/mips/kernel/ptrace32.c | 4 +-- arch/mips/kernel/signal.c | 10 +++++--- arch/mips/kernel/signal32.c | 10 +++++--- arch/mips/kernel/traps.c | 4 +-- arch/s390/kernel/process.c | 3 +-- arch/s390/kernel/setup.c | 2 +- arch/sh/kernel/cpu/init.c | 2 +- arch/sh/kernel/cpu/sh4/fpu.c | 4 +-- arch/sh/kernel/process.c | 8 +++--- arch/sh/kernel/ptrace.c | 8 +++--- arch/sh/kernel/signal.c | 8 +++--- arch/sh64/kernel/fpu.c | 4 +-- arch/sh64/kernel/process.c | 4 +-- arch/sh64/kernel/ptrace.c | 8 +++--- arch/sh64/kernel/signal.c | 6 ++--- arch/sparc/kernel/process.c | 2 +- arch/sparc/kernel/signal.c | 12 ++++----- arch/sparc/kernel/traps.c | 8 +++--- arch/x86_64/ia32/fpu32.c | 2 +- arch/x86_64/ia32/ia32_binfmt.c | 4 +-- arch/x86_64/ia32/ia32_signal.c | 6 ++--- arch/x86_64/ia32/ptrace32.c | 2 +- arch/x86_64/kernel/i387.c | 15 ++++++------ arch/x86_64/kernel/process.c | 2 +- arch/x86_64/kernel/ptrace.c | 2 +- arch/x86_64/kernel/signal.c | 6 ++--- arch/x86_64/kernel/traps.c | 2 +- include/asm-arm26/constants.h | 1 - include/asm-x86_64/i387.h | 10 -------- include/linux/sched.h | 43 +++++++++++++++++++++------------ 46 files changed, 138 insertions(+), 132 deletions(-) diff --git a/arch/arm26/kernel/asm-offsets.c b/arch/arm26/kernel/asm-offsets.c index b8d0442de9b5..4ccacaef94df 100644 --- a/arch/arm26/kernel/asm-offsets.c +++ b/arch/arm26/kernel/asm-offsets.c @@ -42,7 +42,6 @@ int main(void) { - DEFINE(TSK_USED_MATH, offsetof(struct task_struct, used_math)); DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c index efd30d5b83bd..46aea6ac194d 100644 --- a/arch/arm26/kernel/process.c +++ b/arch/arm26/kernel/process.c @@ -271,7 +271,7 @@ void flush_thread(void) memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); memset(&thread->fpstate, 0, sizeof(union fp_state)); - current->used_math = 0; + clear_used_math(); } void release_thread(struct task_struct *dead_task) @@ -305,7 +305,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { struct thread_info *thread = current_thread_info(); - int used_math = current->used_math; + int used_math = !!used_math(); if (used_math) memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 8597ab3574fe..2a137146a77c 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -540,7 +540,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) */ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { - tsk->used_math = 1; + set_stopped_child_used_math(tsk); return copy_from_user(&tsk->thread_info->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 264fcda7196f..026167739bfd 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -629,6 +629,6 @@ void __init cpu_init (void) * Force FPU initialization: */ current_thread_info()->status = 0; - current->used_math = 0; + clear_used_math(); mxcsr_feature_mask_init(); } diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c index 8ffed8a0b34a..5af8b683883d 100644 --- a/arch/i386/kernel/i387.c +++ b/arch/i386/kernel/i387.c @@ -60,7 +60,8 @@ void init_fpu(struct task_struct *tsk) tsk->thread.i387.fsave.twd = 0xffffffffu; tsk->thread.i387.fsave.fos = 0xffff0000u; } - tsk->used_math = 1; + /* only the device not available exception or ptrace can call init_fpu */ + set_stopped_child_used_math(tsk); } /* @@ -331,13 +332,13 @@ static int save_i387_fxsave( struct _fpstate __user *buf ) int save_i387( struct _fpstate __user *buf ) { - if ( !current->used_math ) + if ( !used_math() ) return 0; /* This will cause a "finit" to be triggered by the next * attempted FPU operation by the 'current' process. */ - current->used_math = 0; + clear_used_math(); if ( HAVE_HWFP ) { if ( cpu_has_fxsr ) { @@ -383,7 +384,7 @@ int restore_i387( struct _fpstate __user *buf ) } else { err = restore_i387_soft( ¤t->thread.i387.soft, buf ); } - current->used_math = 1; + set_used_math(); return err; } @@ -507,7 +508,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) int fpvalid; struct task_struct *tsk = current; - fpvalid = tsk->used_math; + fpvalid = !!used_math(); if ( fpvalid ) { unlazy_fpu( tsk ); if ( cpu_has_fxsr ) { @@ -522,7 +523,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) { - int fpvalid = tsk->used_math; + int fpvalid = !!tsk_used_math(tsk); if (fpvalid) { if (tsk == current) @@ -537,7 +538,7 @@ int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) int dump_task_extended_fpu(struct task_struct *tsk, struct user_fxsr_struct *fpu) { - int fpvalid = tsk->used_math && cpu_has_fxsr; + int fpvalid = tsk_used_math(tsk) && cpu_has_fxsr; if (fpvalid) { if (tsk == current) diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index b5db26cbde87..28b0d7bf0a84 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -351,7 +351,7 @@ void flush_thread(void) * Forget coprocessor state.. */ clear_fpu(tsk); - tsk->used_math = 0; + clear_used_math(); } void release_thread(struct task_struct *dead_task) diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index dffd0c20f9ca..3985587e1cd2 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -592,7 +592,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) break; } ret = 0; - if (!child->used_math) + if (!tsk_used_math(child)) init_fpu(child); get_fpregs((struct user_i387_struct __user *)data, child); break; @@ -604,7 +604,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } - child->used_math = 1; + set_stopped_child_used_math(child); set_fpregs(child, (struct user_i387_struct __user *)data); ret = 0; break; @@ -616,7 +616,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } - if (!child->used_math) + if (!tsk_used_math(child)) init_fpu(child); ret = get_fpxregs((struct user_fxsr_struct __user *)data, child); break; @@ -628,7 +628,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } - child->used_math = 1; + set_stopped_child_used_math(child); ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data); break; } diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index a67849a83ff8..1e8b41ca083f 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -192,9 +192,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax err |= restore_i387(buf); } else { struct task_struct *me = current; - if (me->used_math) { + if (used_math()) { clear_fpu(me); - me->used_math = 0; + clear_used_math(); } } } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index bf616fd5ba41..065649245cde 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -911,7 +911,7 @@ asmlinkage void math_state_restore(struct pt_regs regs) struct task_struct *tsk = thread->task; clts(); /* Allow maths ops (or we recurse) */ - if (!tsk->used_math) + if (!tsk_used_math(tsk)) init_fpu(tsk); restore_fpu(tsk); thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c index 633f954c3450..4162c3c1454a 100644 --- a/arch/i386/math-emu/fpu_entry.c +++ b/arch/i386/math-emu/fpu_entry.c @@ -155,10 +155,10 @@ asmlinkage void math_emulate(long arg) RE_ENTRANT_CHECK_ON; #endif /* RE_ENTRANT_CHECKING */ - if (!current->used_math) + if (!used_math()) { finit(); - current->used_math = 1; + set_used_math(); } SETUP_DATA_AREA(arg); diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h index 31fbbcd6d8ee..b73b8b6b10c1 100644 --- a/arch/ia64/ia32/elfcore32.h +++ b/arch/ia64/ia32/elfcore32.h @@ -106,7 +106,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr struct ia32_user_i387_struct *fpstate = (void*)fpu; mm_segment_t old_fs; - if (!tsk->used_math) + if (!tsk_used_math(tsk)) return 0; old_fs = get_fs(); @@ -124,7 +124,7 @@ elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu) struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu; mm_segment_t old_fs; - if (!tsk->used_math) + if (!tsk_used_math(tsk)) return 0; old_fs = get_fs(); diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index c3e3c759abc3..8b40f362dd6f 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -130,7 +130,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, #ifndef NO_FPU else if (off >= (long)(&dummy->fpu >> 2) && off < (long)(&dummy->u_fpvalid >> 2)) { - if (!tsk->used_math) { + if (!tsk_used_math(tsk)) { if (off == (long)(&dummy->fpu.fpscr >> 2)) tmp = FPSCR_INIT; else @@ -139,7 +139,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, tmp = ((long *)(&tsk->thread.fpu >> 2)) [off - (long)&dummy->fpu]; } else if (off == (long)(&dummy->u_fpvalid >> 2)) - tmp = tsk->used_math; + tmp = !!tsk_used_math(tsk); #endif /* not NO_FPU */ else tmp = 0; @@ -187,12 +187,12 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off, #ifndef NO_FPU else if (off >= (long)(&dummy->fpu >> 2) && off < (long)(&dummy->u_fpvalid >> 2)) { - tsk->used_math = 1; + set_stopped_child_used_math(tsk); ((long *)&tsk->thread.fpu) [off - (long)&dummy->fpu] = data; ret = 0; } else if (off == (long)(&dummy->u_fpvalid >> 2)) { - tsk->used_math = data ? 1 : 0; + conditional_stopped_child_used_math(data, tsk); ret = 0; } #endif /* not NO_FPU */ diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index bde87d3aa921..fb03be1a0c94 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c @@ -391,7 +391,7 @@ void __init cpu_init (void) /* Force FPU initialization */ current_thread_info()->status = 0; - current->used_math = 0; + clear_used_math(); #ifdef CONFIG_MMU /* Set up MMU */ diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 5ad101c0c0a2..64d46091a60e 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -99,7 +99,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, __put_user((u64) regs->hi, &ctx->hi); __put_user((u64) regs->lo, &ctx->lo); __put_user((u64) regs->cp0_epc, &ctx->pc); - __put_user(current->used_math, &ctx->usedfp); + __put_user(!!used_math(), &ctx->usedfp); __put_user((u64) regs->cp0_cause, &ctx->cp0_cause); __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr); @@ -725,7 +725,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) __put_user(regs->cp0_epc, &ctx->regs[35]); flags = 0x0f; - if(!current->used_math) { + if(!used_math()) { flags &= ~(0x08); } else { /* XXX wheee... */ diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index fb76e458e340..4356713f2317 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -76,7 +76,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) #endif status |= KU_USER; regs->cp0_status = status; - current->used_math = 0; + clear_used_math(); lose_fpu(); regs->cp0_epc = pc; regs->regs[29] = sp; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 1ce7bd150940..bdfe1c4b2b80 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -119,7 +119,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) tmp = regs->regs[addr]; break; case FPR_BASE ... FPR_BASE + 31: - if (child->used_math) { + if (tsk_used_math(child)) { fpureg_t *fregs = get_fpu_regs(child); #ifdef CONFIG_MIPS32 @@ -205,7 +205,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case FPR_BASE ... FPR_BASE + 31: { fpureg_t *fregs = get_fpu_regs(child); - if (!child->used_math) { + if (!tsk_used_math(child)) { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, sizeof(child->thread.fpu.hard)); diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 799919d9beaa..611dee919d50 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -112,7 +112,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) tmp = regs->regs[addr]; break; case FPR_BASE ... FPR_BASE + 31: - if (child->used_math) { + if (tsk_used_math(child)) { fpureg_t *fregs = get_fpu_regs(child); /* @@ -193,7 +193,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) case FPR_BASE ... FPR_BASE + 31: { fpureg_t *fregs = get_fpu_regs(child); - if (!child->used_math) { + if (!tsk_used_math(child)) { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, sizeof(child->thread.fpu.hard)); diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 3e8e4e7e8580..5dc4f0fdb4f0 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -154,6 +154,7 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs) asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { int err = 0; + unsigned int used_math; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -178,11 +179,12 @@ asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) restore_gp_reg(31); #undef restore_gp_reg - err |= __get_user(current->used_math, &sc->sc_used_math); + err |= __get_user(used_math, &sc->sc_used_math); + conditional_used_math(used_math); preempt_disable(); - if (current->used_math) { + if (used_math()) { /* restore fpu context if we have used it before */ own_fpu(); err |= restore_fp_context(sc); @@ -323,9 +325,9 @@ inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - err |= __put_user(current->used_math, &sc->sc_used_math); + err |= __put_user(!!used_math(), &sc->sc_used_math); - if (!current->used_math) + if (!used_math()) goto out; /* diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 6c3d5097802c..1543cd463212 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -337,6 +337,7 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc) { int err = 0; + __u32 used_math; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -361,11 +362,12 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs, restore_gp_reg(31); #undef restore_gp_reg - err |= __get_user(current->used_math, &sc->sc_used_math); + err |= __get_user(used_math, &sc->sc_used_math); + conditional_used_math(used_math); preempt_disable(); - if (current->used_math) { + if (used_math()) { /* restore fpu context if we have used it before */ own_fpu(); err |= restore_fp_context32(sc); @@ -552,9 +554,9 @@ static inline int setup_sigcontext32(struct pt_regs *regs, err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - err |= __put_user(current->used_math, &sc->sc_used_math); + err |= __put_user(!!used_math(), &sc->sc_used_math); - if (!current->used_math) + if (!used_math()) goto out; /* diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b7cfe61394b9..d841a9588354 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -655,11 +655,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) preempt_disable(); own_fpu(); - if (current->used_math) { /* Using the FPU again. */ + if (used_math()) { /* Using the FPU again. */ restore_fp(current); } else { /* First time FPU user. */ init_fpu(); - current->used_math = 1; + set_used_math(); } if (!cpu_has_fpu) { diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 12b7ac948526..7aea25d6e300 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -215,8 +215,7 @@ void exit_thread(void) void flush_thread(void) { - - current->used_math = 0; + clear_used_math(); clear_tsk_thread_flag(current, TIF_USEDFPU); } diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 6fbc5279e4bb..adb32f2fa8a9 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -96,7 +96,7 @@ void __devinit cpu_init (void) * Force FPU initialization: */ clear_thread_flag(TIF_USEDFPU); - current->used_math = 0; + clear_used_math(); atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 352f71a10003..cf94e8ef17c5 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -194,7 +194,7 @@ asmlinkage void __init sh_cpu_init(void) /* FPU initialization */ if ((cpu_data->flags & CPU_HAS_FPU)) { clear_thread_flag(TIF_USEDFPU); - current->used_math = 0; + clear_used_math(); } #ifdef CONFIG_SH_DSP diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index fccc85eaff33..f486c07e10e2 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -323,13 +323,13 @@ do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, return; } - if (tsk->used_math) { + if (used_math()) { /* Using the FPU again. */ restore_fpu(tsk); } else { /* First time FPU user. */ fpu_init(); - tsk->used_math = 1; + set_used_math(); } set_tsk_thread_flag(tsk, TIF_USEDFPU); } diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 8e7eaf18a32c..3d024590c24e 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -208,7 +208,7 @@ void flush_thread(void) /* Forget lazy FPU state */ clear_fpu(tsk, regs); - tsk->used_math = 0; + clear_used_math(); #endif } @@ -225,7 +225,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) #if defined(CONFIG_SH_FPU) struct task_struct *tsk = current; - fpvalid = tsk->used_math; + fpvalid = !!tsk_used_math(tsk); if (fpvalid) { unlazy_fpu(tsk, regs); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); @@ -260,7 +260,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu) int fpvalid = 0; #if defined(CONFIG_SH_FPU) - fpvalid = tsk->used_math; + fpvalid = !!tsk_used_math(tsk); if (fpvalid) { struct pt_regs *regs = (struct pt_regs *) ((unsigned long)tsk->thread_info @@ -286,7 +286,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, unlazy_fpu(tsk, regs); p->thread.fpu = tsk->thread.fpu; - p->used_math = tsk->used_math; + copy_to_stopped_child_used_math(p); #endif childregs = ((struct pt_regs *) diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index d14810a459d9..35385c90064d 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -150,7 +150,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) tmp = get_stack_long(child, addr); else if (addr >= (long) &dummy->fpu && addr < (long) &dummy->u_fpvalid) { - if (!child->used_math) { + if (!tsk_used_math(child)) { if (addr == (long)&dummy->fpu.fpscr) tmp = FPSCR_INIT; else @@ -159,7 +159,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) tmp = ((long *)&child->thread.fpu) [(addr - (long)&dummy->fpu) >> 2]; } else if (addr == (long) &dummy->u_fpvalid) - tmp = child->used_math; + tmp = !!tsk_used_math(child); else tmp = 0; ret = put_user(tmp, (unsigned long *)data); @@ -185,12 +185,12 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = put_stack_long(child, addr, data); else if (addr >= (long) &dummy->fpu && addr < (long) &dummy->u_fpvalid) { - child->used_math = 1; + set_stopped_child_used_math(child); ((long *)&child->thread.fpu) [(addr - (long)&dummy->fpu) >> 2] = data; ret = 0; } else if (addr == (long) &dummy->u_fpvalid) { - child->used_math = data?1:0; + conditional_stopped_child_used_math(data, child); ret = 0; } break; diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index cec91c6b18c8..22e15018748a 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -162,7 +162,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) if (!(cpu_data->flags & CPU_HAS_FPU)) return 0; - tsk->used_math = 1; + set_used_math(); return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], sizeof(long)*(16*2+2)); } @@ -175,7 +175,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, if (!(cpu_data->flags & CPU_HAS_FPU)) return 0; - if (!tsk->used_math) { + if (!used_math()) { __put_user(0, &sc->sc_ownedfp); return 0; } @@ -185,7 +185,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. */ - tsk->used_math = 0; + clear_used_math(); unlazy_fpu(tsk, regs); return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, @@ -219,7 +219,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p regs->sr |= SR_FD; /* Release FPU */ clear_fpu(tsk, regs); - tsk->used_math = 0; + clear_used_math(); __get_user (owned_fp, &sc->sc_ownedfp); if (owned_fp) err |= restore_sigcontext_fpu(sc); diff --git a/arch/sh64/kernel/fpu.c b/arch/sh64/kernel/fpu.c index 175c88a5d3a3..8ad4ed6a6c9b 100644 --- a/arch/sh64/kernel/fpu.c +++ b/arch/sh64/kernel/fpu.c @@ -158,12 +158,12 @@ do_fpu_state_restore(unsigned long ex, struct pt_regs *regs) fpsave(&last_task_used_math->thread.fpu.hard); } last_task_used_math = current; - if (current->used_math) { + if (used_math()) { fpload(¤t->thread.fpu.hard); } else { /* First time FPU user. */ fpload(&init_fpuregs.hard); - current->used_math = 1; + set_used_math(); } release_fpu(); } diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index c482c3a682f1..e3f509ea6ec3 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -688,7 +688,7 @@ void flush_thread(void) last_task_used_math = NULL; } /* Force FPU state to be reinitialised after exec */ - current->used_math = 0; + clear_used_math(); #endif /* if we are a kernel thread, about to change to user thread, @@ -713,7 +713,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) int fpvalid; struct task_struct *tsk = current; - fpvalid = tsk->used_math; + fpvalid = !!tsk_used_math(tsk); if (fpvalid) { if (current == last_task_used_math) { grab_fpu(); diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index f27c696b3e00..27c1a32cc0ea 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -63,7 +63,7 @@ get_fpu_long(struct task_struct *task, unsigned long addr) struct pt_regs *regs; regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; - if (!task->used_math) { + if (!tsk_used_math(task)) { if (addr == offsetof(struct user_fpu_struct, fpscr)) { tmp = FPSCR_INIT; } else { @@ -105,9 +105,9 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; - if (!task->used_math) { + if (!tsk_used_math(task)) { fpinit(&task->thread.fpu.hard); - task->used_math = 1; + set_stopped_child_used_math(task); } else if (last_task_used_math == task) { grab_fpu(); fpsave(&task->thread.fpu.hard); @@ -187,7 +187,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) (addr < offsetof(struct user, u_fpvalid))) { tmp = get_fpu_long(child, addr - offsetof(struct user, fpu)); } else if (addr == offsetof(struct user, u_fpvalid)) { - tmp = child->used_math; + tmp = !!tsk_used_math(child); } else { break; } diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c index b9bb2dcc3172..608f6796a2e5 100644 --- a/arch/sh64/kernel/signal.c +++ b/arch/sh64/kernel/signal.c @@ -186,7 +186,7 @@ restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) int fpvalid; err |= __get_user (fpvalid, &sc->sc_fpvalid); - current->used_math = fpvalid; + conditional_used_math(fpvalid); if (! fpvalid) return err; @@ -207,7 +207,7 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) int err = 0; int fpvalid; - fpvalid = current->used_math; + fpvalid = !!used_math(); err |= __put_user(fpvalid, &sc->sc_fpvalid); if (! fpvalid) return err; @@ -222,7 +222,7 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) err |= __copy_to_user(&sc->sc_fpregs[0], ¤t->thread.fpu.hard, (sizeof(long long) * 32) + (sizeof(int) * 1)); - current->used_math = 0; + clear_used_math(); return err; } diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 0915e41b1e53..aadc6f7010ce 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -599,7 +599,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump) */ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) { - if (current->used_math == 0) { + if (used_math()) { memset(fpregs, 0, sizeof(*fpregs)); fpregs->pr_q_entrysize = 8; return 1; diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index df8936608763..203728dc64cd 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -202,7 +202,7 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) regs->psr &= ~PSR_EF; } #endif - current->used_math = 1; + set_used_math(); clear_tsk_thread_flag(current, TIF_USEDFPU); if (verify_area(VERIFY_READ, fpu, sizeof(*fpu))) @@ -584,7 +584,7 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) ¤t->thread.fpqueue[0], ((sizeof(unsigned long) + (sizeof(unsigned long *)))*16)); - current->used_math = 0; + clear_used_math(); return err; } @@ -599,7 +599,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, synchronize_user_stack(); sigframe_size = NF_ALIGNEDSZ; - if (!current->used_math) + if (!used_math()) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct new_signal_frame __user *) @@ -616,7 +616,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(0, &sf->extra_size); - if (current->used_math) { + if (used_math()) { err |= save_fpu_state(regs, &sf->fpu_state); err |= __put_user(&sf->fpu_state, &sf->fpu_save); } else { @@ -677,7 +677,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, synchronize_user_stack(); sigframe_size = RT_ALIGNEDSZ; - if (!current->used_math) + if (!used_math()) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct rt_signal_frame __user *) get_sigframe(&ka->sa, regs, sigframe_size); @@ -690,7 +690,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(regs->npc, &sf->regs.npc); err |= __put_user(regs->y, &sf->regs.y); psr = regs->psr; - if (current->used_math) + if (used_math()) psr |= PSR_EF; err |= __put_user(psr, &sf->regs.psr); err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs)); diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index ceb4a8f29abd..3f451ae66482 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -246,17 +246,17 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, &fptask->thread.fpqueue[0], &fptask->thread.fpqdepth); } last_task_used_math = current; - if(current->used_math) { + if(used_math()) { fpload(¤t->thread.float_regs[0], ¤t->thread.fsr); } else { /* Set initial sane state. */ fpload(&init_fregs[0], &init_fsr); - current->used_math = 1; + set_used_math(); } #else - if(!current->used_math) { + if(!used_math()) { fpload(&init_fregs[0], &init_fsr); - current->used_math = 1; + set_used_math(); } else { fpload(¤t->thread.float_regs[0], ¤t->thread.fsr); } diff --git a/arch/x86_64/ia32/fpu32.c b/arch/x86_64/ia32/fpu32.c index 1c7501967abd..1c23095f1813 100644 --- a/arch/x86_64/ia32/fpu32.c +++ b/arch/x86_64/ia32/fpu32.c @@ -157,7 +157,7 @@ int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf, sizeof(struct i387_fxsave_struct))) return -1; tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; - tsk->used_math = 1; + set_stopped_child_used_math(tsk); } return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf); } diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 2b69d92253f1..445717b9c66b 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -214,7 +214,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr struct _fpstate_ia32 *fpstate = (void*)fpu; mm_segment_t oldfs = get_fs(); - if (!tsk->used_math) + if (!tsk_used_math(tsk)) return 0; if (!regs) regs = (struct pt_regs *)tsk->thread.rsp0; @@ -235,7 +235,7 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) { struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1; - if (!t->used_math) + if (!tsk_used_math(t)) return 0; if (t == current) unlazy_fpu(t); diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 7b78206dd90b..4a4f27741fb2 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -263,9 +263,9 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, err |= restore_i387_ia32(current, buf, 0); } else { struct task_struct *me = current; - if (me->used_math) { + if (used_math()) { clear_fpu(me); - me->used_math = 0; + clear_used_math(); } } } @@ -389,7 +389,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ if (tmp < 0) err = -EFAULT; else { - current->used_math = 0; + clear_used_math(); stts(); err |= __put_user((u32)(u64)(tmp ? fpstate : NULL), &sc->fpstate); } diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 81d4a9883fe6..d2cd083b03b3 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -358,7 +358,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) break; /* no checking to be bug-to-bug compatible with i386 */ __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)); - child->used_math = 1; + set_stopped_child_used_math(child); child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; ret = 0; break; diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c index 6bc3d64e0095..ba139cac57ce 100644 --- a/arch/x86_64/kernel/i387.c +++ b/arch/x86_64/kernel/i387.c @@ -57,12 +57,12 @@ void __init fpu_init(void) mxcsr_feature_mask_init(); /* clean state in init */ current_thread_info()->status = 0; - current->used_math = 0; + clear_used_math(); } void init_fpu(struct task_struct *child) { - if (child->used_math) { + if (tsk_used_math(child)) { if (child == current) unlazy_fpu(child); return; @@ -70,7 +70,8 @@ void init_fpu(struct task_struct *child) memset(&child->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct)); child->thread.i387.fxsave.cwd = 0x37f; child->thread.i387.fxsave.mxcsr = 0x1f80; - child->used_math = 1; + /* only the device not available exception or ptrace can call init_fpu */ + set_stopped_child_used_math(child); } /* @@ -91,9 +92,9 @@ int save_i387(struct _fpstate __user *buf) if ((unsigned long)buf % 16) printk("save_i387: bad fpstate %p\n",buf); - if (!tsk->used_math) + if (!used_math()) return 0; - tsk->used_math = 0; /* trigger finit */ + clear_used_math(); /* trigger finit */ if (tsk->thread_info->status & TS_USEDFPU) { err = save_i387_checking((struct i387_fxsave_struct __user *)buf); if (err) return err; @@ -133,7 +134,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) { struct task_struct *tsk = current; - if (!tsk->used_math) + if (!used_math()) return 0; unlazy_fpu(tsk); @@ -143,7 +144,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) { - int fpvalid = tsk->used_math; + int fpvalid = !!tsk_used_math(tsk); if (fpvalid) { if (tsk == current) diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index ce2866d3dc0d..bbe26dda5e79 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -314,7 +314,7 @@ void flush_thread(void) * Forget coprocessor state.. */ clear_fpu(tsk); - tsk->used_math = 0; + clear_used_math(); } void release_thread(struct task_struct *dead_task) diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 17a4bd966213..eaa7250152f5 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -480,7 +480,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data ret = -EIO; break; } - child->used_math = 1; + set_stopped_child_used_math(child); ret = set_fpregs(child, (struct user_i387_struct __user *)data); break; } diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index 1cb237ad1fcc..9cf703827214 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -126,9 +126,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned err |= restore_i387(buf); } else { struct task_struct *me = current; - if (me->used_math) { + if (used_math()) { clear_fpu(me); - me->used_math = 0; + clear_used_math(); } } } @@ -251,7 +251,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int err = 0; struct task_struct *me = current; - if (me->used_math) { + if (used_math()) { fp = get_stack(ka, regs, sizeof(struct _fpstate)); frame = (void __user *)round_down((unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 10f635e15c2c..72e672ef3260 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -892,7 +892,7 @@ asmlinkage void math_state_restore(void) struct task_struct *me = current; clts(); /* Allow maths ops (or we recurse) */ - if (!me->used_math) + if (!used_math()) init_fpu(me); restore_fpu_checking(&me->thread.i387.fxsave); me->thread_info->status |= TS_USEDFPU; diff --git a/include/asm-arm26/constants.h b/include/asm-arm26/constants.h index 47c65cae7e6a..0d0b14415563 100644 --- a/include/asm-arm26/constants.h +++ b/include/asm-arm26/constants.h @@ -7,7 +7,6 @@ * */ -#define TSK_USED_MATH 788 /* offsetof(struct task_struct, used_math) */ #define TSK_ACTIVE_MM 96 /* offsetof(struct task_struct, active_mm) */ #define VMA_VM_MM 0 /* offsetof(struct vm_area_struct, vm_mm) */ diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h index e613b8b164e4..aa39cfd0e001 100644 --- a/include/asm-x86_64/i387.h +++ b/include/asm-x86_64/i387.h @@ -25,16 +25,6 @@ extern void mxcsr_feature_mask_init(void); extern void init_fpu(struct task_struct *child); extern int save_i387(struct _fpstate __user *buf); -static inline int need_signal_i387(struct task_struct *me) -{ - if (!me->used_math) - return 0; - me->used_math = 0; - if (me->thread_info->status & TS_USEDFPU) - return 0; - return 1; -} - /* * FPU lazy state save handling... */ diff --git a/include/linux/sched.h b/include/linux/sched.h index cf7394b25af5..1f4ccd433ce9 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -614,19 +614,7 @@ struct task_struct { struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */ struct key *thread_keyring; /* keyring private to this thread */ #endif -/* - * Must be changed atomically so it shouldn't be - * be a shareable bitflag. - */ - unsigned char used_math; -/* - * OOM kill score adjustment (bit shift). - * Cannot live together with used_math since - * used_math and oomkilladj can be changed at the - * same time, so they would race if they're in the - * same atomic block. - */ - short oomkilladj; + int oomkilladj; /* OOM kill score adjustment (bit shift). */ char comm[TASK_COMM_LEN]; /* file system info */ int link_count, total_link_count; @@ -695,7 +683,7 @@ struct task_struct { #endif #ifdef CONFIG_NUMA struct mempolicy *mempolicy; - short il_next; /* could be shared with used_math */ + short il_next; #endif }; @@ -737,7 +725,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_SIGNALED 0x00000400 /* killed by a signal */ #define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ - +#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ #define PF_FREEZE 0x00004000 /* this task is being frozen for suspend now */ #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ #define PF_FROZEN 0x00010000 /* frozen for system suspend */ @@ -748,6 +736,31 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ +/* + * Only the _current_ task can read/write to tsk->flags, but other + * tasks can access tsk->flags in readonly mode for example + * with tsk_used_math (like during threaded core dumping). + * There is however an exception to this rule during ptrace + * or during fork: the ptracer task is allowed to write to the + * child->flags of its traced child (same goes for fork, the parent + * can write to the child->flags), because we're guaranteed the + * child is not running and in turn not changing child->flags + * at the same time the parent does it. + */ +#define clear_stopped_child_used_math(child) do { (child)->flags &= ~PF_USED_MATH; } while (0) +#define set_stopped_child_used_math(child) do { (child)->flags |= PF_USED_MATH; } while (0) +#define clear_used_math() clear_stopped_child_used_math(current) +#define set_used_math() set_stopped_child_used_math(current) +#define conditional_stopped_child_used_math(condition, child) \ + do { (child)->flags &= ~PF_USED_MATH, (child)->flags |= (condition) ? PF_USED_MATH : 0; } while (0) +#define conditional_used_math(condition) \ + conditional_stopped_child_used_math(condition, current) +#define copy_to_stopped_child_used_math(child) \ + do { (child)->flags &= ~PF_USED_MATH, (child)->flags |= current->flags & PF_USED_MATH; } while (0) +/* NOTE: this will return 0 or PF_USED_MATH, it will never return 1 */ +#define tsk_used_math(p) ((p)->flags & PF_USED_MATH) +#define used_math() tsk_used_math(current) + #ifdef CONFIG_SMP extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); #else -- 2.30.9