Skip to contentSkip to conversation

clocksource update v12

PATCH In review Daniel Walker 3 participants 57 messages Jan 31, 2007 4 messages not in the archive

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

cover clocksource update v12

This tree is mostly cleanups . I move timekeeping code into it's own file, and I modify the clocksource interface to provide a more robust API.

I've dropped some duplication off the hrt/dynamic tick patch set which is all new to that tree and new to -mm. This is an -mm patch set , it's not meant to go on 2.6.20-rc6 at all .. I'm modifying code only included in -mm.

I boot tested x86_64 smp, and i386 smp, and compile tested for ARM (!GENERIC_TIME). This set should be bisect-able for at least i386 and likely x86_64.

It's also available at,

ftp://source.mvista.com/pub/dwalker/clocksource/clocksource-v12/

Daniel

#1 lore raw

PATCH 1/23 clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch

Drop.

---
 kernel/time/clocksource.c |   11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)
kernel/time/clocksource.c +1 -10
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -28,7 +28,6 @@
 #include <linux/sysdev.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/tick.h>
 
 /* XXX - Would like a better way for initializing curr_clocksource */
 extern struct clocksource clocksource_jiffies;
@@ -107,16 +106,8 @@ static void clocksource_watchdog(unsigne
 		/* Initialized ? */
 		if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
 			if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
-			    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
+			    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS))
 				cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-				/*
-				 * We just marked the clocksource as
-				 * highres-capable, notify the rest of the
-				 * system as well so that we transition
-				 * into high-res mode:
-				 */
-				tick_clock_notify();
-			}
 			cs->flags |= CLOCK_SOURCE_WATCHDOG;
 			cs->wd_last = csnow;
 		} else {
#2 lore raw

Re: [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch

Quoted 1 line · Daniel Walker

Drop.

i'm summarily replying to your 4 'Drop' patches: what you didnt explain is /why/ you dropped these patches. I.e. why you think they are bad and how you think your solution is better. Without doing such analysis you shouldnt just be dropping patches of others like this.

Ingo

#3 lore raw

PATCH 2/23 clocksource: drop clocksource-add-verification-watchdog-helper.patch

In reply to Daniel Walker

Drop.

---
 arch/i386/Kconfig           |    4 -
 arch/i386/kernel/tsc.c      |   49 +++++++++++++++++
 include/linux/clocksource.h |   15 -----
 kernel/time/clocksource.c   |  125 +-------------------------------------------
 kernel/timer.c              |   48 ++++++++--------
 5 files changed, 79 insertions(+), 162 deletions(-)
arch/i386/Kconfig +0 -4
Index: linux-2.6.19/arch/i386/Kconfig
===================================================================
@@ -18,10 +18,6 @@ config GENERIC_TIME
 	bool
 	default y
 
-config CLOCKSOURCE_WATCHDOG
-	bool
-	default y
-
 config GENERIC_CLOCKEVENTS
 	bool
 	default y
arch/i386/kernel/tsc.c +49 -0

61 lines not on this page · raw message

include/linux/clocksource.h +2 -13
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -12,13 +12,11 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
-#include <linux/timer.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 
 /* clocksource cycle base type */
 typedef u64 cycle_t;
-struct clocksource;
 
 /**
  * struct clocksource - hardware abstraction for a free running counter
@@ -66,22 +64,13 @@ struct clocksource {
 	cycle_t cycle_last, cycle_interval;
 	u64 xtime_nsec, xtime_interval;
 	s64 error;
-
-#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
-	/* Watchdog related data, used by the framework */
-	struct list_head wd_list;
-	cycle_t wd_last;
-#endif
 };
 
 /*
  * Clock source flags bits::
  */
-#define CLOCK_SOURCE_IS_CONTINUOUS		0x01
-#define CLOCK_SOURCE_MUST_VERIFY		0x02
-
-#define CLOCK_SOURCE_WATCHDOG			0x10
-#define CLOCK_SOURCE_VALID_FOR_HRES		0x20
+#define CLOCK_SOURCE_IS_CONTINUOUS	0x01
+#define CLOCK_SOURCE_MUST_VERIFY	0x02
 
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
kernel/time/clocksource.c +4 -121

161 lines not on this page · raw message

kernel/timer.c +24 -24

73 lines not on this page · raw message

#4 lore raw

PATCH 3/23 clocksource: drop clocksource-remove-the-update-callback.patch

In reply to Daniel Walker

Drop.

---
 arch/i386/kernel/tsc.c      |   51 +++++++++++++++++++++++++++++---------------
 include/linux/clocksource.h |   11 ++++++---
 kernel/timer.c              |    3 ++
 3 files changed, 45 insertions(+), 20 deletions(-)
arch/i386/kernel/tsc.c +34 -17
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
@@ -60,6 +60,12 @@ static inline int check_tsc_unstable(voi
 	return tsc_unstable;
 }
 
+void mark_tsc_unstable(void)
+{
+	tsc_unstable = 1;
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
 /* Accellerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -289,6 +295,7 @@ core_initcall(cpufreq_tsc);
 /* clock source code */
 
 static unsigned long current_tsc_khz = 0;
+static int tsc_update_callback(void);
 
 static cycle_t read_tsc(void)
 {
@@ -306,28 +313,38 @@ static struct clocksource clocksource_ts
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
+	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-void mark_tsc_unstable(void)
+static int tsc_update_callback(void)
 {
-	if (!tsc_unstable) {
-		tsc_unstable = 1;
-		/* Can be called before registration */
-		if (clocksource_tsc.mult)
-			clocksource_change_rating(&clocksource_tsc, 0);
-		else
-			clocksource_tsc.rating = 0;
+	int change = 0;
+
+	/* check to see if we should switch to the safe clocksource: */
+	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
+		clocksource_tsc.rating = 0;
+		clocksource_reselect();
+		change = 1;
+	}
+
+	/* only update if tsc_khz has changed: */
+	if (current_tsc_khz != tsc_khz) {
+		current_tsc_khz = tsc_khz;
+		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+							clocksource_tsc.shift);
+		change = 1;
 	}
+
+	return change;
 }
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
 {
 	printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
 		       d->ident);
-	tsc_unstable = 1;
+	mark_tsc_unstable();
 	return 0;
 }
 
@@ -399,12 +416,11 @@ __cpuinit int unsynchronized_tsc(void)
 	 * Intel systems are normally all synchronized.
 	 * Exceptions must mark TSC as unstable:
 	 */
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
-		/* assume multi socket systems are not synchronized: */
-		if (num_possible_cpus() > 1)
-			tsc_unstable = 1;
-	}
-	return tsc_unstable;
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ 		return 0;
+
+	/* assume multi socket systems are not synchronized: */
+ 	return num_possible_cpus() > 1;
 }
 
 /*
@@ -433,7 +449,8 @@ static int __init init_tsc_clocksource(v
 		/* check blacklist */
 		dmi_check_system(bad_tsc_dmi_table);
 
-		unsynchronized_tsc();
+		if (unsynchronized_tsc()) /* mark unstable if unsynced */
+			mark_tsc_unstable();
 		check_geode_tsc_reliable();
 		current_tsc_khz = tsc_khz;
 		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
include/linux/clocksource.h +8 -3
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -44,6 +44,7 @@ typedef u64 cycle_t;
  *			subtraction of non 64 bit counters
  * @mult:		cycle to nanosecond multiplier
  * @shift:		cycle to nanosecond divisor (power of two)
+ * @update_callback:	called when safe to alter clocksource values
  * @flags:		flags describing special properties
  * @vread:		vsyscall based read
  * @cycle_interval:	Used internally by timekeeping core, please ignore.
@@ -57,6 +58,7 @@ struct clocksource {
 	cycle_t mask;
 	u32 mult;
 	u32 shift;
+	int (*update_callback)(void);
 	unsigned long flags;
 	cycle_t (*vread)(void);
 
@@ -184,9 +186,9 @@ static inline void clocksource_calculate
 
 
 /* used to install a new clocksource */
-extern int clocksource_register(struct clocksource*);
-extern struct clocksource* clocksource_get_next(void);
-extern void clocksource_change_rating(struct clocksource *cs, int rating);
+int clocksource_register(struct clocksource*);
+void clocksource_reselect(void);
+struct clocksource* clocksource_get_next(void);
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
@@ -196,4 +198,7 @@ static inline void update_vsyscall(struc
 }
 #endif
 
+#define clocksource_reselect()	clocksource_change_rating(&clocksource_tsc, clocksource_tsc.rating)
+extern void clocksource_change_rating(struct clocksource *cs, int rating);
+
 #endif /* _LINUX_CLOCKSOURCE_H */
kernel/timer.c +3 -0
Index: linux-2.6.19/kernel/timer.c
===================================================================
@@ -893,6 +893,8 @@ static int change_clocksource(void)
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
 		return 1;
+	} else if (clock->update_callback) {
+		return clock->update_callback();
 	}
 	return 0;
 }
@@ -959,6 +961,7 @@ void __init timekeeping_init(void)
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
+
 /* flag for if timekeeping is suspended */
 static int timekeeping_suspended;
 /* time in seconds when suspend began */
#5 lore raw

PATCH 4/23 clocksource: drop time-x86_64-tsc-fixup-clocksource-changes.patch

In reply to Daniel Walker

Drop.

---
 arch/x86_64/kernel/tsc.c |   31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)
