tick.h 9.6 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3
/*
 * Tick related global functions
4 5 6 7 8
 */
#ifndef _LINUX_TICK_H
#define _LINUX_TICK_H

#include <linux/clockchips.h>
9
#include <linux/irqflags.h>
10
#include <linux/percpu.h>
11 12
#include <linux/context_tracking_state.h>
#include <linux/cpumask.h>
13
#include <linux/sched.h>
14
#include <linux/rcupdate.h>
15

16 17
#ifdef CONFIG_GENERIC_CLOCKEVENTS
extern void __init tick_init(void);
18 19 20
/* Should be core only, but ARM BL switcher requires it */
extern void tick_suspend_local(void);
/* Should be core only, but XEN resume magic and ARM BL switcher require it */
21
extern void tick_resume_local(void);
22
extern void tick_handover_do_timer(void);
23
extern void tick_cleanup_dead_cpu(int cpu);
24 25
#else /* CONFIG_GENERIC_CLOCKEVENTS */
static inline void tick_init(void) { }
26
static inline void tick_suspend_local(void) { }
27
static inline void tick_resume_local(void) { }
28
static inline void tick_handover_do_timer(void) { }
29
static inline void tick_cleanup_dead_cpu(int cpu) { }
30
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
31

32 33 34 35 36 37 38 39
#if defined(CONFIG_GENERIC_CLOCKEVENTS) && defined(CONFIG_SUSPEND)
extern void tick_freeze(void);
extern void tick_unfreeze(void);
#else
static inline void tick_freeze(void) { }
static inline void tick_unfreeze(void) { }
#endif

40
#ifdef CONFIG_TICK_ONESHOT
41
extern void tick_irq_enter(void);
42
#  ifndef arch_needs_cpu
43
#   define arch_needs_cpu() (0)
44
#  endif
45
# else
46
static inline void tick_irq_enter(void) { }
47
#endif
48

49 50 51 52 53 54
#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
extern void hotplug_cpu__broadcast_tick_pull(int dead_cpu);
#else
static inline void hotplug_cpu__broadcast_tick_pull(int dead_cpu) { }
#endif

55 56 57 58 59 60
enum tick_broadcast_mode {
	TICK_BROADCAST_OFF,
	TICK_BROADCAST_ON,
	TICK_BROADCAST_FORCE,
};

61 62 63 64 65
enum tick_broadcast_state {
	TICK_BROADCAST_EXIT,
	TICK_BROADCAST_ENTER,
};

66 67 68 69 70 71
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
extern void tick_broadcast_control(enum tick_broadcast_mode mode);
#else
static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { }
#endif /* BROADCAST */

72 73 74 75 76 77
#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_HOTPLUG_CPU)
extern void tick_offline_cpu(unsigned int cpu);
#else
static inline void tick_offline_cpu(unsigned int cpu) { }
#endif

78
#ifdef CONFIG_GENERIC_CLOCKEVENTS
79
extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state);
80 81 82 83 84 85
#else
static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state)
{
	return 0;
}
#endif
86

87 88 89 90 91 92 93 94 95 96 97 98
static inline void tick_broadcast_enable(void)
{
	tick_broadcast_control(TICK_BROADCAST_ON);
}
static inline void tick_broadcast_disable(void)
{
	tick_broadcast_control(TICK_BROADCAST_OFF);
}
static inline void tick_broadcast_force(void)
{
	tick_broadcast_control(TICK_BROADCAST_FORCE);
}
99 100 101 102 103 104 105 106
static inline int tick_broadcast_enter(void)
{
	return tick_broadcast_oneshot_control(TICK_BROADCAST_ENTER);
}
static inline void tick_broadcast_exit(void)
{
	tick_broadcast_oneshot_control(TICK_BROADCAST_EXIT);
}
107

108 109 110 111
enum tick_dep_bits {
	TICK_DEP_BIT_POSIX_TIMER	= 0,
	TICK_DEP_BIT_PERF_EVENTS	= 1,
	TICK_DEP_BIT_SCHED		= 2,
F
Frederic Weisbecker 已提交
112
	TICK_DEP_BIT_CLOCK_UNSTABLE	= 3,
113 114
	TICK_DEP_BIT_RCU		= 4,
	TICK_DEP_BIT_RCU_EXP		= 5
115
};
116
#define TICK_DEP_BIT_MAX TICK_DEP_BIT_RCU_EXP
117

