1#ifndef __LINUX_PREEMPT_H 2#define __LINUX_PREEMPT_H 3 4/* 5 * include/linux/preempt.h - macros for accessing and manipulating 6 * preempt_count (used for kernel preemption, interrupt count, etc.) 7 */ 8 9#include <linux/thread_info.h> 10#include <linux/linkage.h> 11#include <linux/list.h> 12 13#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) 14 extern void add_preempt_count(int val); 15 extern void sub_preempt_count(int val); 16#else 17# define add_preempt_count(val) do { preempt_count() += (val); } while (0) 18# define sub_preempt_count(val) do { preempt_count() -= (val); } while (0) 19#endif 20 21#define inc_preempt_count() add_preempt_count(1) 22#define dec_preempt_count() sub_preempt_count(1) 23 24#define preempt_count() (current_thread_info()->preempt_count) 25 26#ifdef CONFIG_PREEMPT 27 28asmlinkage void preempt_schedule(void); 29 30#define preempt_check_resched() \ 31do { \ 32 if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ 33 preempt_schedule(); \ 34} while (0) 35 36#else /* !CONFIG_PREEMPT */ 37 38#define preempt_check_resched() do { } while (0) 39 40#endif /* CONFIG_PREEMPT */ 41 42 43#ifdef CONFIG_PREEMPT_COUNT 44 45#define preempt_disable() \ 46do { \ 47 inc_preempt_count(); \ 48 barrier(); \ 49} while (0) 50 51#define sched_preempt_enable_no_resched() \ 52do { \ 53 barrier(); \ 54 dec_preempt_count(); \ 55} while (0) 56 57#define preempt_enable_no_resched() sched_preempt_enable_no_resched() 58 59#define preempt_enable() \ 60do { \ 61 preempt_enable_no_resched(); \ 62 barrier(); \ 63 preempt_check_resched(); \ 64} while (0) 65 66/* For debugging and tracer internals only! */ 67#define add_preempt_count_notrace(val) \ 68 do { preempt_count() += (val); } while (0) 69#define sub_preempt_count_notrace(val) \ 70 do { preempt_count() -= (val); } while (0) 71#define inc_preempt_count_notrace() add_preempt_count_notrace(1) 72#define dec_preempt_count_notrace() sub_preempt_count_notrace(1) 73 74#define preempt_disable_notrace() \ 75do { \ 76 inc_preempt_count_notrace(); \ 77 barrier(); \ 78} while (0) 79 80#define preempt_enable_no_resched_notrace() \ 81do { \ 82 barrier(); \ 83 dec_preempt_count_notrace(); \ 84} while (0) 85 86/* preempt_check_resched is OK to trace */ 87#define preempt_enable_notrace() \ 88do { \ 89 preempt_enable_no_resched_notrace(); \ 90 barrier(); \ 91 preempt_check_resched(); \ 92} while (0) 93 94#else /* !CONFIG_PREEMPT_COUNT */ 95 96#define preempt_disable() do { } while (0) 97#define sched_preempt_enable_no_resched() do { } while (0) 98#define preempt_enable_no_resched() do { } while (0) 99#define preempt_enable() do { } while (0) 100 101#define preempt_disable_notrace() do { } while (0) 102#define preempt_enable_no_resched_notrace() do { } while (0) 103#define preempt_enable_notrace() do { } while (0) 104 105#endif /* CONFIG_PREEMPT_COUNT */ 106 107#ifdef CONFIG_PREEMPT_NOTIFIERS 108 109struct preempt_notifier; 110 111/** 112 * preempt_ops - notifiers called when a task is preempted and rescheduled 113 * @sched_in: we're about to be rescheduled: 114 * notifier: struct preempt_notifier for the task being scheduled 115 * cpu: cpu we're scheduled on 116 * @sched_out: we've just been preempted 117 * notifier: struct preempt_notifier for the task being preempted 118 * next: the task that's kicking us out 119 * 120 * Please note that sched_in and out are called under different 121 * contexts. sched_out is called with rq lock held and irq disabled 122 * while sched_in is called without rq lock and irq enabled. This 123 * difference is intentional and depended upon by its users. 124 */ 125struct preempt_ops { 126 void (*sched_in)(struct preempt_notifier *notifier, int cpu); 127 void (*sched_out)(struct preempt_notifier *notifier, 128 struct task_struct *next); 129}; 130 131/** 132 * preempt_notifier - key for installing preemption notifiers 133 * @link: internal use 134 * @ops: defines the notifier functions to be called 135 * 136 * Usually used in conjunction with container_of(). 137 */ 138struct preempt_notifier { 139 struct hlist_node link; 140 struct preempt_ops *ops; 141}; 142 143void preempt_notifier_register(struct preempt_notifier *notifier); 144void preempt_notifier_unregister(struct preempt_notifier *notifier); 145 146static inline void preempt_notifier_init(struct preempt_notifier *notifier, 147 struct preempt_ops *ops) 148{ 149 INIT_HLIST_NODE(¬ifier->link); 150 notifier->ops = ops; 151} 152 153#endif 154 155#endif /* __LINUX_PREEMPT_H */ 156