Skip to content

Commit 3f27c0d

Browse files
committed
Merge branch 'timers-for-linus-clocksource' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-for-linus-clocksource' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: clocksource: prevent selection of low resolution clocksourse also for nohz=on clocksource: sanity check sysfs clocksource changes
2 parents 9aaa630 + cd6d95d commit 3f27c0d

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

include/linux/tick.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ extern void tick_clock_notify(void);
9797
extern int tick_check_oneshot_change(int allow_nohz);
9898
extern struct tick_sched *tick_get_tick_sched(int cpu);
9999
extern void tick_check_idle(int cpu);
100+
extern int tick_oneshot_mode_active(void);
100101
# else
101102
static inline void tick_clock_notify(void) { }
102103
static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
103104
static inline void tick_check_idle(int cpu) { }
105+
static inline int tick_oneshot_mode_active(void) { return 0; }
104106
# endif
105107

106108
#else /* CONFIG_GENERIC_CLOCKEVENTS */
@@ -109,6 +111,7 @@ static inline void tick_cancel_sched_timer(int cpu) { }
109111
static inline void tick_clock_notify(void) { }
110112
static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
111113
static inline void tick_check_idle(int cpu) { }
114+
static inline int tick_oneshot_mode_active(void) { return 0; }
112115
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
113116

114117
# ifdef CONFIG_NO_HZ

kernel/time/clocksource.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,18 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
509509
}
510510
}
511511

512+
/*
513+
* Check to make sure we don't switch to a non-highres capable
514+
* clocksource if the tick code is in oneshot mode (highres or nohz)
515+
*/
516+
if (tick_oneshot_mode_active() &&
517+
!(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
518+
printk(KERN_WARNING "%s clocksource is not HRT compatible. "
519+
"Cannot switch while in HRT/NOHZ mode\n", ovr->name);
520+
ovr = NULL;
521+
override_name[0] = 0;
522+
}
523+
512524
/* Reselect, when the override name has changed */
513525
if (ovr != clocksource_override) {
514526
clocksource_override = ovr;
@@ -537,7 +549,13 @@ sysfs_show_available_clocksources(struct sys_device *dev,
537549

538550
spin_lock_irq(&clocksource_lock);
539551
list_for_each_entry(src, &clocksource_list, list) {
540-
count += snprintf(buf + count,
552+
/*
553+
* Don't show non-HRES clocksource if the tick code is
554+
* in one shot mode (highres=on or nohz=on)
555+
*/
556+
if (!tick_oneshot_mode_active() ||
557+
(src->flags & CLOCK_SOURCE_VALID_FOR_HRES))
558+
count += snprintf(buf + count,
541559
max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
542560
"%s ", src->name);
543561
}

kernel/time/tick-oneshot.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,23 @@ int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
128128
return 0;
129129
}
130130

131+
/**
132+
* tick_check_oneshot_mode - check whether the system is in oneshot mode
133+
*
134+
* returns 1 when either nohz or highres are enabled. otherwise 0.
135+
*/
136+
int tick_oneshot_mode_active(void)
137+
{
138+
unsigned long flags;
139+
int ret;
140+
141+
local_irq_save(flags);
142+
ret = __get_cpu_var(tick_cpu_device).mode == TICKDEV_MODE_ONESHOT;
143+
local_irq_restore(flags);
144+
145+
return ret;
146+
}
147+
131148
#ifdef CONFIG_HIGH_RES_TIMERS
132149
/**
133150
* tick_init_highres - switch to high resolution mode

0 commit comments

Comments
 (0)