118
#define TICK_DEP_MASK_NONE		0
119 120 121 122
#define TICK_DEP_MASK_POSIX_TIMER	(1 << TICK_DEP_BIT_POSIX_TIMER)
#define TICK_DEP_MASK_PERF_EVENTS	(1 << TICK_DEP_BIT_PERF_EVENTS)
#define TICK_DEP_MASK_SCHED		(1 << TICK_DEP_BIT_SCHED)
#define TICK_DEP_MASK_CLOCK_UNSTABLE	(1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
F
Frederic Weisbecker 已提交
123
#define TICK_DEP_MASK_RCU		(1 << TICK_DEP_BIT_RCU)
124
#define TICK_DEP_MASK_RCU_EXP		(1 << TICK_DEP_BIT_RCU_EXP)
125

126
#ifdef CONFIG_NO_HZ_COMMON
127
extern bool tick_nohz_enabled;
128
extern bool tick_nohz_tick_stopped(void);
129
extern bool tick_nohz_tick_stopped_cpu(int cpu);
130
extern void tick_nohz_idle_stop_tick(void);
131
extern void tick_nohz_idle_retain_tick(void);
132
extern void tick_nohz_idle_restart_tick(void);
133
extern void tick_nohz_idle_enter(void);
134 135
extern void tick_nohz_idle_exit(void);
extern void tick_nohz_irq_exit(void);
136
extern bool tick_nohz_idle_got_tick(void);
137
extern ktime_t tick_nohz_get_next_hrtimer(void);
138
extern ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next);
139
extern unsigned long tick_nohz_get_idle_calls(void);
140
extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu);
141
extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
142
extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
143 144 145 146 147 148 149 150

static inline void tick_nohz_idle_stop_tick_protected(void)
{
	local_irq_disable();
	tick_nohz_idle_stop_tick();
	local_irq_enable();
}

151
#else /* !CONFIG_NO_HZ_COMMON */
152
#define tick_nohz_enabled (0)
153
static inline int tick_nohz_tick_stopped(void) { return 0; }
154
static inline int tick_nohz_tick_stopped_cpu(int cpu) { return 0; }
155
static inline void tick_nohz_idle_stop_tick(void) { }
156
static inline void tick_nohz_idle_retain_tick(void) { }
157
static inline void tick_nohz_idle_restart_tick(void) { }
158 159
static inline void tick_nohz_idle_enter(void) { }
static inline void tick_nohz_idle_exit(void) { }
160
static inline bool tick_nohz_idle_got_tick(void) { return false; }
161 162 163 164 165
static inline ktime_t tick_nohz_get_next_hrtimer(void)
{
	/* Next wake up is the tick period, assume it starts now */
	return ktime_add(ktime_get(), TICK_NSEC);
}
166
static inline ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next)
167
{
168 169
	*delta_next = TICK_NSEC;
	return *delta_next;
170
}
171
static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
172
static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
173 174

static inline void tick_nohz_idle_stop_tick_protected(void) { }
175
#endif /* !CONFIG_NO_HZ_COMMON */
176

177
#ifdef CONFIG_NO_HZ_FULL
178 179 180 181 182
extern bool tick_nohz_full_running;
extern cpumask_var_t tick_nohz_full_mask;

static inline bool tick_nohz_full_enabled(void)
{
183
	if (!context_tracking_enabled())
184 185 186 187 188 189 190 191 192 193 194 195 196
		return false;

	return tick_nohz_full_running;
}

static inline bool tick_nohz_full_cpu(int cpu)
{
	if (!tick_nohz_full_enabled())
		return false;

	return cpumask_test_cpu(cpu, tick_nohz_full_mask);
}