arch/x86_64/kernel/tsc.c +21 -10
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
@@ -46,6 +46,13 @@ static inline int check_tsc_unstable(voi
 {
 	return tsc_unstable;
 }
+
+void mark_tsc_unstable(void)
+{
+	tsc_unstable = 1;
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
 #ifdef CONFIG_CPU_FREQ
 
 /* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
@@ -174,6 +181,9 @@ __setup("notsc", notsc_setup);
 
 
 /* clock source code: */
+
+static int tsc_update_callback(void);
+
 static cycle_t read_tsc(void)
 {
 	cycle_t ret = (cycle_t)get_cycles_sync();
@@ -192,23 +202,24 @@ static struct clocksource clocksource_ts
 	.read			= read_tsc,
 	.mask			= CLOCKSOURCE_MASK(64),
 	.shift			= 22,
+	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 	.vread			= vread_tsc,
 };
 
-void mark_tsc_unstable(void)
+static int tsc_update_callback(void)
 {
-	if (!tsc_unstable) {
-		tsc_unstable = 1;
-		/* Change only the rating, when not registered */
-		if (clocksource_tsc.mult)
-			clocksource_change_rating(&clocksource_tsc, 0);
-		else
-			clocksource_tsc.rating = 0;
+	int change = 0;
+
+	/* check to see if we should switch to the safe clocksource: */
+	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
+		clocksource_tsc.rating = 50;
+		clocksource_reselect();
+		change = 1;
 	}
+	return change;
 }
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init init_tsc_clocksource(void)
 {
@@ -216,7 +227,7 @@ static int __init init_tsc_clocksource(v
 		clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
 							clocksource_tsc.shift);
 		if (check_tsc_unstable())
-			clocksource_tsc.rating = 0;
+			clocksource_tsc.rating = 50;
 
 		return clocksource_register(&clocksource_tsc);
 	}
#6 lore raw

PATCH 5/23 clocksource: drop simplify-the-registration-of-clocksources.patch

In reply to Daniel Walker

Drop.

---
 include/linux/clocksource.h |    3 -
 kernel/time/clocksource.c   |  118 ++++++++++++++++++++++----------------------
 2 files changed, 61 insertions(+), 60 deletions(-)
include/linux/clocksource.h +0 -3
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -198,7 +198,4 @@ static inline void update_vsyscall(struc
 }
 #endif
 
-#define clocksource_reselect()	clocksource_change_rating(&clocksource_tsc, clocksource_tsc.rating)
-extern void clocksource_change_rating(struct clocksource *cs, int rating);
-
 #endif /* _LINUX_CLOCKSOURCE_H */
kernel/time/clocksource.c +61 -57

189 lines not on this page · raw message

#7 lore raw

PATCH 6/23 timekeeping: create kernel/time/timekeeping.c

In reply to Daniel Walker

Move the generic timekeeping code from kernel/timer.c to kernel/time/timekeeping.c . This requires some glue code which is added to the include/linux/timekeeping.h header.

I tried to be as careful as possible in picking up recent changes to the timekeeping code. This patches is on top of -mm , and moves all the changes included in -mm.

This is also moving do_timer and the load calculation code which was connect to the timekeeping code. Moving it provided for slightly better compiler optimization.

---
 include/linux/clocksource.h |    3 
 include/linux/timekeeping.h |   13 
 kernel/time/Makefile        |    2 
 kernel/time/clocksource.c   |    3 
 kernel/time/timekeeping.c   |  711 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/timer.c              |  694 ------------------------------------------
 6 files changed, 729 insertions(+), 697 deletions(-)
include/linux/clocksource.h +3 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -18,6 +18,9 @@
 /* clocksource cycle base type */
 typedef u64 cycle_t;
 
+/* XXX - Would like a better way for initializing curr_clocksource */
+extern struct clocksource clocksource_jiffies;
+
 /**
  * struct clocksource - hardware abstraction for a free running counter
  *	Provides mostly state-free accessors to the underlying hardware.
include/linux/timekeeping.h new file +13 -0
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
@@ -0,0 +1,13 @@
+#ifndef _LINUX_TIMEKEEPING_H
+#define _LINUX_TIMEKEEPING_H
+
+#include <linux/clocksource.h>
+
+#ifndef CONFIG_GENERIC_TIME
+static inline int change_clocksource(void)
+{
+	return 0;
+}
+#endif /* !CONFIG_GENERIC_TIME */
+
+#endif /* _LINUX_TIMEKEEPING_H */
kernel/time/Makefile +1 -1
Index: linux-2.6.19/kernel/time/Makefile
===================================================================
@@ -1,4 +1,4 @@
-obj-y += ntp.o clocksource.o jiffies.o timer_list.o
+obj-y += ntp.o clocksource.o jiffies.o timer_list.o timekeeping.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
kernel/time/clocksource.c +0 -3
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -29,9 +29,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 
-/* XXX - Would like a better way for initializing curr_clocksource */
-extern struct clocksource clocksource_jiffies;
-
 /*[Clocksource internal variables]---------
  * curr_clocksource:
  *	currently selected clocksource. Initialized to clocksource_jiffies.
kernel/time/timekeeping.c new file +711 -0

711 lines not on this page · raw message

kernel/timer.c +1 -693

724 lines not on this page · raw message

#8 lore raw

Re: [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c

Quoted 2 lines · Daniel Walker

Move the generic timekeeping code from kernel/timer.c to kernel/time/timekeeping.c. [...]

please lets not do this just yet. While i have no problems with the change in theory, the time code is in high flux and it's easier to keep things sorted if we dont do big code movements. It also makes it harder to review things and it acts as a hard merge barrier. We usually do such move chunks of code in 'quiet periods', and now is definitely not such a period. It's also pretty easy to do.

Ingo

#9 lore raw

Re: [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c

Quoted 11 lines · Ingo Molnar
Quoted 2 lines · Daniel Walker

Move the generic timekeeping code from kernel/timer.c to kernel/time/timekeeping.c. [...]

please lets not do this just yet. While i have no problems with the change in theory, the time code is in high flux and it's easier to keep things sorted if we dont do big code movements. It also makes it harder to review things and it acts as a hard merge barrier. We usually do such move chunks of code in 'quiet periods', and now is definitely not such a period. It's also pretty easy to do.

I'm not opposed to waiting .. I do think this needs to go in eventually tho .. This is a clean up that John requested, and I only added it because I was making other changes to timekeeping.. So it's really his call .

Daniel

#10 lore raw

PATCH 7/23 clocksource: rating sorted list

In reply to Daniel Walker

Converts the original plain list into a sorted list based on the clock rating. Later in my tree this allows some of the variables to be dropped since the highest rated clock is always at the front of the list. This also does some other nice things like allow the sysfs files to print the clocks in a more interesting order. It's forward looking.

---
 arch/i386/kernel/tsc.c      |    2 
 arch/x86_64/kernel/tsc.c    |    2 
 include/linux/clocksource.h |    8 +-
 kernel/time/clocksource.c   |  132 +++++++++++++++++++++++++++++---------------
 4 files changed, 96 insertions(+), 48 deletions(-)
arch/i386/kernel/tsc.c +1 -1
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
@@ -325,7 +325,7 @@ static int tsc_update_callback(void)
 	/* check to see if we should switch to the safe clocksource: */
 	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
 		clocksource_tsc.rating = 0;
-		clocksource_reselect();
+		clocksource_rating_change(&clocksource_tsc);
 		change = 1;
 	}
 
arch/x86_64/kernel/tsc.c +1 -1
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
@@ -229,7 +229,7 @@ static int tsc_update_callback(void)
 	/* check to see if we should switch to the safe clocksource: */
 	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
 		clocksource_tsc.rating = 50;
-		clocksource_reselect();
+		clocksource_rating_change(&clocksource_tsc);
 		change = 1;
 	}
 	return change;
include/linux/clocksource.h +5 -3
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -12,6 +12,8 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/sysdev.h>
+
 #include <asm/div64.h>
 #include <asm/io.h>
 
@@ -189,9 +191,9 @@ static inline void clocksource_calculate
 
 
 /* used to install a new clocksource */
-int clocksource_register(struct clocksource*);
-void clocksource_reselect(void);
-struct clocksource* clocksource_get_next(void);
+extern struct clocksource *clocksource_get_next(void);
+extern int clocksource_register(struct clocksource*);
+extern void clocksource_rating_change(struct clocksource*);
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
kernel/time/clocksource.c +89 -43

207 lines not on this page · raw message

#11 lore raw

Re: [PATCH 07/23] clocksource: rating sorted list

Quoted 5 lines · Daniel Walker

Converts the original plain list into a sorted list based on the clock rating. Later in my tree this allows some of the variables to be dropped since the highest rated clock is always at the front of the list. This also does some other nice things like allow the sysfs files to print the clocks in a more interesting order. It's forward looking.

Unfortunately this seems to be a step backwards to me. Please consider:

arch/i386/kernel/tsc.c static int tsc_update_callback(void) · line 329

Quoted 5 lines
arch/i386/kernel/tsc.c +1 -1
 	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
 		clocksource_tsc.rating = 0;
-		clocksource_reselect();
+		clocksource_rating_change(&clocksource_tsc);
 		change = 1;

this should be the following API:

	clocksource_rating_change(&clocksource_tsc, 0);

a rating change can occur due to other things as well, not only due to 'tsc unstable' events. So keeping an API around that changes the rating (and propagates all related changes), makes more sense to me.

also, a pure function call is the most natural (and most flexible) API, for a centrally registered resource like a clock source driver. And a rating change should imply a reselect too, obviously. That way we replace 2 lines with 1 line - that's a real API improvement and a real cleanup patch.

and that's precisely what Thomas' patch in -mm that your queue undoes implements. (see: simplify-the-registration-of-clocksources.patch in -mm) Have you considered Thomas' change when you dropped it?

Ingo

#12 lore raw

Re: [PATCH 07/23] clocksource: rating sorted list

Quoted 10 lines · Ingo Molnar

a rating change can occur due to other things as well, not only due to 'tsc unstable' events. So keeping an API around that changes the rating (and propagates all related changes), makes more sense to me.

also, a pure function call is the most natural (and most flexible) API, for a centrally registered resource like a clock source driver. And a rating change should imply a reselect too, obviously. That way we replace 2 lines with 1 line - that's a real API improvement and a real cleanup patch.

Quoted 3 lines

and that's precisely what Thomas' patch in -mm that your queue undoes implements. (see: simplify-the-registration-of-clocksources.patch in -mm) Have you considered Thomas' change when you dropped it?

My patch set makes clocksource ratings constant (when fully applied). That particular function is dropped all together .

Daniel

#13 lore raw

PATCH 8/23 clocksource: drop duplicate register checking

In reply to Daniel Walker

This is something Thomas already dropped, and I'm just sticking with that .. If you register your clocksource _twice_ your kernel will likely not work correctly (and might crash).

---
 kernel/time/clocksource.c |   19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)
kernel/time/clocksource.c +6 -13
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -186,16 +186,12 @@ int clocksource_register(struct clocksou
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	if (unlikely(!list_empty(&c->list) && __is_registered(c->name))) {
-		printk("register_clocksource: Cannot register %s clocksource. "
-		       "Already registered!", c->name);
-		ret = -EBUSY;
-	} else {
-		INIT_LIST_HEAD(&c->list);
- 		__sorted_list_add(c);
-		/* scan the registered clocksources, and pick the best one */
-		next_clocksource = select_clocksource();
-	}
+ 	__sorted_list_add(c);
+
+	/*
+	 * scan the registered clocksources, and pick the best one
+	 */
+	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 	return ret;
 }
@@ -212,9 +208,6 @@ void clocksource_rating_change(struct cl
 {
 	unsigned long flags;
 
-	if (unlikely(list_empty(&c->list)))
-		return;
-
   	spin_lock_irqsave(&clocksource_lock, flags);
 
 	/*
#14 lore raw

Re: [PATCH 08/23] clocksource: drop duplicate register checking

Quoted 1 line · Daniel Walker

This is something Thomas already dropped, [...]

(i think you forgot to Cc: Thomas here, nor is this something that Thomas' change dropped.)

Quoted 3 lines

[...] and I'm just sticking with that .. If you register your clocksource _twice_ your kernel will likely not work correctly (and might crash).

this is a quite bad change. John's original clocksource code protects against double registry:

         if (is_registered_source(c)) {
                 printk("register_clocksource: Cannot register %s. "
                        "Already registered!", c->name);
                 ret = -EBUSY;

and Thomas' change keeps that property, but doesnt printk. Your change makes double registry possible, potentially crashing the kernel later on! (And this isnt theoretical, double registry did happen in practice when i debugged suspend problems on my SMP laptop.)

Ingo

#15 lore raw

Re: [PATCH 08/23] clocksource: drop duplicate register checking

Quoted 6 lines · Ingo Molnar
Quoted 1 line · Daniel Walker

This is something Thomas already dropped, [...]

(i think you forgot to Cc: Thomas here, nor is this something that Thomas' change dropped.)

Yes your right .

Quoted 12 lines
Quoted 3 lines

[...] and I'm just sticking with that .. If you register your clocksource _twice_ your kernel will likely not work correctly (and might crash).

this is a quite bad change. John's original clocksource code protects against double registry:

         if (is_registered_source(c)) {
                 printk("register_clocksource: Cannot register %s. "
                        "Already registered!", c->name);
                 ret = -EBUSY;
Quoted 4 lines

and Thomas' change keeps that property, but doesnt printk. Your change makes double registry possible, potentially crashing the kernel later on! (And this isnt theoretical, double registry did happen in practice when i debugged suspend problems on my SMP laptop.)

My original patch set makes the duplicate register checking better (which I dropped) .. I'll be happy to reintroduce that part of it..

Daniel

#16 lore raw

Re: [PATCH 08/23] clocksource: drop duplicate register checking

Quoted 5 lines · Daniel Walker
Quoted 5 lines
         if (is_registered_source(c)) {
                 printk("register_clocksource: Cannot register %s. "
                        "Already registered!", c->name);
                 ret = -EBUSY;
Quoted 8 lines
Quoted 5 lines

and Thomas' change keeps that property, but doesnt printk. Your change makes double registry possible, potentially crashing the kernel later on! (And this isnt theoretical, double registry did happen in practice when i debugged suspend problems on my SMP laptop.)

My original patch set makes the duplicate register checking better (which I dropped) .. I'll be happy to reintroduce that part of it..

why if Thomas' patch: simplify-the-registration-of-clocksources.patch already does it?

Ingo

#17 lore raw

PATCH 9/23 clocksource: add block notifier

In reply to Daniel Walker

Adds a call back interface for register/rating change events. This is also used later in this series to signal other interesting events.

---
 include/linux/clocksource.h |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/timekeeping.h |    3 +++
 kernel/time/clocksource.c   |   10 ++++++++++
 3 files changed, 50 insertions(+)
include/linux/clocksource.h +37 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -13,6 +13,7 @@
 #include <linux/time.h>
 #include <linux/list.h>
 #include <linux/sysdev.h>
+#include <linux/notifier.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -23,6 +24,42 @@ typedef u64 cycle_t;
 /* XXX - Would like a better way for initializing curr_clocksource */
 extern struct clocksource clocksource_jiffies;
 
+/*
+ * Allows inlined calling for notifier routines.
+ */
+extern struct atomic_notifier_head clocksource_list_notifier;
+
+/*
+ * Block notifier flags.
+ */
+#define CLOCKSOURCE_NOTIFY_REGISTER	1
+#define CLOCKSOURCE_NOTIFY_RATING	2
+#define CLOCKSOURCE_NOTIFY_FREQ		4
+
+/**
+ * clocksource_notifier_register - Registers a list change notifier
+ * @nb:		pointer to a notifier block
+ *
+ * Returns zero always.
+ */
+static inline int clocksource_notifier_register(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&clocksource_list_notifier, nb);
+}
+
+/**
+ * clocksource_freq_change - Allows notification of dynamic frequency changes.
+ *
+ * Signals that a clocksource is dynamically changing it's frequency.
+ * This could happen if a clocksource becomes more/less stable.
+ */
+static inline void clocksource_freq_change(struct clocksource *c)
+{
+	atomic_notifier_call_chain(&clocksource_list_notifier,
+				   CLOCKSOURCE_NOTIFY_FREQ, c);
+}
+
+
 /**
  * struct clocksource - hardware abstraction for a free running counter
  *	Provides mostly state-free accessors to the underlying hardware.
include/linux/timekeeping.h +3 -0
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
@@ -8,6 +8,9 @@ static inline int change_clocksource(voi
 {
 	return 0;
 }
+
+static inline void change_clocksource(void) { }
+
 #endif /* !CONFIG_GENERIC_TIME */
 
 #endif /* _LINUX_TIMEKEEPING_H */
kernel/time/clocksource.c +10 -0
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -49,6 +49,8 @@ static DEFINE_SPINLOCK(clocksource_lock)
 static char override_name[32];
 static int finished_booting;
 
+ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
+
 /* clocksource_done_booting - Called near the end of bootup
  *
  * Hack to avoid lots of clocksource churn at boot time
@@ -193,6 +195,10 @@ int clocksource_register(struct clocksou
 	 */
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
+
+	atomic_notifier_call_chain(&clocksource_list_notifier,
+ 				   CLOCKSOURCE_NOTIFY_REGISTER, c);
+
 	return ret;
 }
 EXPORT_SYMBOL(clocksource_register);
