Skip to content

Commit 7988e5a

Browse files
Frederic WeisbeckerKAGA-KOKO
authored andcommitted
tick: Split nohz and highres features from nohz_mode
The nohz mode field tells about low resolution nohz mode or high resolution nohz mode but it doesn't tell about high resolution non-nohz mode. In order to retrieve the latter state, tick_cancel_sched_timer() must fiddle with struct hrtimer's internals to guess if the tick has been initialized in high resolution. Move instead the nohz mode field information into the tick flags and provide two new bits: one to know if the tick is in nohz mode and another one to know if the tick is in high resolution. The combination of those two flags provides all the needed informations to determine which of the three tick modes is running. Signed-off-by: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20240225225508.11587-14-frederic@kernel.org
1 parent a478ffb commit 7988e5a

File tree

4 files changed

+26
-26
lines changed

4 files changed

+26
-26
lines changed

kernel/time/hrtimer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ static void hrtimer_switch_to_hres(void)
747747
base->hres_active = 1;
748748
hrtimer_resolution = HIGH_RES_NSEC;
749749

750-
tick_setup_sched_timer(NOHZ_MODE_HIGHRES);
750+
tick_setup_sched_timer(true);
751751
/* "Retrigger" the interrupt to get things going */
752752
retrigger_next_event(NULL);
753753
}

kernel/time/tick-sched.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
831831
/* Forward the time to expire in the future */
832832
hrtimer_forward(&ts->sched_timer, now, TICK_NSEC);
833833

834-
if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
834+
if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES)) {
835835
hrtimer_start_expires(&ts->sched_timer,
836836
HRTIMER_MODE_ABS_PINNED_HARD);
837837
} else {
@@ -1040,14 +1040,14 @@ static void tick_nohz_stop_tick(struct tick_sched *ts, int cpu)
10401040
* the tick timer.
10411041
*/
10421042
if (unlikely(expires == KTIME_MAX)) {
1043-
if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
1043+
if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES))
10441044
hrtimer_cancel(&ts->sched_timer);
10451045
else
10461046
tick_program_event(KTIME_MAX, 1);
10471047
return;
10481048
}
10491049

1050-
if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
1050+
if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES)) {
10511051
hrtimer_start(&ts->sched_timer, expires,
10521052
HRTIMER_MODE_ABS_PINNED_HARD);
10531053
} else {
@@ -1108,7 +1108,7 @@ static void tick_nohz_full_update_tick(struct tick_sched *ts)
11081108
if (!tick_nohz_full_cpu(smp_processor_id()))
11091109
return;
11101110

1111-
if (ts->nohz_mode == NOHZ_MODE_INACTIVE)
1111+
if (!tick_sched_flag_test(ts, TS_FLAG_NOHZ))
11121112
return;
11131113

11141114
__tick_nohz_full_update_tick(ts, ktime_get());
@@ -1168,7 +1168,7 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
11681168
return false;
11691169
}
11701170

1171-
if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
1171+
if (unlikely(!tick_sched_flag_test(ts, TS_FLAG_NOHZ)))
11721172
return false;
11731173

11741174
if (need_resched())
@@ -1487,11 +1487,11 @@ static void tick_nohz_lowres_handler(struct clock_event_device *dev)
14871487
tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
14881488
}
14891489

1490-
static inline void tick_nohz_activate(struct tick_sched *ts, int mode)
1490+
static inline void tick_nohz_activate(struct tick_sched *ts)
14911491
{
14921492
if (!tick_nohz_enabled)
14931493
return;
1494-
ts->nohz_mode = mode;
1494+
tick_sched_flag_set(ts, TS_FLAG_NOHZ);
14951495
/* One update is enough */
14961496
if (!test_and_set_bit(0, &tick_nohz_active))
14971497
timers_update_nohz();
@@ -1512,7 +1512,7 @@ static void tick_nohz_switch_to_nohz(void)
15121512
* Recycle the hrtimer in 'ts', so we can share the
15131513
* highres code.
15141514
*/
1515-
tick_setup_sched_timer(NOHZ_MODE_LOWRES);
1515+
tick_setup_sched_timer(false);
15161516
}
15171517

15181518
static inline void tick_nohz_irq_enter(void)
@@ -1540,7 +1540,7 @@ static inline void tick_nohz_irq_enter(void)
15401540

15411541
static inline void tick_nohz_switch_to_nohz(void) { }
15421542
static inline void tick_nohz_irq_enter(void) { }
1543-
static inline void tick_nohz_activate(struct tick_sched *ts, int mode) { }
1543+
static inline void tick_nohz_activate(struct tick_sched *ts) { }
15441544

15451545
#endif /* CONFIG_NO_HZ_COMMON */
15461546