197 198 199 200 201 202
static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask)
{
	if (tick_nohz_full_enabled())
		cpumask_or(mask, mask, tick_nohz_full_mask);
}

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
extern void tick_nohz_dep_set(enum tick_dep_bits bit);
extern void tick_nohz_dep_clear(enum tick_dep_bits bit);
extern void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit);
extern void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit);
extern void tick_nohz_dep_set_task(struct task_struct *tsk,
				   enum tick_dep_bits bit);
extern void tick_nohz_dep_clear_task(struct task_struct *tsk,
				     enum tick_dep_bits bit);
extern void tick_nohz_dep_set_signal(struct signal_struct *signal,
				     enum tick_dep_bits bit);
extern void tick_nohz_dep_clear_signal(struct signal_struct *signal,
				       enum tick_dep_bits bit);

/*
 * The below are tick_nohz_[set,clear]_dep() wrappers that optimize off-cases
 * on top of static keys.
 */
static inline void tick_dep_set(enum tick_dep_bits bit)
{
	if (tick_nohz_full_enabled())
		tick_nohz_dep_set(bit);
}

static inline void tick_dep_clear(enum tick_dep_bits bit)
{
	if (tick_nohz_full_enabled())
		tick_nohz_dep_clear(bit);
}

static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit)
{
	if (tick_nohz_full_cpu(cpu))
		tick_nohz_dep_set_cpu(cpu, bit);
}

static inline void tick_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
{
	if (tick_nohz_full_cpu(cpu))
		tick_nohz_dep_clear_cpu(cpu, bit);
}

static inline void tick_dep_set_task(struct task_struct *tsk,
				     enum tick_dep_bits bit)
{
	if (tick_nohz_full_enabled())
		tick_nohz_dep_set_task(tsk, bit);
}
static inline void tick_dep_clear_task(struct task_struct *tsk,
				       enum tick_dep_bits bit)
{
	if (tick_nohz_full_enabled())
		tick_nohz_dep_clear_task(tsk, bit);
}
static inline void tick_dep_set_signal(struct signal_struct *signal,
				       enum tick_dep_bits bit)
{
	if (tick_nohz_full_enabled())
		tick_nohz_dep_set_signal(signal, bit);
}
static inline void tick_dep_clear_signal(struct signal_struct *signal,
					 enum tick_dep_bits bit)
{
	if (tick_nohz_full_enabled())
		tick_nohz_dep_clear_signal(signal, bit);
}

269
extern void tick_nohz_full_kick_cpu(int cpu);
270
extern void __tick_nohz_task_switch(void);
271
extern void __init tick_nohz_full_setup(cpumask_var_t cpumask);
272
#else
273 274
static inline bool tick_nohz_full_enabled(void) { return false; }
static inline bool tick_nohz_full_cpu(int cpu) { return false; }
275
static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
276

F
Frederic Weisbecker 已提交
277 278 279
static inline void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
static inline void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit) { }

280 281 282 283 284 285 286 287 288 289 290 291 292
static inline void tick_dep_set(enum tick_dep_bits bit) { }
static inline void tick_dep_clear(enum tick_dep_bits bit) { }
static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
static inline void tick_dep_clear_cpu(int cpu, enum tick_dep_bits bit) { }
static inline void tick_dep_set_task(struct task_struct *tsk,
				     enum tick_dep_bits bit) { }
static inline void tick_dep_clear_task(struct task_struct *tsk,
				       enum tick_dep_bits bit) { }
static inline void tick_dep_set_signal(struct signal_struct *signal,
				       enum tick_dep_bits bit) { }
static inline void tick_dep_clear_signal(struct signal_struct *signal,
					 enum tick_dep_bits bit) { }

293
static inline void tick_nohz_full_kick_cpu(int cpu) { }
294
static inline void __tick_nohz_task_switch(void) { }
295
static inline void tick_nohz_full_setup(cpumask_var_t cpumask) { }
296 297
#endif

298
static inline void tick_nohz_task_switch(void)
299 300
{
	if (tick_nohz_full_enabled())
301
		__tick_nohz_task_switch();
302 303
}

304 305 306 307 308 309
static inline void tick_nohz_user_enter_prepare(void)
{
	if (tick_nohz_full_cpu(smp_processor_id()))
		rcu_nocb_flush_deferred_wakeup();
}

310
#endif