@@ -218,6 +224,10 @@ void clocksource_rating_change(struct cl
 
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
+
+	atomic_notifier_call_chain(&clocksource_list_notifier,
+				   CLOCKSOURCE_NOTIFY_RATING, c);
+
 }
 EXPORT_SYMBOL(clocksource_rating_change);
 
#18 lore raw

Re: [PATCH 09/23] clocksource: add block notifier

Quoted 2 lines · Daniel Walker

Adds a call back interface for register/rating change events. This is also used later in this series to signal other interesting events.

This patch adds:

include/linux/clocksource.h typedef u64 cycle_t; · line 37

Quoted 3 lines
include/linux/clocksource.h +3 -0
+#define CLOCKSOURCE_NOTIFY_REGISTER	1
+#define CLOCKSOURCE_NOTIFY_RATING	2
+#define CLOCKSOURCE_NOTIFY_FREQ		4

and a later patch adds:

Quoted 1 line

+#define CLOCKSOURCE_NOTIFY_UNSTABLE 8

while i tentatively agree with the introduction of clocksource driver notifications in general (given any actual real users of that infrastructure), i can see three problems with your notifier changes:

firstly, with the full changes applied, CLOCKSOURCE_NOTIFY_RATING is totally unused (and not even driven by the core clocksource code).

secondly, CLOCKSOURCE_NOTIFY_REGISTER is only used by the core clocksource code and no register-notifier interface is exposed: this makes the whole thing an expensive NOP.

thirdly, CLOCKSOURCE_NOTIFY_FREQ is totally unused as well.

(there are tons of examples in the kernel of how to do driver notification APIs properly.)

Ingo

#19 lore raw

Re: [PATCH 09/23] clocksource: add block notifier

Quoted 13 lines · Ingo Molnar
Quoted 2 lines · Daniel Walker

Adds a call back interface for register/rating change events. This is also used later in this series to signal other interesting events.

This patch adds:

include/linux/clocksource.h typedef u64 cycle_t; · line 37

Quoted 3 lines
include/linux/clocksource.h +3 -0
+#define CLOCKSOURCE_NOTIFY_REGISTER	1
+#define CLOCKSOURCE_NOTIFY_RATING	2
+#define CLOCKSOURCE_NOTIFY_FREQ		4

and a later patch adds:

Quoted 8 lines
Quoted 1 line

+#define CLOCKSOURCE_NOTIFY_UNSTABLE 8

while i tentatively agree with the introduction of clocksource driver notifications in general (given any actual real users of that infrastructure), i can see three problems with your notifier changes:

firstly, with the full changes applied, CLOCKSOURCE_NOTIFY_RATING is totally unused (and not even driven by the core clocksource code).

True, ratings are constant so the notification never happens (and never needs to)

Quoted 3 lines

secondly, CLOCKSOURCE_NOTIFY_REGISTER is only used by the core clocksource code and no register-notifier interface is exposed: this makes the whole thing an expensive NOP.

I don't know what you mean when you say "no register-notifier interface is exposed" .. The timekeeping code doesn't use this notification , but it really should. It's not that big of an issue since we don't have many clocks in modules..

Quoted 1 line

thirdly, CLOCKSOURCE_NOTIFY_FREQ is totally unused as well.

Indeed . Consider it dropped.

Quoted 2 lines

(there are tons of examples in the kernel of how to do driver notification APIs properly.)

Are you referring to the comments above , or something else your seeing in the code?

Daniel

#20 lore raw

Re: [PATCH 09/23] clocksource: add block notifier

Quoted 7 lines · Daniel Walker
Quoted 3 lines

secondly, CLOCKSOURCE_NOTIFY_REGISTER is only used by the core clocksource code and no register-notifier interface is exposed: this makes the whole thing an expensive NOP.

I don't know what you mean when you say "no register-notifier interface is exposed" .. The timekeeping code doesn't use this notification , but it really should. [...]

what i say is that there's no public interface exposed of this notifier (and even if there was, there isnt any user of it) and there's only a single notifier used internally: this means that this thing is an expensive function call.

Ingo

#21 lore raw

PATCH 10/23 clocksource: remove update_callback

In reply to Daniel Walker

Uses the block notifier to replace the functionality of update_callback(). update_callback() was a special case specifically for the tsc, but including it in the clocksource structure duplicated it needlessly for other clocks.

---
 arch/i386/kernel/tsc.c      |   33 +++++++++------------------------
 arch/x86_64/kernel/tsc.c    |   19 +++++--------------
 include/linux/clocksource.h |    2 --
 include/linux/timekeeping.h |    1 +
 kernel/time/timekeeping.c   |   32 ++++++++++++++++++++++++++++++--
 5 files changed, 45 insertions(+), 42 deletions(-)
arch/i386/kernel/tsc.c +9 -24
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
@@ -50,8 +50,7 @@ static int __init tsc_setup(char *str)
 __setup("notsc", tsc_setup);
 
 /*
- * code to mark and check if the TSC is unstable
- * due to cpufreq or due to unsynced TSCs
+ * Flag that denotes an unstable tsc and check function.
  */
 static int tsc_unstable;
 
@@ -60,12 +59,6 @@ static inline int check_tsc_unstable(voi
 	return tsc_unstable;
 }
 
-void mark_tsc_unstable(void)
-{
-	tsc_unstable = 1;
-}
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
-
 /* Accellerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -179,6 +172,7 @@ int recalibrate_cpu_khz(void)
 	if (cpu_has_tsc) {
 		cpu_khz = calculate_cpu_khz();
 		tsc_khz = cpu_khz;
+		mark_tsc_unstable();
 		cpu_data[0].loops_per_jiffy =
 			cpufreq_scale(cpu_data[0].loops_per_jiffy,
 					cpu_khz_old, cpu_khz);
@@ -295,7 +289,6 @@ core_initcall(cpufreq_tsc);
 /* clock source code */
 
 static unsigned long current_tsc_khz = 0;
-static int tsc_update_callback(void);
 
 static cycle_t read_tsc(void)
 {
@@ -313,32 +306,24 @@ static struct clocksource clocksource_ts
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-static int tsc_update_callback(void)
+/*
+ * Code to mark if the TSC is unstable due to cpufreq or due to unsynced TSCs
+ */
+void mark_tsc_unstable(void)
 {
-	int change = 0;
-
 	/* check to see if we should switch to the safe clocksource: */
-	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
+	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 0)) {
 		clocksource_tsc.rating = 0;
 		clocksource_rating_change(&clocksource_tsc);
-		change = 1;
 	}
 
-	/* only update if tsc_khz has changed: */
-	if (current_tsc_khz != tsc_khz) {
-		current_tsc_khz = tsc_khz;
-		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
-							clocksource_tsc.shift);
-		change = 1;
-	}
-
-	return change;
+	tsc_unstable = 1;
 }
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
 {
arch/x86_64/kernel/tsc.c +5 -14
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
@@ -47,11 +47,6 @@ static inline int check_tsc_unstable(voi
 	return tsc_unstable;
 }
 
-void mark_tsc_unstable(void)
-{
-	tsc_unstable = 1;
-}
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 #ifdef CONFIG_CPU_FREQ
 
@@ -182,8 +177,6 @@ __setup("notsc", notsc_setup);
 
 /* clock source code: */
 
-static int tsc_update_callback(void);
-
 static cycle_t read_tsc(void)
 {
 	cycle_t ret = (cycle_t)get_cycles_sync();
@@ -202,24 +195,22 @@ static struct clocksource clocksource_ts
 	.read			= read_tsc,
 	.mask			= CLOCKSOURCE_MASK(64),
 	.shift			= 22,
-	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 	.vread			= vread_tsc,
 };
 
-static int tsc_update_callback(void)
+void mark_tsc_unstable(void)
 {
-	int change = 0;
-
 	/* check to see if we should switch to the safe clocksource: */
-	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
+	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 50)) {
 		clocksource_tsc.rating = 50;
 		clocksource_rating_change(&clocksource_tsc);
-		change = 1;
 	}
