162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __ASM_PREEMPT_H 362306a36Sopenharmony_ci#define __ASM_PREEMPT_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/thread_info.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define PREEMPT_ENABLED (0) 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistatic __always_inline int preempt_count(void) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci return READ_ONCE(current_thread_info()->preempt_count); 1262306a36Sopenharmony_ci} 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic __always_inline volatile int *preempt_count_ptr(void) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci return ¤t_thread_info()->preempt_count; 1762306a36Sopenharmony_ci} 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic __always_inline void preempt_count_set(int pc) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci *preempt_count_ptr() = pc; 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * must be macros to avoid header recursion hell 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci#define init_task_preempt_count(p) do { \ 2862306a36Sopenharmony_ci task_thread_info(p)->preempt_count = FORK_PREEMPT_COUNT; \ 2962306a36Sopenharmony_ci} while (0) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define init_idle_preempt_count(p, cpu) do { \ 3262306a36Sopenharmony_ci task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \ 3362306a36Sopenharmony_ci} while (0) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic __always_inline void set_preempt_need_resched(void) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic __always_inline void clear_preempt_need_resched(void) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic __always_inline bool test_preempt_need_resched(void) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return false; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * The various preempt_count add/sub methods 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic __always_inline void __preempt_count_add(int val) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci *preempt_count_ptr() += val; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic __always_inline void __preempt_count_sub(int val) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci *preempt_count_ptr() -= val; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic __always_inline bool __preempt_count_dec_and_test(void) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci /* 6562306a36Sopenharmony_ci * Because of load-store architectures cannot do per-cpu atomic 6662306a36Sopenharmony_ci * operations; we cannot use PREEMPT_NEED_RESCHED because it might get 6762306a36Sopenharmony_ci * lost. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci return !--*preempt_count_ptr() && tif_need_resched(); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * Returns true when we need to resched and can (barring IRQ state). 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_cistatic __always_inline bool should_resched(int preempt_offset) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci return unlikely(preempt_count() == preempt_offset && 7862306a36Sopenharmony_ci tif_need_resched()); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#ifdef CONFIG_PREEMPTION 8262306a36Sopenharmony_ciextern asmlinkage void preempt_schedule(void); 8362306a36Sopenharmony_ciextern asmlinkage void preempt_schedule_notrace(void); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#if defined(CONFIG_PREEMPT_DYNAMIC) && defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY) 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid dynamic_preempt_schedule(void); 8862306a36Sopenharmony_civoid dynamic_preempt_schedule_notrace(void); 8962306a36Sopenharmony_ci#define __preempt_schedule() dynamic_preempt_schedule() 9062306a36Sopenharmony_ci#define __preempt_schedule_notrace() dynamic_preempt_schedule_notrace() 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#else /* !CONFIG_PREEMPT_DYNAMIC || !CONFIG_HAVE_PREEMPT_DYNAMIC_KEY*/ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define __preempt_schedule() preempt_schedule() 9562306a36Sopenharmony_ci#define __preempt_schedule_notrace() preempt_schedule_notrace() 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#endif /* CONFIG_PREEMPT_DYNAMIC && CONFIG_HAVE_PREEMPT_DYNAMIC_KEY*/ 9862306a36Sopenharmony_ci#endif /* CONFIG_PREEMPTION */ 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#endif /* __ASM_PREEMPT_H */ 101