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 &current_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