-	return change;
+
+	tsc_unstable = 1;
 }
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init init_tsc_clocksource(void)
 {
include/linux/clocksource.h +0 -2
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -86,7 +86,6 @@ static inline void clocksource_freq_chan
  *			subtraction of non 64 bit counters
  * @mult:		cycle to nanosecond multiplier
  * @shift:		cycle to nanosecond divisor (power of two)
- * @update_callback:	called when safe to alter clocksource values
  * @flags:		flags describing special properties
  * @vread:		vsyscall based read
  * @cycle_interval:	Used internally by timekeeping core, please ignore.
@@ -100,7 +99,6 @@ struct clocksource {
 	cycle_t mask;
 	u32 mult;
 	u32 shift;
-	int (*update_callback)(void);
 	unsigned long flags;
 	cycle_t (*vread)(void);
 
include/linux/timekeeping.h +1 -0
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
@@ -10,6 +10,7 @@ static inline int change_clocksource(voi
 }
 
 static inline void change_clocksource(void) { }
+static inline void timekeeping_init_notifier(void) { }
 
 #endif /* !CONFIG_GENERIC_TIME */
 
kernel/time/timekeeping.c +30 -2
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
@@ -39,6 +39,7 @@ static unsigned long timekeeping_suspend
  * Clock used for timekeeping
  */
 struct clocksource *clock = &clocksource_jiffies;
+atomic_t clock_recalc_interval = ATOMIC_INIT(0);
 
 #ifdef CONFIG_GENERIC_TIME
 /**
@@ -176,8 +177,9 @@ static int change_clocksource(void)
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
 		return 1;
-	} else if (clock->update_callback) {
-		return clock->update_callback();
+	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
+		atomic_set(&clock_recalc_interval, 0);
+		return 1;
 	}
 	return 0;
 }
@@ -199,6 +201,29 @@ int timekeeping_is_continuous(void)
 
 	return ret;
 }
+
+static int
+clocksource_callback(struct notifier_block *nb, unsigned long op, void *c)
+{
+	if (c == clock && op == CLOCKSOURCE_NOTIFY_FREQ &&
+	    !atomic_read(&clock_recalc_interval))
+		atomic_inc(&clock_recalc_interval);
+
+	return 0;
+}
+
+static struct notifier_block clocksource_nb = {
+	.notifier_call = clocksource_callback,
+};
+
+void __init timekeeping_init_notifier(void)
+{
+	/*
+	 * Needs to be done early, incase a clock is unstable
+	 * early.
+	 */
+	clocksource_notifier_register(&clocksource_nb);
+}
 #endif /* CONFIG_GENERIC_TIME */
 
 /**
@@ -237,6 +262,9 @@ void __init timekeeping_init(void)
 		-xtime.tv_sec, -xtime.tv_nsec);
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	timekeeping_init_notifier();
+
 }
 
 
#22 lore raw

Re: [PATCH 10/23] clocksource: remove update_callback

Quoted 4 lines · Daniel Walker

Uses the block notifier to replace the functionality of update_callback(). update_callback() was a special case specifically for the tsc, but including it in the clocksource structure duplicated it needlessly for other clocks.

Firstly, it think it should be mentioned that Thomas' queue already does this, in clocksource-remove-the-update-callback.patch (hence he should have been Cc:-ed). Your queue 'drops' Thomas' patch then redoes it here without mentioning that this is another version of what is in Thomas's queue. So we get this situation:

clocksource-remove-the-update-callback.patch drop-clocksource-remove-the-update-callback.patch clocksource_remove_update_callback.patch

that all flip-flops the same thing.

Secondly, your patch seems to do other changes as well:

arch/i386/kernel/tsc.c int recalibrate_cpu_khz(void) · line 178

Quoted 8 lines
arch/i386/kernel/tsc.c +1 -0
@@ -179,6 +172,7 @@ int recalibrate_cpu_khz(void)
 	if (cpu_has_tsc) {
 		cpu_khz = calculate_cpu_khz();
 		tsc_khz = cpu_khz;
+		mark_tsc_unstable();
 		cpu_data[0].loops_per_jiffy =
 			cpufreq_scale(cpu_data[0].loops_per_jiffy,
 					cpu_khz_old, cpu_khz);

this adds a new event to a place that didnt have it before. (If this is fixing up an initialization artifact then that needs a comment at least.)

plus:

Quoted 2 lines

struct clocksource *clock = &clocksource_jiffies;
+atomic_t clock_recalc_interval = ATOMIC_INIT(0);

is not mentioned in the changelog. It's also needlessly global. Furthermore, it seems to be a rather unclean method of passing information from clocksource_callback() into change_clocksource():

kernel/time/timekeeping.c static int change_clocksource(void) · line 182

Quoted 9 lines
kernel/time/timekeeping.c +3 -2
@@ -176,8 +177,9 @@ static int change_clocksource(void)
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
 		return 1;
-	} else if (clock->update_callback) {
-		return clock->update_callback();
+	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
+		atomic_set(&clock_recalc_interval, 0);
+		return 1;

that's quite bad: you lost an information passing facility by going to a notifier, and you try to work it around via a global atomic variable. Which also looks quite racy as well.

The clean solution is i think what Thomas did: he calls straight into clocksource_change_rating(). And look at Thomas' patch:

 3 files changed, 17 insertions(+), 37 deletions(-)

versus yours:

 5 files changed, 45 insertions(+), 42 deletions(-)

Thomas' looks definitely simpler to me.

ingo

#23 lore raw

Re: [PATCH 10/23] clocksource: remove update_callback

Quoted 13 lines · Ingo Molnar
Quoted 4 lines · Daniel Walker

Uses the block notifier to replace the functionality of update_callback(). update_callback() was a special case specifically for the tsc, but including it in the clocksource structure duplicated it needlessly for other clocks.

Firstly, it think it should be mentioned that Thomas' queue already does this, in clocksource-remove-the-update-callback.patch (hence he should have been Cc:-ed). Your queue 'drops' Thomas' patch then redoes it here without mentioning that this is another version of what is in Thomas's queue. So we get this situation:

Quoted 5 lines

clocksource-remove-the-update-callback.patch drop-clocksource-remove-the-update-callback.patch clocksource_remove_update_callback.patch

that all flip-flops the same thing.

To be clear this change has exists for a very long time, long before Thomas implemented it ..

Quoted 14 lines

Secondly, your patch seems to do other changes as well:

arch/i386/kernel/tsc.c int recalibrate_cpu_khz(void) · line 178

Quoted 8 lines
arch/i386/kernel/tsc.c +1 -0
@@ -179,6 +172,7 @@ int recalibrate_cpu_khz(void)
 	if (cpu_has_tsc) {
 		cpu_khz = calculate_cpu_khz();
 		tsc_khz = cpu_khz;
+		mark_tsc_unstable();
 		cpu_data[0].loops_per_jiffy =
 			cpufreq_scale(cpu_data[0].loops_per_jiffy,
 					cpu_khz_old, cpu_khz);

this adds a new event to a place that didnt have it before. (If this is fixing up an initialization artifact then that needs a comment at least.)

Alright .. Later on I talk about clock frequency recalculation which pertains to this change ..

Quoted 8 lines

plus:

Quoted 2 lines

struct clocksource *clock = &clocksource_jiffies;
+atomic_t clock_recalc_interval = ATOMIC_INIT(0);

is not mentioned in the changelog. It's also needlessly global. Furthermore, it seems to be a rather unclean method of passing information from clocksource_callback() into change_clocksource():

It's a bisect artifact .. It's eventually dropped in a latter patch .

Quoted 14 lines

kernel/time/timekeeping.c static int change_clocksource(void) · line 182

Quoted 9 lines
kernel/time/timekeeping.c +3 -2
@@ -176,8 +177,9 @@ static int change_clocksource(void)
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
 		return 1;
-	} else if (clock->update_callback) {
-		return clock->update_callback();
+	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
+		atomic_set(&clock_recalc_interval, 0);
+		return 1;

that's quite bad: you lost an information passing facility by going to a notifier, and you try to work it around via a global atomic variable. Which also looks quite racy as well.

Quoted 2 lines

The clean solution is i think what Thomas did: he calls straight into clocksource_change_rating(). And look at Thomas' patch:

The information passing was purposefully dropped .. It was used (in part) to recalculate the frequency of a clock , but after discussing it with John he suggested we drop the frequency recalculation entirely. So the information passing should no longer be needed.

Daniel

#24 lore raw

Re: [PATCH 10/23] clocksource: remove update_callback

Quoted 14 lines · Daniel Walker
Quoted 13 lines · Ingo Molnar
Quoted 4 lines · Daniel Walker

Uses the block notifier to replace the functionality of update_callback(). update_callback() was a special case specifically for the tsc, but including it in the clocksource structure duplicated it needlessly for other clocks.

Firstly, it think it should be mentioned that Thomas' queue already does this, in clocksource-remove-the-update-callback.patch (hence he should have been Cc:-ed). Your queue 'drops' Thomas' patch then redoes it here without mentioning that this is another version of what is in Thomas's queue. So we get this situation:

Quoted 8 lines
Quoted 5 lines

clocksource-remove-the-update-callback.patch drop-clocksource-remove-the-update-callback.patch clocksource_remove_update_callback.patch

that all flip-flops the same thing.

To be clear this change has exists for a very long time, long before Thomas implemented it ..

it doesnt matter who invented the wheel first, what matters is a clean channel of communication so that we end up with the best code - and leaving out Cc:s doesnt really help that.

Ingo

#25 lore raw

PATCH 11/23 clocksource: atomic signals

In reply to Daniel Walker

Modifies the way clocks are switched to in the timekeeping code. The original code would constantly monitor the clocksource list checking for newly added clocksources. I modified this by using atomic types to signal when a new clock is added. This allows the operation to be used only when it's needed.

The fast path is also reduced to checking a single atomic value.

---
 include/linux/clocksource.h |    5 ++++
 include/linux/timekeeping.h |    4 ---
 kernel/time/clocksource.c   |    6 +++++
 kernel/time/timekeeping.c   |   49 ++++++++++++++++++++++++++++----------------
 4 files changed, 43 insertions(+), 21 deletions(-)
include/linux/clocksource.h +5 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -25,6 +25,11 @@ typedef u64 cycle_t;
 extern struct clocksource clocksource_jiffies;
 
 /*
+ * Atomic signal that is specific to timekeeping.
+ */
+extern atomic_t clock_check;
+
+/*
  * Allows inlined calling for notifier routines.
  */
 extern struct atomic_notifier_head clocksource_list_notifier;
include/linux/timekeeping.h +0 -4
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
@@ -4,10 +4,6 @@
 #include <linux/clocksource.h>
 
 #ifndef CONFIG_GENERIC_TIME
-static inline int change_clocksource(void)
-{
-	return 0;
-}
 
 static inline void change_clocksource(void) { }
 static inline void timekeeping_init_notifier(void) { }
kernel/time/clocksource.c +6 -0
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -50,6 +50,7 @@ static char override_name[32];
 static int finished_booting;
 
 ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
+atomic_t clock_check = ATOMIC_INIT(0);
 
 /* clocksource_done_booting - Called near the end of bootup
  *
@@ -58,6 +59,8 @@ ATOMIC_NOTIFIER_HEAD(clocksource_list_no
 static int __init clocksource_done_booting(void)
 {
 	finished_booting = 1;
+	/* Check for a new clock now */
+	atomic_inc(&clock_check);
 	return 0;
 }
 
@@ -285,6 +288,9 @@ static ssize_t sysfs_override_clocksourc
 	/* try to select it: */
 	next_clocksource = select_clocksource();
 
+	/* Signal that there is a new clocksource */
+	atomic_inc(&clock_check);
+
 	spin_unlock_irq(&clocksource_lock);
 
 	return ret;
kernel/time/timekeeping.c +32 -17

96 lines not on this page · raw message

#26 lore raw

Re: [PATCH 11/23] clocksource: atomic signals

Quoted 5 lines · Daniel Walker

Modifies the way clocks are switched to in the timekeeping code. The original code would constantly monitor the clocksource list checking for newly added clocksources. I modified this by using atomic types to signal when a new clock is added. This allows the operation to be used only when it's needed.

I see little difference between your and John's code: both poll something - you poll an atomic "did a new clocksource arrive" flag in the timer interrupt, John takes the clocksource_lock spinlock and checks a "did a new clocksource arrive" variable. Both are global atomic variables in essence.

what i'd see as a real cleanup here would be to get away from this 'poll whether there's any clocksource update' model, and to just ensure that a running timer irq will always see the latest clocksource. I.e. to run the change_clocksource() logic (and the following updates) when a new clock source is selected - not when the next timer interrupt runs. That would propagate all effects of a new clock source immediately.

Ingo

#27 lore raw

Re: [PATCH 11/23] clocksource: atomic signals

Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Daniel Walker

Modifies the way clocks are switched to in the timekeeping code. The original code would constantly monitor the clocksource list checking for newly added clocksources. I modified this by using atomic types to signal when a new clock is added. This allows the operation to be used only when it's needed.

Quoted 5 lines

I see little difference between your and John's code: both poll something - you poll an atomic "did a new clocksource arrive" flag in the timer interrupt, John takes the clocksource_lock spinlock and checks a "did a new clocksource arrive" variable. Both are global atomic variables in essence.

The original version has more operations on every timer interrupt. Also changing the spinlock to an atomic eliminates the possibility of contention in the timer interrupt ..

Quoted 6 lines

what i'd see as a real cleanup here would be to get away from this 'poll whether there's any clocksource update' model, and to just ensure that a running timer irq will always see the latest clocksource. I.e. to run the change_clocksource() logic (and the following updates) when a new clock source is selected - not when the next timer interrupt runs. That would propagate all effects of a new clock source immediately.

You could reduce the code in the interrupt handler (which is good), but I think you'll end up with a polling model regardless.. If you add some locking between the interrupt handler and something else you may as well add the run time of that new critical section to the timer latency . So I'm not sure it would be a outright win ..

Daniel

#28 lore raw

Re: [PATCH 11/23] clocksource: atomic signals

Quoted 9 lines · Daniel Walker
Quoted 5 lines

I see little difference between your and John's code: both poll something - you poll an atomic "did a new clocksource arrive" flag in the timer interrupt, John takes the clocksource_lock spinlock and checks a "did a new clocksource arrive" variable. Both are global atomic variables in essence.

The original version has more operations on every timer interrupt. Also changing the spinlock to an atomic eliminates the possibility of contention in the timer interrupt ..

there is precisely /zero/ contention on the clocksource_lock! It is a very short-held lock, and it's only held by the timer interrupt and some really rare operations like 'clocksource register' or 'show clocksources'.

