diff options
Diffstat (limited to 'src/compat/simd/include/linux/simd.h')
-rw-r--r-- | src/compat/simd/include/linux/simd.h | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/src/compat/simd/include/linux/simd.h b/src/compat/simd/include/linux/simd.h index f31059d..1a0ecae 100644 --- a/src/compat/simd/include/linux/simd.h +++ b/src/compat/simd/include/linux/simd.h @@ -17,49 +17,61 @@ #endif typedef enum { - HAVE_NO_SIMD, - HAVE_FULL_SIMD + HAVE_NO_SIMD = 1 << 0, + HAVE_FULL_SIMD = 1 << 1, + HAVE_SIMD_IN_USE = 1 << 31 } simd_context_t; -static __must_check inline simd_context_t simd_get(void) +static inline void simd_get(simd_context_t *ctx) { bool have_simd = false; #if defined(CONFIG_X86_64) && !defined(CONFIG_UML) && !defined(CONFIG_PREEMPT_RT_BASE) have_simd = irq_fpu_usable(); - if (have_simd) - kernel_fpu_begin(); #elif IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !defined(CONFIG_PREEMPT_RT_BASE) #if defined(CONFIG_ARM64) have_simd = true; /* ARM64 supports NEON in any context. */ #elif defined(CONFIG_ARM) have_simd = may_use_simd(); /* ARM doesn't support NEON in interrupt context. */ #endif - if (have_simd) - kernel_neon_begin(); #endif - return have_simd ? HAVE_FULL_SIMD : HAVE_NO_SIMD; + *ctx = have_simd ? HAVE_FULL_SIMD : HAVE_NO_SIMD; } -static inline void simd_put(simd_context_t prior_context) +static inline void simd_put(simd_context_t *ctx) { #if defined(CONFIG_X86_64) && !defined(CONFIG_UML) && !defined(CONFIG_PREEMPT_RT_BASE) - if (prior_context != HAVE_NO_SIMD) + if (*ctx & HAVE_SIMD_IN_USE) kernel_fpu_end(); #elif IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !defined(CONFIG_PREEMPT_RT_BASE) - if (prior_context != HAVE_NO_SIMD) + if (*ctx & HAVE_SIMD_IN_USE) kernel_neon_end(); #endif + *ctx = HAVE_NO_SIMD; } -static __must_check inline simd_context_t simd_relax(simd_context_t prior_context) +static inline void simd_relax(simd_context_t *ctx) { #ifdef CONFIG_PREEMPT - if (prior_context != HAVE_NO_SIMD && need_resched()) { - simd_put(prior_context); - return simd_get(); + if ((*ctx & HAVE_SIMD_IN_USE) && need_resched()) { + simd_put(ctx); + simd_get(ctx); } #endif - return prior_context; +} + +static __must_check inline bool simd_use(simd_context_t *ctx) +{ + if (!(*ctx & HAVE_FULL_SIMD)) + return false; + if (*ctx & HAVE_SIMD_IN_USE) + return true; +#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) && !defined(CONFIG_PREEMPT_RT_BASE) + kernel_fpu_begin(); +#elif IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !defined(CONFIG_PREEMPT_RT_BASE) + kernel_neon_begin(); +#endif + *ctx |= HAVE_SIMD_IN_USE; + return true; } #endif /* _WG_SIMD_H */ |