@@ -1567,15 +1567,17 @@ early_param("skew_tick", skew_tick);
15671567
* tick_setup_sched_timer - setup the tick emulation timer
15681568
* @mode: tick_nohz_mode to setup for
15691569
*/
1570-
void tick_setup_sched_timer(int mode)
1570+
void tick_setup_sched_timer(bool hrtimer)
15711571
{
15721572
struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
15731573

15741574
/* Emulate tick processing via per-CPU hrtimers: */
15751575
hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
15761576

1577-
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && mode == NOHZ_MODE_HIGHRES)
1577+
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && hrtimer) {
1578+
tick_sched_flag_set(ts, TS_FLAG_HIGHRES);
15781579
ts->sched_timer.function = tick_nohz_handler;
1580+
}
15791581

15801582
/* Get the next period (per-CPU) */
15811583
hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update());
@@ -1589,11 +1591,11 @@ void tick_setup_sched_timer(int mode)
15891591
}
15901592

15911593
hrtimer_forward_now(&ts->sched_timer, TICK_NSEC);
1592-
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && mode == NOHZ_MODE_HIGHRES)
1594+
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && hrtimer)
15931595
hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS_PINNED_HARD);
15941596
else
15951597
tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
1596-
tick_nohz_activate(ts, mode);
1598+
tick_nohz_activate(ts);
15971599
}
15981600

15991601
void tick_cancel_sched_timer(int cpu)
@@ -1602,7 +1604,7 @@ void tick_cancel_sched_timer(int cpu)
16021604
ktime_t idle_sleeptime, iowait_sleeptime;
16031605
unsigned long idle_calls, idle_sleeps;
16041606

1605-
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && ts->sched_timer.base)
1607+
if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES))
16061608
hrtimer_cancel(&ts->sched_timer);
16071609

16081610
idle_sleeptime = ts->idle_sleeptime;
@@ -1652,7 +1654,7 @@ int tick_check_oneshot_change(int allow_nohz)
16521654
if (!test_and_clear_bit(0, &ts->check_clocks))
16531655
return 0;
16541656

1655-
if (ts->nohz_mode != NOHZ_MODE_INACTIVE)
1657+
if (tick_sched_flag_test(ts, TS_FLAG_NOHZ))
16561658
return 0;
16571659

16581660
if (!timekeeping_valid_for_hres() || !tick_is_oneshot_available())

kernel/time/tick-sched.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@ struct tick_device {
1414
enum tick_device_mode mode;
1515
};
1616

17-
enum tick_nohz_mode {
18-
NOHZ_MODE_INACTIVE,
19-
NOHZ_MODE_LOWRES,
20-
NOHZ_MODE_HIGHRES,
21-
};
22-
2317
/* The CPU is in the tick idle mode */
2418
#define TS_FLAG_INIDLE BIT(0)
2519
/* The idle tick has been stopped */
@@ -31,6 +25,10 @@ enum tick_nohz_mode {
3125
#define TS_FLAG_IDLE_ACTIVE BIT(2)
3226
/* CPU was the last one doing do_timer before going idle */
3327
#define TS_FLAG_DO_TIMER_LAST BIT(3)
28+
/* NO_HZ is enabled */
29+
#define TS_FLAG_NOHZ BIT(4)
30+
/* High resolution tick mode */
31+
#define TS_FLAG_HIGHRES BIT(5)
3432

3533
/**
3634
* struct tick_sched - sched tick emulation and no idle tick control/stats
@@ -84,7 +82,6 @@ struct tick_sched {
8482
ktime_t idle_entrytime;
8583

8684
/* Tick stop */
87-
enum tick_nohz_mode nohz_mode;
8885
unsigned long last_jiffies;
8986
u64 timer_expires_base;
9087
u64 timer_expires;
@@ -107,7 +104,7 @@ struct tick_sched {
107104

108105
extern struct tick_sched *tick_get_tick_sched(int cpu);
109106

110-
extern void tick_setup_sched_timer(int mode);
107+
extern void tick_setup_sched_timer(bool hrtimer);
111108
#if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
112109
extern void tick_cancel_sched_timer(int cpu);
113110
#else

kernel/time/timer_list.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
152152

153153
{
154154
struct tick_sched *ts = tick_get_tick_sched(cpu);
155-
P(nohz_mode);
155+
P_flag(nohz, TS_FLAG_NOHZ);
156+
P_flag(highres, TS_FLAG_HIGHRES);
156157
P_ns(last_tick);
157158
P_flag(tick_stopped, TS_FLAG_STOPPED);
158159
P(idle_jiffies);
@@ -259,7 +260,7 @@ static void timer_list_show_tickdevices_header(struct seq_file *m)
259260

260261
static inline void timer_list_header(struct seq_file *m, u64 now)
261262
{
262-
SEQ_printf(m, "Timer List Version: v0.9\n");
263+
SEQ_printf(m, "Timer List Version: v0.10\n");
263264
SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
264265
SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
265266
SEQ_printf(m, "\n");

0 commit comments

Comments
 (0)