Quoted 8 lines
Quoted 7 lines

what i'd see as a real cleanup here would be to get away from this 'poll whether there's any clocksource update' model, and to just ensure that a running timer irq will always see the latest clocksource. I.e. to run the change_clocksource() logic (and the following updates) when a new clock source is selected - not when the next timer interrupt runs. That would propagate all effects of a new clock source immediately.

Quoted 5 lines

You could reduce the code in the interrupt handler (which is good), but I think you'll end up with a polling model regardless.. If you add some locking between the interrupt handler and something else you may as well add the run time of that new critical section to the timer latency . So I'm not sure it would be a outright win ..

I think you didnt understand what i said: the point is to /remove/ the polling, and to replace it with a natural lock that is held anyway:
xtime_lock or whatever other exclusion mechanism. Again, there is almost /never/ any contention on this lock so there's no 'latency to add'. But the polling overhead in every timer irq, even if it's just a single atomic flag, does add up in every timer tick.

you also didnt seem to understand my other point:

Quoted 4 lines
Quoted 4 lines

I.e. to run the change_clocksource() logic (and the following updates) when a new clock source is selected - not when the next timer interrupt runs. That would propagate all effects of a new clock source immediately.

that is actually more important from a design cleanliness POV than the basic avoidance of some polling overhead.

Ingo

#29 lore raw

PATCH 12/23 clocksource: add clocksource_get_clock()

In reply to Daniel Walker

One new API call clocksource_get_clock() which allows clocks to be selected based on their name, or if the name is null the highest rated clock is returned.

---
 include/linux/clocksource.h |   12 ++++++++++++
 kernel/time/clocksource.c   |   18 ++++++++++++++++++
 2 files changed, 30 insertions(+)
include/linux/clocksource.h +12 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -234,6 +234,18 @@ static inline void clocksource_calculate
 extern struct clocksource *clocksource_get_next(void);
 extern int clocksource_register(struct clocksource*);
 extern void clocksource_rating_change(struct clocksource*);
+extern struct clocksource * clocksource_get_clock(char*);
+
+/**
+ * clocksource_get_best_clock - Finds highest rated clocksource
+ *
+ * Returns the highest rated clocksource. If none are register the
+ * jiffies clock is returned.
+ */
+static inline struct clocksource * clocksource_get_best_clock(void)
+{
+	return clocksource_get_clock(NULL);
+}
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
kernel/time/clocksource.c +18 -0
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -132,6 +132,24 @@ static inline struct clocksource * __get
 }
 
 /**
+ * clocksource_get_clock - Finds a specific clocksource
+ * @name:		name of the clocksource to return
+ *
+ * Returns the clocksource if registered, zero otherwise.
+ */
+struct clocksource * clocksource_get_clock(char * name)
+{
+	struct clocksource * ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocksource_lock, flags);
+	ret = __get_clock(name);
+	spin_unlock_irqrestore(&clocksource_lock, flags);
+	return ret;
+}
+
+
+/**
  * select_clocksource - Finds the best registered clocksource.
  *
  * Private function. Must hold clocksource_lock when called.
#30 lore raw

Re: [PATCH 12/23] clocksource: add clocksource_get_clock()

Quoted 3 lines · Daniel Walker

One new API call clocksource_get_clock() which allows clocks to be selected based on their name, or if the name is null the highest rated clock is returned.

this one (and the dependent APIs utilizations) look a step in the right direction to me, but they are not fully consequent and thus a bit confusing at the moment:

- the current_clocksource is now something that is conceptually related to timekeeping - while it still resides in the clocksource domain.

- if we do this split there should be a separate sysfs hierarchy for timekeeping, separate of clocksource

- you use struct sys_device clocksource_sys_device from clocksource.c in timekeeping.c, which is inconsistent as well.

so these bits need more work.

Ingo

#31 lore raw

Re: [PATCH 12/23] clocksource: add clocksource_get_clock()

Quoted 6 lines · Ingo Molnar
Quoted 3 lines · Daniel Walker

One new API call clocksource_get_clock() which allows clocks to be selected based on their name, or if the name is null the highest rated clock is returned.

Quoted 6 lines

this one (and the dependent APIs utilizations) look a step in the right direction to me, but they are not fully consequent and thus a bit confusing at the moment:

- the current_clocksource is now something that is conceptually related to timekeeping - while it still resides in the clocksource domain.

Yes . The sysfs code gets moved in the next patch so it resides in the timekeeping code ..

Quoted 2 lines

- if we do this split there should be a separate sysfs hierarchy for timekeeping, separate of clocksource

A long time ago I changed "current_clocksource" to "timekeeping_clocksource" which made sense at the time .. I got push back on that from John, and I think maybe Thomas ..

Quoted 3 lines

- you use struct sys_device clocksource_sys_device from clocksource.c in timekeeping.c, which is inconsistent as well.

This was on purpose , because I feel the sysfs organization benefits when you have the clocksource users all in one place. Along with the list of available clocksources .. I'm all ears if you have a better suggestion ..

Daniel

#32 lore raw

PATCH 13/23 timekeeping: move sysfs layer/drop API calls

In reply to Daniel Walker

This moves the timekeeping sysfs override layer into timekeeping.c and removes the get_next_clocksource and select_clocksource functions, and their component variables, since they are no longer used.

---
 include/linux/clocksource.h |    5 -
 kernel/time/clocksource.c   |  169 --------------------------------------------
 kernel/time/timekeeping.c   |  131 +++++++++++++++++++++++++++++++++-
 3 files changed, 134 insertions(+), 171 deletions(-)
include/linux/clocksource.h +2 -3
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -25,9 +25,9 @@ typedef u64 cycle_t;
 extern struct clocksource clocksource_jiffies;
 
 /*
- * Atomic signal that is specific to timekeeping.
+ * Sysfs device extern, for registering clocksources under the same sysfs dir.
  */
-extern atomic_t clock_check;
+extern struct sys_device clocksource_sys_device;
 
 /*
  * Allows inlined calling for notifier routines.
@@ -231,7 +231,6 @@ static inline void clocksource_calculate
 
 
 /* used to install a new clocksource */
-extern struct clocksource *clocksource_get_next(void);
 extern int clocksource_register(struct clocksource*);
 extern void clocksource_rating_change(struct clocksource*);
 extern struct clocksource * clocksource_get_clock(char*);
kernel/time/clocksource.c +3 -166

245 lines not on this page · raw message

kernel/time/timekeeping.c +129 -2

161 lines not on this page · raw message

#33 lore raw

Re: [PATCH 13/23] timekeeping: move sysfs layer/drop API calls

Quoted 3 lines · Daniel Walker

This moves the timekeeping sysfs override layer into timekeeping.c and removes the get_next_clocksource and select_clocksource functions, and their component variables, since they are no longer used.

please do these two changes in at least two separate phases. Like for the timer.c code movement i'd not do the big code shuffling just now, and even if it's done, it should be a /pure/ movement, with all preparatory and post changes done in separate patches. That way the individual changes are much more reviewable.

Ingo

#34 lore raw

PATCH 14/23 clocksource: increase initcall priority

In reply to Daniel Walker

Normal systems often have almost everything registered in device_initcall() . Most drivers are registered there, and usually if people add code that needs an initcall they will either use device_initcall() or module_init() which both result in the same initcall..

When John created the clocksource interface he did what most people would do , and he made the clocksource registration happen in device_initcall with most everything else .. The effect of doing this was the addition of the following code,

/* clocksource_done_booting - Called near the end of bootup
*
* Hack to avoid lots of clocksource churn at boot time */
static int __init clocksource_done_booting(void)

{
        finished_booting = 1;
        return 0;
}

late_initcall(clocksource_done_booting);

This is one of two initcalls in the clocksource interface , the other one is device_initcall(init_clocksource_sysfs); ..

If I leave the clocksource initcall alone then anything that uses a clocksource in the future would need at least one late_initcall(). Since the clocksources aren't all fully register until after device_initcall.

The reason behind changing that is because it doesn't fit the usually development flow of initialization functions which , as I said earlier, almost always end up into device_initcall .

This change certainly isn't mandatory . I feel it would reduce the likely hood of developers that use the clocksource interface from adding multiple initcalls (one late_initcall, and one device_initcall). It also better fits developers tendencies to put almost everything into device_initcall() ..

In addition,

This patch removes a small amount of code in time keeping which existed to detect the end of the initcall sequence then selected a clock.

As a note, arm and mips both register their clocksources during time_init() instead of using initcalls.

---
 arch/i386/kernel/hpet.c          |    2 +-
 arch/i386/kernel/i8253.c         |    2 +-
 arch/i386/kernel/tsc.c           |    2 +-
 arch/x86_64/kernel/hpet.c        |    2 +-
 arch/x86_64/kernel/tsc.c         |    3 +--
 drivers/clocksource/acpi_pm.c    |    8 +++++++-
 drivers/clocksource/cyclone.c    |    2 +-
 drivers/clocksource/scx200_hrt.c |    2 +-
 include/linux/clocksource.h      |    6 ++++++
 kernel/time/clocksource.c        |   13 -------------
 kernel/time/jiffies.c            |    2 +-
 kernel/time/tick-sched.c         |    8 ++++++++
 kernel/time/timekeeping.c        |   15 +++++++--------
 13 files changed, 36 insertions(+), 31 deletions(-)
arch/i386/kernel/hpet.c +1 -1
Index: linux-2.6.19/arch/i386/kernel/hpet.c
===================================================================
@@ -315,7 +315,7 @@ static int __init init_hpet_clocksource(
 	return clocksource_register(&clocksource_hpet);
 }
 
-module_init(init_hpet_clocksource);
+clocksource_initcall(init_hpet_clocksource);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
arch/i386/kernel/i8253.c +1 -1
Index: linux-2.6.19/arch/i386/kernel/i8253.c
===================================================================
@@ -195,4 +195,4 @@ static int __init init_pit_clocksource(v
 	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
 	return clocksource_register(&clocksource_pit);
 }
-module_init(init_pit_clocksource);
+clocksource_initcall(init_pit_clocksource);
arch/i386/kernel/tsc.c +1 -1
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
@@ -458,4 +458,4 @@ static int __init init_tsc_clocksource(v
 	return 0;
 }
 
-module_init(init_tsc_clocksource);
+clocksource_initcall(init_tsc_clocksource);
arch/x86_64/kernel/hpet.c +1 -1
Index: linux-2.6.19/arch/x86_64/kernel/hpet.c
===================================================================
@@ -508,4 +508,4 @@ static int __init init_hpet_clocksource(
 	return clocksource_register(&clocksource_hpet);
 }
 
-module_init(init_hpet_clocksource);
+clocksource_initcall(init_hpet_clocksource);
arch/x86_64/kernel/tsc.c +1 -2
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
@@ -224,5 +224,4 @@ static int __init init_tsc_clocksource(v
 	}
 	return 0;
 }
-
-module_init(init_tsc_clocksource);
+clocksource_initcall(init_tsc_clocksource);
drivers/clocksource/acpi_pm.c +7 -1
Index: linux-2.6.19/drivers/clocksource/acpi_pm.c
===================================================================
@@ -214,4 +214,10 @@ pm_good:
 	return clocksource_register(&clocksource_acpi_pm);
 }
 
-module_init(init_acpi_pm_clocksource);
+/*
+ * This clocksource is removed from the clocksource_initcall
+ * macro since it's mandatory for it to be in fs_initcall as the
+ * highest initcall level, or else it doesn't work properly with
+ * it's PCI fix ups.
+ */
+fs_initcall(init_acpi_pm_clocksource);
drivers/clocksource/cyclone.c +1 -1
Index: linux-2.6.19/drivers/clocksource/cyclone.c
===================================================================
@@ -116,4 +116,4 @@ static int __init init_cyclone_clocksour
 	return clocksource_register(&clocksource_cyclone);
 }
 
-module_init(init_cyclone_clocksource);
+clocksource_initcall(init_cyclone_clocksource);
drivers/clocksource/scx200_hrt.c +1 -1
Index: linux-2.6.19/drivers/clocksource/scx200_hrt.c
===================================================================
@@ -94,7 +94,7 @@ static int __init init_hrt_clocksource(v
 	return clocksource_register(&cs_hrt);
 }
 
