0001
0002 #ifndef __ASM_PREEMPT_H
0003 #define __ASM_PREEMPT_H
0004
0005 #include <linux/jump_label.h>
0006 #include <linux/thread_info.h>
0007
0008 #define PREEMPT_NEED_RESCHED BIT(32)
0009 #define PREEMPT_ENABLED (PREEMPT_NEED_RESCHED)
0010
0011 static inline int preempt_count(void)
0012 {
0013 return READ_ONCE(current_thread_info()->preempt.count);
0014 }
0015
0016 static inline void preempt_count_set(u64 pc)
0017 {
0018
0019 WRITE_ONCE(current_thread_info()->preempt.count, pc);
0020 }
0021
0022 #define init_task_preempt_count(p) do { \
0023 task_thread_info(p)->preempt_count = FORK_PREEMPT_COUNT; \
0024 } while (0)
0025
0026 #define init_idle_preempt_count(p, cpu) do { \
0027 task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \
0028 } while (0)
0029
0030 static inline void set_preempt_need_resched(void)
0031 {
0032 current_thread_info()->preempt.need_resched = 0;
0033 }
0034
0035 static inline void clear_preempt_need_resched(void)
0036 {
0037 current_thread_info()->preempt.need_resched = 1;
0038 }
0039
0040 static inline bool test_preempt_need_resched(void)
0041 {
0042 return !current_thread_info()->preempt.need_resched;
0043 }
0044
0045 static inline void __preempt_count_add(int val)
0046 {
0047 u32 pc = READ_ONCE(current_thread_info()->preempt.count);
0048 pc += val;
0049 WRITE_ONCE(current_thread_info()->preempt.count, pc);
0050 }
0051
0052 static inline void __preempt_count_sub(int val)
0053 {
0054 u32 pc = READ_ONCE(current_thread_info()->preempt.count);
0055 pc -= val;
0056 WRITE_ONCE(current_thread_info()->preempt.count, pc);
0057 }
0058
0059 static inline bool __preempt_count_dec_and_test(void)
0060 {
0061 struct thread_info *ti = current_thread_info();
0062 u64 pc = READ_ONCE(ti->preempt_count);
0063
0064
0065 WRITE_ONCE(ti->preempt.count, --pc);
0066
0067
0068
0069
0070
0071
0072
0073
0074 return !pc || !READ_ONCE(ti->preempt_count);
0075 }
0076
0077 static inline bool should_resched(int preempt_offset)
0078 {
0079 u64 pc = READ_ONCE(current_thread_info()->preempt_count);
0080 return pc == preempt_offset;
0081 }
0082
0083 #ifdef CONFIG_PREEMPTION
0084
0085 void preempt_schedule(void);
0086 void preempt_schedule_notrace(void);
0087
0088 #ifdef CONFIG_PREEMPT_DYNAMIC
0089
0090 DECLARE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched);
0091 void dynamic_preempt_schedule(void);
0092 #define __preempt_schedule() dynamic_preempt_schedule()
0093 void dynamic_preempt_schedule_notrace(void);
0094 #define __preempt_schedule_notrace() dynamic_preempt_schedule_notrace()
0095
0096 #else
0097
0098 #define __preempt_schedule() preempt_schedule()
0099 #define __preempt_schedule_notrace() preempt_schedule_notrace()
0100
0101 #endif
0102 #endif
0103
0104 #endif