/* * Copyright 2017, Data61 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) * ABN 41 687 119 230. * * This software may be distributed and modified according to the terms of * the GNU General Public License version 2. Note that NO WARRANTY is provided. * See "LICENSE_GPLv2.txt" for details. * * @TAG(DATA61_GPL) */ #ifndef __MACHINE_FPU_H #define __MACHINE_FPU_H #include #include #include #include #ifdef CONFIG_HAVE_FPU /* Perform any actions required for the deletion of the given thread. */ void fpuThreadDelete(tcb_t *thread); /* Handle an FPU exception. */ exception_t handleFPUFault(void); void switchLocalFpuOwner(user_fpu_state_t *new_owner); /* Switch the current owner of the FPU state on the core specified by 'cpu'. */ void switchFpuOwner(user_fpu_state_t *new_owner, word_t cpu); /* Returns whether or not the passed thread is using the current active fpu state */ static inline bool_t nativeThreadUsingFPU(tcb_t *thread) { return &thread->tcbArch.tcbContext.fpuState == NODE_STATE_ON_CORE(ksActiveFPUState, thread->tcbAffinity); } static inline void FORCE_INLINE lazyFPURestore(tcb_t *thread) { if (unlikely(NODE_STATE(ksActiveFPUState))) { /* If we have enabled/disabled the FPU too many times without * someone else trying to use it, we assume it is no longer * in use and switch out its state. */ if (unlikely(NODE_STATE(ksFPURestoresSinceSwitch) > CONFIG_FPU_MAX_RESTORES_SINCE_SWITCH)) { switchLocalFpuOwner(NULL); NODE_STATE(ksFPURestoresSinceSwitch) = 0; } else { if (likely(nativeThreadUsingFPU(thread))) { /* We are using the FPU, make sure it is enabled */ enableFpu(); } else { /* Someone is using the FPU and it might be enabled */ disableFpu(); } NODE_STATE(ksFPURestoresSinceSwitch)++; } } else { /* No-one (including us) is using the FPU, so we assume it * is currently disabled */ } } #endif /* CONFIG_HAVE_FPU */ #endif /* __MACHINE_FPU_H */