-module_init(init_hrt_clocksource);
+clocksource_initcall(init_hrt_clocksource);
 
 MODULE_AUTHOR("Jim Cromie <[email protected]>");
 MODULE_DESCRIPTION("clocksource on SCx200 HiRes Timer");
include/linux/clocksource.h +6 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -41,6 +41,12 @@ extern struct atomic_notifier_head clock
 #define CLOCKSOURCE_NOTIFY_RATING	2
 #define CLOCKSOURCE_NOTIFY_FREQ		4
 
+/*
+ * Defined so the initcall can be changes without touching
+ * every clocksource in the system.
+ */
+#define clocksource_initcall(x)		fs_initcall(x)
+
 /**
  * clocksource_notifier_register - Registers a list change notifier
  * @nb:		pointer to a notifier block
kernel/time/clocksource.c +0 -13
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
@@ -38,22 +38,9 @@
  */
 static LIST_HEAD(clocksource_list);
 static DEFINE_SPINLOCK(clocksource_lock);
-static int finished_booting;
 
 ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
 
-/* clocksource_done_booting - Called near the end of bootup
- *
- * Hack to avoid lots of clocksource churn at boot time
- */
-static int __init clocksource_done_booting(void)
-{
-	finished_booting = 1;
-	return 0;
-}
-
-late_initcall(clocksource_done_booting);
-
 /**
  * __is_registered - Returns a clocksource if it's registered
  * @name:		name of the clocksource to return
kernel/time/jiffies.c +1 -1
Index: linux-2.6.19/kernel/time/jiffies.c
===================================================================
@@ -69,4 +69,4 @@ static int __init init_jiffies_clocksour
 	return clocksource_register(&clocksource_jiffies);
 }
 
-module_init(init_jiffies_clocksource);
+clocksource_initcall(init_jiffies_clocksource);
kernel/time/tick-sched.c +8 -0
Index: linux-2.6.19/kernel/time/tick-sched.c
===================================================================
@@ -540,6 +540,14 @@ int tick_check_oneshot_change(int allow_
 {
 	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 
+	/*
+	 * HRT or Dynamic tick can't be started during init, but it's possible
+	 * for generic time to switch to a good clock during init. So
+	 * explicitly check that we are't still booting here.
+	 */
+	if (system_state == SYSTEM_BOOTING)
+		return 0;
+
 	if (!test_and_clear_bit(0, &ts->check_clocks))
 		return 0;
 
kernel/time/timekeeping.c +7 -8
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
@@ -318,14 +318,6 @@ static __init int timekeeping_init_sysfs
 device_initcall(timekeeping_init_sysfs);
 #endif /* CONFIG_SYSFS */
 
-static int __init timekeeping_early_clockswitch(void)
-{
-	atomic_inc(&clock_check);
-	return 0;
-}
-
-late_initcall(timekeeping_early_clockswitch);
-
 /**
  * boot_override_clocksource - boot clock override
  * @str:	override name
@@ -471,6 +463,13 @@ static int __init timekeeping_init_devic
 	if (!error)
 		error = sysdev_register(&device_timer);
 
+#ifdef CONFIG_GENERIC_TIME
+	/*
+	 * Now we signal to switch to a high-res clock.
+	 */
+	atomic_inc(&clock_check);
+#endif
+
 	return error;
 }
 
#35 lore raw

Re: [PATCH 14/23] clocksource: increase initcall priority

drivers/clocksource/acpi_pm.c pm_good: · line 223

Quoted 8 lines · Daniel Walker
drivers/clocksource/acpi_pm.c +7 -1
-module_init(init_acpi_pm_clocksource);
+/*
+ * This clocksource is removed from the clocksource_initcall
+ * macro since it's mandatory for it to be in fs_initcall as the
+ * highest initcall level, or else it doesn't work properly with
+ * it's PCI fix ups.
+ */
+fs_initcall(init_acpi_pm_clocksource);

ugh - this bit looks quite interesting.

what's the purpose of this patch? Switching to high-res timers should be done late in the bootup - in case there's a problem it's more debuggable, etc.

Ingo

#36 lore raw

Re: [PATCH 14/23] clocksource: increase initcall priority

Quoted 13 lines · Ingo Molnar

drivers/clocksource/acpi_pm.c pm_good: · line 223

Quoted 8 lines · Daniel Walker
drivers/clocksource/acpi_pm.c +7 -1
-module_init(init_acpi_pm_clocksource);
+/*
+ * This clocksource is removed from the clocksource_initcall
+ * macro since it's mandatory for it to be in fs_initcall as the
+ * highest initcall level, or else it doesn't work properly with
+ * it's PCI fix ups.
+ */
+fs_initcall(init_acpi_pm_clocksource);

ugh - this bit looks quite interesting.

Quoted 3 lines

what's the purpose of this patch? Switching to high-res timers should be done late in the bootup - in case there's a problem it's more debuggable, etc.

The timekeeping code, and hrt/dynamic tick both wait till after boot up to switch to high res mode ..

The specific code block you commented on above was added cause acpi_pm has special pci fixups that don't function properly earlier in boot up. So it can't be arbitrarily raised to order in the initcall sequence ..

Daniel

#37 lore raw

Re: [PATCH 14/23] clocksource: increase initcall priority

Quoted 14 lines · Daniel Walker
Quoted 13 lines · Ingo Molnar

drivers/clocksource/acpi_pm.c pm_good: · line 223

Quoted 8 lines · Daniel Walker
drivers/clocksource/acpi_pm.c +7 -1
-module_init(init_acpi_pm_clocksource);
+/*
+ * This clocksource is removed from the clocksource_initcall
+ * macro since it's mandatory for it to be in fs_initcall as the
+ * highest initcall level, or else it doesn't work properly with
+ * it's PCI fix ups.
+ */
+fs_initcall(init_acpi_pm_clocksource);

ugh - this bit looks quite interesting.

Quoted 6 lines
Quoted 3 lines

what's the purpose of this patch? Switching to high-res timers should be done late in the bootup - in case there's a problem it's more debuggable, etc.

The timekeeping code, and hrt/dynamic tick both wait till after boot up to switch to high res mode ..

again, let me repeat the question: what's the purpose of this (whole!) patch. Not just of this chunk - the whole patch. You change around initcall levels - why? It makes no sense to me. The explanation in the patch header makes no sense to me.

Please if possible try to build clear arguments: first outlining "this is how it worked before: <X>", then outlining "this is how it will work after my change: <Y>", and then maybe a small blurb about "Y is better than X, because: <Z>". That X, Y, Z analysis is what is needed to accept a patch.

Quoted 4 lines

The specific code block you commented on above was added cause acpi_pm has special pci fixups that don't function properly earlier in boot up. So it can't be arbitrarily raised to order in the initcall sequence ..

i think you misunderstood my comment. In the chunk above you used fs_initcall() initcall instead of clocksource_initcall(). (Which is funny even ignoring the bad hack that clocksource_initcall is defined to fs_initcall.)

Ingo

#38 lore raw

Re: [PATCH 14/23] clocksource: increase initcall priority

Quoted 28 lines · Ingo Molnar
Quoted 14 lines · Daniel Walker
Quoted 13 lines · Ingo Molnar

drivers/clocksource/acpi_pm.c pm_good: · line 223

Quoted 8 lines · Daniel Walker
drivers/clocksource/acpi_pm.c +7 -1
-module_init(init_acpi_pm_clocksource);
+/*
+ * This clocksource is removed from the clocksource_initcall
+ * macro since it's mandatory for it to be in fs_initcall as the
+ * highest initcall level, or else it doesn't work properly with
+ * it's PCI fix ups.
+ */
+fs_initcall(init_acpi_pm_clocksource);

ugh - this bit looks quite interesting.

Quoted 6 lines
Quoted 3 lines

what's the purpose of this patch? Switching to high-res timers should be done late in the bootup - in case there's a problem it's more debuggable, etc.

The timekeeping code, and hrt/dynamic tick both wait till after boot up to switch to high res mode ..

again, let me repeat the question: what's the purpose of this (whole!) patch. Not just of this chunk - the whole patch. You change around initcall levels - why? It makes no sense to me. The explanation in the patch header makes no sense to me.

Quoted 5 lines

Please if possible try to build clear arguments: first outlining "this is how it worked before: <X>", then outlining "this is how it will work after my change: <Y>", and then maybe a small blurb about "Y is better than X, because: <Z>". That X, Y, Z analysis is what is needed to accept a patch.

I don't know that I could explain it better than what's in the patch header .. I'll think about it.

Quoted 9 lines
Quoted 4 lines

The specific code block you commented on above was added cause acpi_pm has special pci fixups that don't function properly earlier in boot up. So it can't be arbitrarily raised to order in the initcall sequence ..

i think you misunderstood my comment. In the chunk above you used fs_initcall() initcall instead of clocksource_initcall(). (Which is funny even ignoring the bad hack that clocksource_initcall is defined to fs_initcall.)

The purpose of clocksource_initcall is so the initcall can be increased without changing all the individual clocksources .. So I have to disconnect that from the acpi_pm because it can't tolerate it.

Daniel

#39 lore raw

Re: [PATCH 14/23] clocksource: increase initcall priority

Quoted 3 lines · Daniel Walker

The purpose of clocksource_initcall is so the initcall can be increased without changing all the individual clocksources .. So I have to disconnect that from the acpi_pm because it can't tolerate it.

Each clocksource has to decide on its own, when the registration is done. ARM clocksources register in the timer init, pm timer needs to wait.

So what exactly is solved by an extra initcall ?

tglx

#40 lore raw

PATCH 15/23 clocksource: add new flags

In reply to Daniel Walker

Compile patch .. This just adds some code so the next few patches will compile.

---
 include/linux/clocksource.h |    6 ++++++
 1 file changed, 6 insertions(+)
include/linux/clocksource.h +6 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -235,6 +235,12 @@ static inline void clocksource_calculate
 	c->xtime_interval = (u64)c->cycle_interval * c->mult;
 }
 
+#define CLOCKSOURCE_NOT_CONTINUOUS	1
+#define CLOCKSOURCE_UNSTABLE		2
+#define CLOCKSOURCE_NOT_ATOMIC		4
+#define CLOCKSOURCE_UNDER_32BITS	8
+#define CLOCKSOURCE_64BITS		16
+#define CLOCKSOURCE_PM_AFFECTED		32
 
 /* used to install a new clocksource */
 extern int clocksource_register(struct clocksource*);
#41 lore raw

PATCH 16/23 clocksource: arm update for new flags

In reply to Daniel Walker

Update ARM for new flags.

---
 arch/arm/mach-imx/time.c      |    1 -
 arch/arm/mach-ixp4xx/common.c |    1 -
 arch/arm/mach-netx/time.c     |    1 -
 arch/arm/mach-pxa/time.c      |    1 -
 4 files changed, 4 deletions(-)
arch/arm/mach-imx/time.c +0 -1
Index: linux-2.6.19/arch/arm/mach-imx/time.c
===================================================================
@@ -87,7 +87,6 @@ static struct clocksource clocksource_im
 	.read		= imx_get_cycles,
 	.mask		= 0xFFFFFFFF,
 	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init imx_clocksource_init(void)
arch/arm/mach-ixp4xx/common.c +0 -1
Index: linux-2.6.19/arch/arm/mach-ixp4xx/common.c
===================================================================
@@ -395,7 +395,6 @@ static struct clocksource clocksource_ix
 	.read		= ixp4xx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 unsigned long ixp4xx_timer_freq = FREQ;
arch/arm/mach-netx/time.c +0 -1
Index: linux-2.6.19/arch/arm/mach-netx/time.c
===================================================================
@@ -62,7 +62,6 @@ static struct clocksource clocksource_ne
 	.read		= netx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
arch/arm/mach-pxa/time.c +0 -1
Index: linux-2.6.19/arch/arm/mach-pxa/time.c
===================================================================
@@ -112,7 +112,6 @@ static struct clocksource clocksource_px
 	.read           = pxa_get_cycles,
 	.mask           = CLOCKSOURCE_MASK(32),
 	.shift          = 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init pxa_timer_init(void)
#42 lore raw

Re: [PATCH 16/23] clocksource: arm update for new flags

Review

Quoted 5 lines · Daniel Walker

Update ARM for new flags.

(quoted diff) +0 -1
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,

see my general objection to this change (under the [PATCH 22/23] subject), but even looking at the pure patch note that it does the flag update incorrectly and in a bisect-boot-unfriendly way: the queue at this point changes kernel functionality and has side-effects. The right way to do flags updates is to first introduce them, then change things over.

Ingo

#43 lore raw

PATCH 17/23 clocksource: avr32 update for new flags

In reply to Daniel Walker

Update avr32 for new flags.

---
 arch/avr32/kernel/time.c |    1 -
 1 file changed, 1 deletion(-)
arch/avr32/kernel/time.c +0 -1
Index: linux-2.6.19/arch/avr32/kernel/time.c
===================================================================
@@ -37,7 +37,6 @@ static struct clocksource clocksource_av
 	.read		= read_cycle_count,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift		= 16,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
#44 lore raw

PATCH 18/23 clocksource: i386 update for new flags

In reply to Daniel Walker

Update i386 for new flags.

---
 arch/i386/kernel/hpet.c    |    1 -
 arch/i386/kernel/i8253.c   |    1 +
 arch/i386/kernel/tsc.c     |   23 +++++++++++------------
 arch/i386/kernel/vmitime.c |    2 +-
 4 files changed, 13 insertions(+), 14 deletions(-)
arch/i386/kernel/hpet.c +0 -1
Index: linux-2.6.19/arch/i386/kernel/hpet.c
===================================================================
@@ -287,7 +287,6 @@ static struct clocksource clocksource_hp
 	.read		= read_hpet,
 	.mask		= HPET_MASK,
 	.shift		= HPET_SHIFT,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_hpet_clocksource(void)
arch/i386/kernel/i8253.c +1 -0
Index: linux-2.6.19/arch/i386/kernel/i8253.c
===================================================================
@@ -183,6 +183,7 @@ static struct clocksource clocksource_pi
 	.rating = 110,
 	.read	= pit_read,
 	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCKSOURCE_NOT_ATOMIC,
 	.mult	= 0,
 	.shift	= 20,
 };
arch/i386/kernel/tsc.c +11 -12
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
@@ -306,8 +306,7 @@ static struct clocksource clocksource_ts
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
-				  CLOCK_SOURCE_MUST_VERIFY,
+	.flags			= CLOCKSOURCE_64BITS | CLOCKSOURCE_PM_AFFECTED,
 };
 
 /*
@@ -316,10 +315,8 @@ static struct clocksource clocksource_ts
 void mark_tsc_unstable(void)
 {
 	/* check to see if we should switch to the safe clocksource: */
-	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 0)) {
-		clocksource_tsc.rating = 0;
-		clocksource_rating_change(&clocksource_tsc);
-	}
+	if (unlikely(!tsc_unstable))
+		clocksource_mark_unstable(&clocksource_tsc);
 
 	tsc_unstable = 1;
 }
@@ -434,17 +431,19 @@ static int __init init_tsc_clocksource(v
 		/* check blacklist */
 		dmi_check_system(bad_tsc_dmi_table);
 
-		if (unsynchronized_tsc()) /* mark unstable if unsynced */
+		if (unsynchronized_tsc()) { /* mark unstable if unsynced */
 			mark_tsc_unstable();
+			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE;
+		}
 		check_geode_tsc_reliable();
 		current_tsc_khz = tsc_khz;
 		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
 							clocksource_tsc.shift);
-		/* lower the rating if we already know its unstable: */
-		if (check_tsc_unstable()) {
-			clocksource_tsc.rating = 0;
-			clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
-		}
+
+		/* flags as unstable if we already know its unstable: */
+		if (check_tsc_unstable())
+			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE |
+						 CLOCKSOURCE_NOT_CONTINUOUS;
 
 		init_timer(&verify_tsc_freq_timer);
 		verify_tsc_freq_timer.function = verify_tsc_freq;
arch/i386/kernel/vmitime.c +1 -1
Index: linux-2.6.19/arch/i386/kernel/vmitime.c
===================================================================
@@ -115,7 +115,7 @@ static struct clocksource clocksource_vm
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
+	.flags			= CLOCKSOURCE_64BITS,
 };
 
 
#45 lore raw

PATCH 19/23 clocksource: mips update for new flags

In reply to Daniel Walker

Update mips for new flags.

---
 arch/mips/kernel/time.c |    1 -
 1 file changed, 1 deletion(-)
arch/mips/kernel/time.c +0 -1
Index: linux-2.6.19/arch/mips/kernel/time.c
===================================================================
@@ -307,7 +307,6 @@ static unsigned int __init calibrate_hpt
 struct clocksource clocksource_mips = {
 	.name		= "MIPS",
 	.mask		= 0xffffffff,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init init_mips_clocksource(void)
#46 lore raw

PATCH 20/23 clocksource: x86_64 update for new flags

In reply to Daniel Walker

Update x86_64 for new flags.

---
 arch/x86_64/kernel/hpet.c |    1 -
 arch/x86_64/kernel/tsc.c  |   11 ++++-------
 2 files changed, 4 insertions(+), 8 deletions(-)
arch/x86_64/kernel/hpet.c +0 -1
Index: linux-2.6.19/arch/x86_64/kernel/hpet.c
===================================================================
@@ -470,7 +470,6 @@ struct clocksource clocksource_hpet = {
 	.mask		= (cycle_t)HPET_MASK,
 	.mult		= 0, /* set below */
 	.shift		= HPET_SHIFT,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.vread		= vread_hpet,
 };
 
arch/x86_64/kernel/tsc.c +4 -7
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
@@ -195,18 +195,15 @@ static struct clocksource clocksource_ts
 	.read			= read_tsc,
 	.mask			= CLOCKSOURCE_MASK(64),
 	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
-				  CLOCK_SOURCE_MUST_VERIFY,
+	.flags                  = CLOCKSOURCE_64BITS | CLOCKSOURCE_PM_AFFECTED,
 	.vread			= vread_tsc,
 };
 
 void mark_tsc_unstable(void)
 {
 	/* check to see if we should switch to the safe clocksource: */
-	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 50)) {
-		clocksource_tsc.rating = 50;
-		clocksource_rating_change(&clocksource_tsc);
-	}
+	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 50))
+		clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE;
 
 	tsc_unstable = 1;
 }
@@ -218,7 +215,7 @@ static int __init init_tsc_clocksource(v
 		clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
 							clocksource_tsc.shift);
 		if (check_tsc_unstable())
-			clocksource_tsc.rating = 50;
+			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE;
 
 		return clocksource_register(&clocksource_tsc);
 	}
#47 lore raw

PATCH 21/23 clocksource: drivers/ update for new flags

In reply to Daniel Walker

Update drivers/ for new flags.

---
 drivers/clocksource/acpi_pm.c    |    2 +-
 drivers/clocksource/cyclone.c    |    1 -
 drivers/clocksource/scx200_hrt.c |    1 -
 3 files changed, 1 insertion(+), 3 deletions(-)
drivers/clocksource/acpi_pm.c +1 -1
Index: linux-2.6.19/drivers/clocksource/acpi_pm.c
===================================================================
@@ -73,7 +73,7 @@ static struct clocksource clocksource_ac
 	.mask		= (cycle_t)ACPI_PM_MASK,
 	.mult		= 0, /*to be caluclated*/
 	.shift		= 22,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.flags		= CLOCKSOURCE_UNDER_32BITS,
 
 };
 
drivers/clocksource/cyclone.c +0 -1
Index: linux-2.6.19/drivers/clocksource/cyclone.c
===================================================================
@@ -31,7 +31,6 @@ static struct clocksource clocksource_cy
 	.mask		= CYCLONE_TIMER_MASK,
 	.mult		= 10,
 	.shift		= 0,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_cyclone_clocksource(void)
drivers/clocksource/scx200_hrt.c +0 -1
Index: linux-2.6.19/drivers/clocksource/scx200_hrt.c
===================================================================
@@ -57,7 +57,6 @@ static struct clocksource cs_hrt = {
 	.rating		= 250,
 	.read		= read_hrt,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	/* mult, shift are set based on mhz27 flag */
 };
 
#48 lore raw

PATCH 22/23 clocksource: new clock lookup method

In reply to Daniel Walker

This patch modifies the current clocksource API so that clocks can be masked if they have specific negative qualities. For instance, if a clock is not atomic you can choose not to include it in the list you select from, atomic in this case being lockless.

The following qualities can be masked off,

#define CLOCKSOURCE_NOT_CONTINUOUS      1
#define CLOCKSOURCE_UNSTABLE            2
#define CLOCKSOURCE_NOT_ATOMIC          4
#define CLOCKSOURCE_UNDER_32BITS        8
#define CLOCKSOURCE_64BITS              16
#define CLOCKSOURCE_PM_AFFECTED         32

I modify the .flags to accomplish this.

The reasoning behind this is that it's not interesting to have a positive "rating" value, and have a positive flags value.

For instance, if the clock has a high rating you assume it's continuous. The selection process isn't helped by stating "continuous" in the flags.

The point is to list all the negative side effects that some clocks have which the programmer knows in advance that their code can not tolerate.

---
 include/linux/clocksource.h |   35 +++++++++++++++++++++++++-------
 kernel/time/clocksource.c   |   47 ++++++++++++++++++--------------------------
 kernel/time/jiffies.c       |    1 
 kernel/time/timekeeping.c   |   11 ++++++----
 4 files changed, 55 insertions(+), 39 deletions(-)
include/linux/clocksource.h +27 -8
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -30,6 +30,11 @@ extern struct clocksource clocksource_ji
 extern struct sys_device clocksource_sys_device;
 
 /*
+ * Read function type.
+ */
+typedef cycle_t (*clock_read_t)(void);
+
+/*
  * Allows inlined calling for notifier routines.
  */
 extern struct atomic_notifier_head clocksource_list_notifier;
@@ -40,6 +45,7 @@ extern struct atomic_notifier_head clock
 #define CLOCKSOURCE_NOTIFY_REGISTER	1
 #define CLOCKSOURCE_NOTIFY_RATING	2
 #define CLOCKSOURCE_NOTIFY_FREQ		4
+#define CLOCKSOURCE_NOTIFY_UNSTABLE	8
 
 /*
  * Defined so the initcall can be changes without touching
@@ -119,12 +125,6 @@ struct clocksource {
 	s64 error;
 };
 
-/*
- * Clock source flags bits::
- */
-#define CLOCK_SOURCE_IS_CONTINUOUS	0x01
-#define CLOCK_SOURCE_MUST_VERIFY	0x02
-
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
 
@@ -235,6 +235,9 @@ static inline void clocksource_calculate
 	c->xtime_interval = (u64)c->cycle_interval * c->mult;
 }
 
+/*
+ * Clocksource flags
+ */
 #define CLOCKSOURCE_NOT_CONTINUOUS	1
 #define CLOCKSOURCE_UNSTABLE		2
 #define CLOCKSOURCE_NOT_ATOMIC		4
@@ -243,9 +246,25 @@ static inline void clocksource_calculate
 #define CLOCKSOURCE_PM_AFFECTED		32
 
 /* used to install a new clocksource */
+extern void clocksource_mark_unstable(struct clocksource *);
+extern struct clocksource *clocksource_get_unstable(void);
 extern int clocksource_register(struct clocksource*);
 extern void clocksource_rating_change(struct clocksource*);
-extern struct clocksource * clocksource_get_clock(char*);
+extern struct clocksource * clocksource_get_clock(char*, unsigned long);
+
+
+/**
+ * clocksource_get_masked_clock - Finds highest rated clocksource w/o mask
+ * @mask:		Clocksource features that are not wanted.
+ *
+ * Returns the highest rated clocksource that doesn't have any of the bits set
+ * in mask. If none are register the jiffies clock is returned. If all the clocks
+ * have the mask bits set, then NULL is returned.
+ */
+static inline struct clocksource * clocksource_get_masked_clock(unsigned long mask)
+{
+	return clocksource_get_clock(NULL, mask);
+}
 
 /**
  * clocksource_get_best_clock - Finds highest rated clocksource
@@ -255,7 +274,7 @@ extern struct clocksource * clocksource_
  */
 static inline struct clocksource * clocksource_get_best_clock(void)
 {
-	return clocksource_get_clock(NULL);
+	return clocksource_get_clock(NULL, 0);
 }
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
kernel/time/clocksource.c +20 -27

104 lines not on this page · raw message

kernel/time/jiffies.c +1 -0
Index: linux-2.6.19/kernel/time/jiffies.c
===================================================================
@@ -62,6 +62,7 @@ struct clocksource clocksource_jiffies =
 	.mask		= 0xffffffff, /*32bits*/
 	.mult		= NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
 	.shift		= JIFFIES_SHIFT,
+	.flags		= CLOCKSOURCE_NOT_CONTINUOUS, /* not free running */
 };
 
 static int __init init_jiffies_clocksource(void)
kernel/time/timekeeping.c +7 -4
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
@@ -181,9 +181,12 @@ static void timekeeping_change_clocksour
 	u64 nsec;
 
 	if (!*override_name)
-		new = clocksource_get_clock(NULL);
+		/*
+		 * Mask off unstable clocks.
+		 */
+		new = clocksource_get_masked_clock(CLOCKSOURCE_UNSTABLE);
 	else
-		new = clocksource_get_clock(override_name);
+		new = clocksource_get_clock(override_name, 0);
 
 	if (clock != new) {
 		now = clocksource_read(new);
@@ -216,7 +219,7 @@ int timekeeping_is_continuous(void)
 	do {
 		seq = read_seqbegin(&xtime_lock);
 
-		ret = clock->flags & CLOCK_SOURCE_IS_CONTINUOUS;
+		ret = !(clock->flags & CLOCKSOURCE_NOT_CONTINUOUS);
 
 	} while (read_seqretry(&xtime_lock, seq));
 
@@ -231,7 +234,7 @@ clocksource_callback(struct notifier_blo
 
 	switch (op) {
 		case CLOCKSOURCE_NOTIFY_FREQ:
-		case CLOCKSOURCE_NOTIFY_RATING:
+		case CLOCKSOURCE_NOTIFY_UNSTABLE:
 			atomic_inc(&clock_check);
 	}
 

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#53 lore raw

Re: [PATCH 22/23] clocksource: new clock lookup method

Quoted 9 lines · Daniel Walker
Quoted 6 lines

please read my reply above! To repeat: such flags tend to get forgotten, resulting in a less safe default behavior. Clock hardware and thus clocksources are fundamentally fragile so we want to default to the safest behavior. I.e. if the IS_CONTINOUS flag is 'forgotten', the clock wont be usable as a clock verification base for example. The flag has to be affirmatively set to mark the clocksource continous.

I don't see this as an issue .. Your assuming that not continuous clocks will be prevalent which they aren't ..

And how does this change Ingo's statement ? Such beasts exist and having them default to the safe side is good.

Also I really do not see the "huge burden" for a clocksource coder to add this flag. If he forgets it, then he can not use highres / dynticks and nothing breaks.

tglx

#54 lore raw

Re: [PATCH 22/23] clocksource: new clock lookup method

Quoted 11 lines · Thomas Gleixner
Quoted 9 lines · Daniel Walker
Quoted 6 lines

please read my reply above! To repeat: such flags tend to get forgotten, resulting in a less safe default behavior. Clock hardware and thus clocksources are fundamentally fragile so we want to default to the safest behavior. I.e. if the IS_CONTINOUS flag is 'forgotten', the clock wont be usable as a clock verification base for example. The flag has to be affirmatively set to mark the clocksource continous.

I don't see this as an issue .. Your assuming that not continuous clocks will be prevalent which they aren't ..

Quoted 6 lines

And how does this change Ingo's statement ? Such beasts exist and having them default to the safe side is good.

Also I really do not see the "huge burden" for a clocksource coder to add this flag. If he forgets it, then he can not use highres / dynticks and nothing breaks.

We're not talking about a rare system runtime configuration . If that were the case I would agree safe is better..

I'm assuming that programmers will test their code, and others will review the code .. Catering to any other situation doesn't make sense to me. On top of that those clocks are rare, and not desirable ..

Daniel

#55 lore raw

Re: [PATCH 22/23] clocksource: new clock lookup method

Quoted 3 lines · Daniel Walker

I'm assuming that programmers will test their code, and others will review the code .. Catering to any other situation doesn't make sense to me. On top of that those clocks are rare, and not desirable ..

So what are you arguing about burden ? It is a property of the clocksource, that it is continuous, and not the other way round. It does not matter how rare or desirable devices are.

What about the other bunch of useless defines:

+#define CLOCKSOURCE_NOT_ATOMIC         4
+#define CLOCKSOURCE_UNDER_32BITS       8
+#define CLOCKSOURCE_64BITS             16

Are those just for fun or are you actually putting the burden to get them straight on the poor overworked clocksource developer ?

Also please define bit values as hexadecimal constants and not as integers.

tglx

#56 lore raw

PATCH 23/23 clocksource tsc: add verify routine

In reply to Daniel Walker

I've included this as another user of the clocksource interface. I don't see a usage for this across all achitectures. So a fully generic version isn't needed.

I modified this from the pre 2.6.20-rc6-mm2 release to make the routine smaller and to make it select a clocksource inside the timer. It should work with an HPET.

---
 arch/i386/kernel/tsc.c      |   55 ++++++++++++++++++++++++++++----------------
 include/linux/clocksource.h |   16 ++++++++++++
 2 files changed, 51 insertions(+), 20 deletions(-)
arch/i386/kernel/tsc.c +35 -20
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
@@ -343,47 +343,59 @@ static struct dmi_system_id __initdata b
 	 {}
 };
 
-#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
+#define WATCHDOG_TRESHOLD (NSEC_PER_SEC >> 4)
+#define TSC_FREQ_CHECK_INTERVAL (MSEC_PER_SEC/2)
 static struct timer_list verify_tsc_freq_timer;
+struct clocksource *verify_clock;
 
 /* XXX - Probably should add locking */
 static void verify_tsc_freq(unsigned long unused)
 {
-	static u64 last_tsc;
-	static unsigned long last_jiffies;
-
-	u64 now_tsc, interval_tsc;
-	unsigned long now_jiffies, interval_jiffies;
+	static cycle_t last_tsc, last_verify;
 
+	cycle_t now_tsc, verify_clock_now, interval;
+	s64 nsecs;
 
 	if (check_tsc_unstable())
 		return;
 
-	rdtscll(now_tsc);
-	now_jiffies = jiffies;
+	if (unlikely(system_state != SYSTEM_RUNNING))
+		goto out_timer;
 
-	if (!last_jiffies) {
-		goto out;
+	if (unlikely(!verify_clock)) {
+		verify_clock =
+			clocksource_get_masked_clock(CLOCKSOURCE_PM_AFFECTED);
+		printk("TSC: selected %s clocksource for TSC verification.\n",
+		       verify_clock->name);
 	}
 
-	interval_jiffies = now_jiffies - last_jiffies;
-	interval_tsc = now_tsc - last_tsc;
-	interval_tsc *= HZ;
-	do_div(interval_tsc, cpu_khz*1000);
+	now_tsc = clocksource_read(&clocksource_tsc);
+	verify_clock_now = clocksource_read(verify_clock);
+
+	if (!last_tsc)
+		goto out;
 
-	if (interval_tsc < (interval_jiffies * 3 / 4)) {
+	interval = clocksource_subtract(verify_clock, verify_clock_now,
+					last_verify);
+	nsecs = cyc2ns(verify_clock, interval);
+
+	interval = clocksource_subtract(&clocksource_tsc, now_tsc, last_tsc);
+	nsecs -= cyc2ns(&clocksource_tsc, interval);
+
+	if (nsecs > WATCHDOG_TRESHOLD) {
 		printk("TSC appears to be running slowly. "
-			"Marking it as unstable\n");
+		       "Marking it as unstable");
 		mark_tsc_unstable();
 		return;
 	}
 
 out:
-	last_tsc = now_tsc;
-	last_jiffies = now_jiffies;
+  	last_tsc = now_tsc;
+	last_verify = verify_clock_now;
+out_timer:
 	/* set us up to go off on the next interval: */
 	mod_timer(&verify_tsc_freq_timer,
-		jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
+		  jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
 }
 
 /*
@@ -444,7 +456,10 @@ static int __init init_tsc_clocksource(v
 		if (check_tsc_unstable())
 			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE |
 						 CLOCKSOURCE_NOT_CONTINUOUS;
-
+		/*
+		 * The verify routine will select the right clock after the
+		 * system boots fully.
+		 */
 		init_timer(&verify_tsc_freq_timer);
 		verify_tsc_freq_timer.function = verify_tsc_freq;
 		verify_tsc_freq_timer.expires =
include/linux/clocksource.h +16 -0
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
@@ -207,6 +207,22 @@ static inline s64 cyc2ns(struct clocksou
 }
 
 /**
+ * clocksource_subtract - Subtract two cycle_t timestamps
+ * @cs:		Clocksource the timestamp came from
+ * @stop:	Stop timestamp
+ * @start:	Start timestamp
+ *
+ * This subtract accounts for rollover by using the clocksource mask.
+ * The clock can roll over only once, after that this subtract will not
+ * work properly.
+ */
+static inline s64 clocksource_subtract(struct clocksource* cs, cycle_t stop,
+				       cycle_t start)
+{
+	return ((stop - start) & cs->mask);
+}
+
+/**
  * clocksource_calculate_interval - Calculates a clocksource interval struct
  *
  * @c:		Pointer to clocksource.
#57 lore raw

Re: [PATCH 23/23] clocksource tsc: add verify routine

Quoted 3 lines · Daniel Walker

I've included this as another user of the clocksource interface. I don't see a usage for this across all achitectures. So a fully generic version isn't needed.

well, this implementation is buggy in at least two ways:

firstly, it allows a circular verification dependency in highres+dyntick mode between the jiffies and tsc clocksources.

secondly, verification is not done while the system is booting up:

Quoted 2 lines

static void verify_tsc_freq(unsigned long unused) {

[...]

arch/i386/kernel/tsc.c static struct dmi_system_id __initdata b · line 363

Quoted 2 lines
arch/i386/kernel/tsc.c +2 -0
+	if (unlikely(system_state != SYSTEM_RUNNING))
+		goto out_timer;

so we should just go with Thomas' patch:

clocksource-add-verification-watchdog-helper.patch

which has been based on and tested on actual systems affected by these problems.

Ingo

#58 lore raw

Re: [PATCH 23/23] clocksource tsc: add verify routine

Quoted 10 lines · Ingo Molnar
Quoted 3 lines · Daniel Walker

I've included this as another user of the clocksource interface. I don't see a usage for this across all achitectures. So a fully generic version isn't needed.

well, this implementation is buggy in at least two ways:

firstly, it allows a circular verification dependency in highres+dyntick mode between the jiffies and tsc clocksources.

In the current implementation, it's only happens if the only clocks that exist are "tsc" and "jiffies" which makes verification impossible anyway .. It's unlikely, but it is possible , the fix is not that complex.

Quoted 1 line

secondly, verification is not done while the system is booting up:

Do you know that this is needed ? The current implementation (clocksource watchdog) doesn't fully settle until after device_initcall() .. So boot-up is about 99% complete ..

It's trivial to make my version do verification during most of device_initcall() ..

Daniel

#59 lore raw

Re: [PATCH 23/23] clocksource tsc: add verify routine

Quoted 9 lines · Daniel Walker
Quoted 4 lines

well, this implementation is buggy in at least two ways:

firstly, it allows a circular verification dependency in highres+dyntick mode between the jiffies and tsc clocksources.

In the current implementation, it's only happens if the only clocks that exist are "tsc" and "jiffies" which makes verification impossible anyway .. It's unlikely, but it is possible , the fix is not that complex.

Wrong. You actually can verify against jiffies. Johns orginal code did this and mine does too. Actually this _IS_ necessary otherwise you can not detect that the BIOS changed the cpu freqeuncy behind the kernels back.

The circular problem is only relevant when you switch to highres/nohz.

tglx

#60 lore raw

Re: [PATCH 23/23] clocksource tsc: add verify routine

In reply to Daniel Walker
Quoted 7 lines · Daniel Walker
Quoted 2 lines

firstly, it allows a circular verification dependency in highres+dyntick mode between the jiffies and tsc clocksources.

In the current implementation, it's only happens if the only clocks that exist are "tsc" and "jiffies" which makes verification impossible anyway .. It's unlikely, but it is possible , the fix is not that complex.

yes, the fix is not that complex and it already exists: Thomas' clocksource-add-verification-watchdog-helper.patch. You said before that Thomas' code was unnecessarily generic, but your version contained at least one bug, despite having had review feedback about precisely that issue.

Ingo