-mm generic clocksoure API
Subsystems (4)
cover -mm generic clocksoure API
This patch set is meant to modify the clocksource structure and API so that it can be used by more than just the timekeeping code. My motivation is mainly that I feel the current clocksource interface could be used for much more than just timekeeping. So if we keep the clocksource interface (which I think we should) then we should get everything out of it that we can.
This set modifies the API, then converts the time keeping code over to the new API. I also added a generic sched_clock() which just re-uses the clocksource interface to provide a high quality scheduling clock (assuming a good clocksource). Several ARM board just output nanoseconds based on jiffies which is still possible with the generic sched_clock().
I tested this on SMP and UP x86, and compile tested for ARM.
Daniel
--
PATCH 1/10 -mm clocksource: increase initcall priority
Since it's likely that this interface would get used during bootup I moved all the clocksource registration into the postcore initcall. This also eliminated some clocksource shuffling during bootup.
--- arch/i386/kernel/hpet.c | 2 +- arch/i386/kernel/i8253.c | 2 +- arch/i386/kernel/tsc.c | 2 +- drivers/clocksource/acpi_pm.c | 2 +- drivers/clocksource/cyclone.c | 2 +- drivers/clocksource/scx200_hrt.c | 2 +- kernel/time/clocksource.c | 15 +-------------- kernel/time/jiffies.c | 2 +- 8 files changed, 8 insertions(+), 21 deletions(-)
arch/i386/kernel/hpet.c +1 -1
@@ -64,4 +64,4 @@ static int __init init_hpet_clocksource(return clocksource_register (&clocksource_hpet); } -module_init (init_hpet_clocksource); +postcore_initcall (init_hpet_clocksource);
arch/i386/kernel/i8253.c +1 -1
@@ -115,4 +115,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); +postcore_initcall (init_pit_clocksource);
arch/i386/kernel/tsc.c +1 -1
@@ -475,4 +475,4 @@ static int __init init_tsc_clocksource(vreturn 0 ; } -module_init (init_tsc_clocksource); +postcore_initcall (init_tsc_clocksource);
drivers/clocksource/acpi_pm.c +1 -1
@@ -174,4 +174,4 @@ pm_good:return clocksource_register (&clocksource_acpi_pm); } -module_init (init_acpi_pm_clocksource); +postcore_initcall (init_acpi_pm_clocksource);
drivers/clocksource/cyclone.c +1 -1
@@ -116,4 +116,4 @@ static int __init init_cyclone_clocksourreturn clocksource_register (&clocksource_cyclone); } -module_init (init_cyclone_clocksource); +postcore_initcall (init_cyclone_clocksource);
drivers/clocksource/scx200_hrt.c +1 -1
@@ -94,7 +94,7 @@ static int __init init_hrt_clocksource(vreturn clocksource_register (&cs_hrt); } -module_init (init_hrt_clocksource); +postcore_initcall (init_hrt_clocksource);MODULE_AUTHOR ("Jim Cromie <[email protected]>" );MODULE_DESCRIPTION ("clocksource on SCx200 HiRes Timer" );
kernel/time/clocksource.c +1 -14
@@ -50,19 +50,6 @@ static struct clocksource *next_clocksoustatic LIST_HEAD (clocksource_list);static DEFINE_SPINLOCK (clocksource_lock);static char override_name[32 ]; -static int finished_booting; - -/* 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);/** * clocksource_get_next - Returns the selected clocksource
@@ -73,7 +60,7 @@ struct clocksource *clocksource_get_nextunsigned long flags;spin_lock_irqsave (&clocksource_lock, flags); -if (next_clocksource && finished_booting) { +if (next_clocksource) { curr_clocksource = next_clocksource; next_clocksource =NULL ; }
kernel/time/jiffies.c +1 -1
@@ -70,4 +70,4 @@ static int __init init_jiffies_clocksourreturn clocksource_register (&clocksource_jiffies); } -module_init (init_jiffies_clocksource); +postcore_initcall (init_jiffies_clocksource);
--
Re: [PATCH 01/10] -mm clocksource: increase initcall priority
First of all, sorry for not reviewing these patches sooner. Its been sitting in on my todo list for way too long. Thanks for continuing to push it despite my slowness.
Quoted 4 lines · On Thu, 2006-08-03 at 20:24 -0700, [email protected] wrote:
plain text document attachment (clocksource_init_call.patch) Since it's likely that this interface would get used during bootup I moved all the clocksource registration into the postcore initcall. This also eliminated some clocksource shuffling during bootup.
This one looks interesting. As long as it works as advertised I'm fine with it, although I worry it might bring up some initialization ordering issues. It will need some careful testing in -mm.
thanks
-john
PATCH 2/10 -mm clocksource: small cleanup
In reply to [email protected]--- include/linux/clocksource.h | 2 +- kernel/time/clocksource.c | 6 +++--- kernel/timer.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-)
include/linux/clocksource.h +1 -1
@@ -159,7 +159,7 @@ static inline s64 cyc2ns(struct clocksou* Unless you're the timekeeping code, you should not be using this! */ static inline void clocksource_calculate_interval (struct clocksource *c, -unsigned long length_nsec) +unsigned long length_nsec) {u64 tmp;
kernel/time/clocksource.c +3 -3
@@ -143,7 +143,7 @@ int clocksource_register(struct clocksou/* check if clocksource is already registered */ if (is_registered_source (c)) {printk ("register_clocksource: Cannot register %s. " -"Already registered!" , c->name); +"Already registered!" , c->name); ret = -EBUSY ; }else {/* register it */
@@ -262,10 +262,10 @@ sysfs_show_available_clocksources(struct* Sysfs setup bits: */ static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources, - sysfs_override_clocksource); + sysfs_override_clocksource); static SYSDEV_ATTR(available_clocksource, 0600, - sysfs_show_available_clocksources, NULL); + sysfs_show_available_clocksources, NULL);static struct sysdev_class clocksource_sysclass = {set_kset_name ("clocksource" ),
kernel/timer.c +4 -3
@@ -924,7 +924,7 @@ static int change_clocksource(void) clock = new; clock->cycle_last = now;printk (KERN_INFO "Time: %s clocksource has been installed.\n" , - clock->name); + clock->name);return 1 ; }else if (clock->update_callback) {return clock->update_callback ();
@@ -932,7 +932,7 @@ static int change_clocksource(void) return 0; }#else -#define change_clocksource () (0) +#define change_clocksource () do { 0; } while(0)#endif /**
@@ -1149,7 +1149,8 @@ static void update_wall_time(void)/* accumulate error between NTP and clock interval */ clock->error +=current_tick_length (); - clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); + clock->error -= clock->xtime_interval << + (TICK_LENGTH_SHIFT - clock->shift); }/* correct the clock when NTP error is too big */
--
Re: [PATCH 02/10] -mm clocksource: small cleanup
Quoted 2 lines · On Thu, 2006-08-03 at 20:24 -0700, [email protected] wrote:
plain text document attachment (clocksource_cleanup.patch)
Signed-off-by Daniel Walker <[email protected]>
thanks
-john
Quoted 79 lines
--- include/linux/clocksource.h | 2 +- kernel/time/clocksource.c | 6 +++--- kernel/timer.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-)Index:
linux-2.6.17/include/linux/clocksource.h
===================================================================include/linux/clocksource.h +1
-1@@ -159,7 +159,7 @@ static inline s64 cyc2ns(struct clocksou* Unless you're the timekeeping code, you should not be using this! */ static inline void clocksource_calculate_interval (struct clocksource *c, -unsigned long length_nsec) +unsigned long length_nsec) {u64 tmp;Index:
linux-2.6.17/kernel/time/clocksource.c
===================================================================kernel/time/clocksource.c +3
-3@@ -143,7 +143,7 @@ int clocksource_register(struct clocksou/* check if clocksource is already registered */ if (is_registered_source (c)) {printk ("register_clocksource: Cannot register %s. " -"Already registered!" , c->name); +"Already registered!" , c->name); ret = -EBUSY ; }else {/* register it */ @@ -262,10 +262,10 @@ sysfs_show_available_clocksources(struct* Sysfs setup bits: */ static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources, - sysfs_override_clocksource); + sysfs_override_clocksource); static SYSDEV_ATTR(available_clocksource, 0600, - sysfs_show_available_clocksources, NULL); + sysfs_show_available_clocksources, NULL);static struct sysdev_class clocksource_sysclass = {set_kset_name ("clocksource" ),Index:
linux-2.6.17/kernel/timer.c
===================================================================kernel/timer.c +4
-4@@ -924,7 +924,7 @@ static int change_clocksource(void) clock = new; clock->cycle_last = now;printk (KERN_INFO "Time: %s clocksource has been installed.\n" , - clock->name); + clock->name);return 1 ; }else if (clock->update_callback) {return clock->update_callback ();@@ -932,7 +932,7 @@ static int change_clocksource(void) return 0; }#else -#define change_clocksource () (0) +#define change_clocksource () do { 0; } while(0)#endif /** @@ -1149,7 +1149,8 @@ static void update_wall_time(void)/* accumulate error between NTP and clock interval */ clock->error +=current_tick_length (); - clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); + clock->error -= clock->xtime_interval << + (TICK_LENGTH_SHIFT - clock->shift); }/* correct the clock when NTP error is too big */ --
PATCH 3/10 -mm clocksource: enable plist
In reply to [email protected]I have a feeling this might get a little more discussion than the other stuff, so it's in it's own patch.
--- init/Kconfig | 1 - lib/Kconfig | 6 ------ lib/Makefile | 3 +-- 3 files changed, 1 insertion(+), 9 deletions(-)
init/Kconfig +0 -1
@@ -407,7 +407,6 @@ config BASE_FULL config RT_MUTEXES boolean - select PLIST config FUTEX bool "Enable futex support" if EMBEDDED
lib/Kconfig +0 -6
@@ -86,10 +86,4 @@ config TEXTSEARCH_BM config TEXTSEARCH_FSM tristate -# -# plist support is select#ed if needed -# -config PLIST - boolean - endmenu
lib/Makefile +1 -2
@@ -5,7 +5,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \ idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \ - sha1.o + sha1.o plist.o lib-$(CONFIG_SMP) += cpumask.o
@@ -26,7 +26,6 @@ lib-$(CONFIG_SEMAPHORE_SLEEPERS) += sema lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o -obj-$(CONFIG_PLIST) += plist.o obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o obj-$(CONFIG_DEBUG_LIST) += list.o
--
PATCH 4/10 -mm clocksource: add some new API calls
In reply to [email protected]This introduces some new API calls,
- clocksource_get_clock()
Allows a clock lookup by name.
- clocksource_rating_change()
Used by a clocksource to signal a rating change. Replaces reselect_clocksource()
I also moved the the clock source list to a plist, which removes some lookup overhead in the average case.
--- arch/i386/kernel/tsc.c | 2 include/linux/clocksource.h | 45 ++++++++++++- kernel/time/clocksource.c | 149 ++++++++++++++++++++++++++++---------------- 3 files changed, 139 insertions(+), 57 deletions(-)
arch/i386/kernel/tsc.c +1 -1
@@ -351,7 +351,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 ; }
include/linux/clocksource.h +41 -4
74 lines not on this page · raw message
kernel/time/clocksource.c +97 -52
238 lines not on this page · raw message
--
Re: [PATCH 04/10] -mm clocksource: add some new API calls
Quoted 120 lines · On Thu, 2006-08-03 at 20:24 -0700, [email protected] wrote:
plain text document attachment (clocksource_user_api.patch) This introduces some new API calls,
-
clocksource_get_clock()
Allows a clock lookup by name.
-clocksource_rating_change()
Used by a clocksource to signal a rating change. Replacesreselect_clocksource()I also moved the the clock source list to a plist, which removes some lookup overhead in the average case.
Signed-off-by Daniel Walker <[email protected]>--- arch/i386/kernel/tsc.c | 2 include/linux/clocksource.h | 45 ++++++++++++- kernel/time/clocksource.c | 149 ++++++++++++++++++++++++++++---------------- 3 files changed, 139 insertions(+), 57 deletions(-)Index:
linux-2.6.17/arch/i386/kernel/tsc.c
===================================================================arch/i386/kernel/tsc.c +1
-1@@ -351,7 +351,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 ; }Index:
linux-2.6.17/include/linux/clocksource.h
===================================================================include/linux/clocksource.h +41
-4@@ -12,12 +12,20 @@#include <linux/timex.h> #include <linux/time.h> #include <linux/list.h> +#include <linux/plist.h> +#include <linux/sysdev.h> #include <asm/div64.h> #include <asm/io.h> /* clocksource cycle base type */ typedef u64 cycle_t ; +/* +* This is the only generic clock, it should be used +* for early initialization. +*/ +extern struct clocksource clocksource_jiffies; +/** * struct clocksource - hardware abstraction for a free running counter * Provides mostly state-free accessors to the underlying hardware. @@ -51,7 +59,7 @@ typedef u64 cycle_t;*/ struct clocksource {char *name; -struct list_head list; +struct plist_node list;int rating;cycle_t (*read)(void );cycle_t mask;@@ -148,6 +156,25 @@ static inline s64 cyc2ns(struct clocksou }/** +* ns2cyc - converts nanoseconds to clocksource cycles +* @cs: Pointer to clocksource +* @ns: Nanoseconds +* +* Uses the clocksource to convert nanoseconds back to cycles. +* +* XXX - This could use some mult_lxl_ll() asm optimization +*/ +static inline cycle_t ns2cyc (struct clocksource *cs,s64 ns) +{ +u64 ret = ns; + + ret <<= cs->shift; +do_div (ret, cs->mult); + +return ret; +} + +/** * clocksource_calculate_interval - Calculates a clocksource interval struct * * @c: Pointer to clocksource. @@ -178,8 +205,18 @@ 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 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 ); +}#endif /* _LINUX_CLOCKSOURCE_H */ Index:
linux-2.6.17/kernel/time/clocksource.c
===================================================================
kernel/time/clocksource.c line 38
Quoted 7 lines
kernel/time/clocksource.c +4
-0@@ -32,13 +32,18 @@/* XXX - Would like a better way for initializing curr_clocksource */ extern struct clocksource clocksource_jiffies; +/* +* Internally used to invert the rating, so lower is better. +*/ +#define CLOCKSOURCE_RATING (x) (INT_MAX-x)
Since this is used for the plist bits, could it get a more explicit name?
Quoted 130 lines
kernel/time/clocksource.c +52
-37/*[Clocksource internal variables]--------- * curr_clocksource: * currently selected clocksource. Initialized to clocksource_jiffies. * next_clocksource: * pending next selected clocksource. * clocksource_list: -* linked list with the registered clocksources +* priority list with the registered clocksources * clocksource_lock: * protects manipulations to curr_clocksource and next_clocksource * and the clocksource_list @@ -47,7 +52,8 @@ extern struct clocksource clocksource_ji*/ static struct clocksource *curr_clocksource = &clocksource_jiffies;static struct clocksource *next_clocksource; -static LIST_HEAD (clocksource_list); +static struct plist_head clocksource_list = +PLIST_HEAD_INIT (clocksource_list, clocksource_lock);static DEFINE_SPINLOCK (clocksource_lock);static char override_name[32 ];@@ -70,84 +76,111 @@ struct clocksource *clocksource_get_next }/** -* select_clocksource - Finds the best registered clocksource. +* __is_registered - Returns a clocksource if it's registered +* @name: name of the clocksource to return * * Private function. Must hold clocksource_lock when called. * -* Looks through the list of registered clocksources, returning -* the one with the highest rating value. If there is a clocksource -* name that matches the override string, it returns that clocksource. +* Returns the clocksource if registered, zero otherwise. +* If no clocksources are registered the jiffies clock is +* returned. */ -static struct clocksource *select_clocksource (void ) +static struct clocksource *__is_registered (char * name) { -struct clocksource *best =NULL ; -struct list_head *tmp; +struct plist_node *tmp; -list_for_each (tmp, &clocksource_list) { +plist_for_each (tmp, &clocksource_list) {struct clocksource *src; src = list_entry(tmp, struct clocksource, list); -if (!best) - best = src; - -/* check for override: */ -if (strlen (src->name) ==strlen (override_name) && - !strcmp (src->name, override_name)) { - best = src; -break ; - } -/* pick the highest rating: */ -if (src->rating > best->rating) - best = src; +if (!strcmp (src->name, name)) +return src; } -return best; +return 0 ; }/** -* is_registered_source - Checks if clocksource is registered -* @c: pointer to a clocksource +* __get_clock - Finds a specific clocksource +* @name: name of the clocksource to return * -* Private helper function. Must hold clocksource_lock when called. +* Private function. Must hold clocksource_lock when called. * -* Returns one if the clocksource is already registered, zero otherwise. +* Returns the clocksource if registered, zero otherwise. +* If the @name is null the highest rated clock is returned. */ -static int is_registered_source (struct clocksource *c) +static inline struct clocksource *__get_clock (char * name) { -int len =strlen (c->name); -struct list_head *tmp; -list_for_each (tmp, &clocksource_list) { -struct clocksource *src; +if (unlikely (plist_head_empty (&clocksource_list))) +return &clocksource_jiffies; - src = list_entry(tmp, struct clocksource, list); -if (strlen (src->name) == len && !strcmp (src->name, c->name)) -return 1 ; - } +if (!name) + return plist_first_entry(&clocksource_list, struct clocksource, + list); -return 0 ; +return __is_registered (name); +} + +/** +* 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. +* +* Looks through the list of registered clocksources, returning
kernel/time/clocksource.c struct clocksource *clocksource_get_next · line 158
Quoted 10 lines
kernel/time/clocksource.c +9
-0+* the one with the highest rating value. If there is a clocksource +* name that matches the override string, it returns that clocksource. +*/ +static struct clocksource *select_clocksource (void ) +{ +if (!*override_name) + return plist_first_entry(&clocksource_list, struct clocksource, + list); +return get_clock (override_name); }
This all looks good.
Quoted 7 lines
kernel/time/clocksource.c +2
-1/** * clocksource_register - Used to install new clocksources * @t: clocksource to be registered * -* Returns -EBUSY if registration fails, zero otherwise. +* Returns -EBUSY clock is already registered, +* Returns -EINVAL if clocksource is invalid,
kernel/time/clocksource.c struct clocksource *clocksource_get_next · line 175
Quoted 10 lines
kernel/time/clocksource.c +4
-0+* Return zero otherwise. */ int clocksource_register (struct clocksource *c) {int ret =0 ;unsigned long flags; +if (unlikely (!c)) +return -EINVAL ; +
I'm not sure I understand the need for this. Is it really likely someone would pass NULL to clocksource_register()?
Quoted 67 lines
kernel/time/clocksource.c +23
-12spin_lock_irqsave (&clocksource_lock, flags); -/* check if clocksource is already registered */ -if (is_registered_source (c)) { -printk ("register_clocksource: Cannot register %s. " +if (unlikely (!plist_node_empty (&c->list) &&__is_registered (c->name))) { +printk ("register_clocksource: Cannot register %s clocksource. " "Already registered!" , c->name); ret = -EBUSY ; }else { -/* register it */ -list_add (&c->list, &clocksource_list); +plist_node_init (&c->list,CLOCKSOURCE_RATING (c->rating)); +plist_add (&c->list, &clocksource_list);/* scan the registered clocksources, and pick the best one */ next_clocksource =select_clocksource (); }@@ -157,21 +190,32 @@ int clocksource_register(struct clocksouEXPORT_SYMBOL (clocksource_register);/** -* clocksource_reselect - Rescan list for next clocksource +* clocksource_rating_change - Allows dynamic rating changes for register +* clocksources. * -* A quick helper function to be used if a clocksource changes its -* rating. Forces the clocksource list to be re-scanned for the best -* clocksource. +* Signals that a clocksource is dynamically changing it's rating. +* This could happen if a clocksource becomes more/less stable. */ -void clocksource_reselect (void ) +void clocksource_rating_change (struct clocksource *c) {unsigned long flags; +if (unlikely (plist_node_empty (&c->list))) +return ; +spin_lock_irqsave (&clocksource_lock, flags); + +/* +* Re-register the clocksource with it's new rating. +*/ +plist_del (&c->list, &clocksource_list); +plist_node_init (&c->list,CLOCKSOURCE_RATING (c->rating)); +plist_add (&c->list, &clocksource_list); + next_clocksource =select_clocksource ();spin_unlock_irqrestore (&clocksource_lock, flags); } -EXPORT_SYMBOL (clocksource_reselect); +EXPORT_SYMBOL (clocksource_rating_change);/** * sysfs_show_current_clocksources - sysfs interface for current clocksource @@ -236,16 +280,17 @@ static ssize_t sysfs_override_clocksourc* @dev: unused * @buf: char buffer to be filled with clocksource list * -* Provides sysfs interface for listing registered clocksources +* Provides sysfs interface for listing registered clocksources. +* Output in priority sorted order. */ static ssize_t sysfs_show_available_clocksources (struct sys_device *dev,char *buf) {
kernel/time/clocksource.c static ssize_t sysfs_override_clocksourc · line 296
Quoted 10 lines
kernel/time/clocksource.c +2
-2-struct list_head *tmp; +struct plist_node *tmp;char *curr = buf;spin_lock_irq (&clocksource_lock); -list_for_each (tmp, &clocksource_list) { +plist_for_each (tmp, &clocksource_list) {struct clocksource *src; src = list_entry(tmp, struct clocksource, list);
No real objections to this one.
thanks
-john
Re: [PATCH 04/10] -mm clocksource: add some new API calls
Quoted 8 lines
kernel/time/clocksource.c line 38
Quoted 5 lines
kernel/time/clocksource.c +4
-0+/* +* Internally used to invert the rating, so lower is better. +*/ +#define CLOCKSOURCE_RATING (x) (INT_MAX-x)Since this is used for the plist bits, could it get a more explicit name?
Sure, like CLOCKSOURCE_INVERT_RATING()
Quoted 11 lines
kernel/time/clocksource.c struct clocksource *clocksource_get_next · line 175
Quoted 8 lines
int
clocksource_register(struct clocksource *c)
{kernel/time/clocksource.c +3
-0int ret =0 ;unsigned long flags; +if (unlikely (!c)) +return -EINVAL ; +I'm not sure I understand the need for this. Is it really likely someone would pass NULL to
clocksource_register()?
Not likely, I was just covering all possibilities.. It might be better as a BUG_ON() actually.
Daniel
Re: [PATCH 04/10] -mm clocksource: add some new API calls
Quoted 12 lines · Daniel Walker
Quoted 11 lines
kernel/time/clocksource.c struct clocksource *clocksource_get_next · line 175
Quoted 8 lines
int
clocksource_register(struct clocksource *c)
{kernel/time/clocksource.c +3
-0int ret =0 ;unsigned long flags; +if (unlikely (!c)) +return -EINVAL ; +I'm not sure I understand the need for this. Is it really likely someone would pass NULL to
clocksource_register()?
Quoted 2 lines
Not likely, I was just covering all possibilities.. It might be better as a
BUG_ON()actually.
BUG_ON is the only thing, which can be correct here. Registering a NULL clocksource simply is a bug, but even the BUG_ON is overkill here.
tglx
PATCH 5/10 -mm clocksource: convert generic timeofday
In reply to [email protected]This patch shifts some of the code around so that the time of day override happens inside kernel/timer.c.
The biggest timeofday changes are in update_wall_time() and change_clocksource(). I removed the unconditional call to change_clocksource(), and replaced it with a single atomic check. The atomic is asserted only when a clock change is needed. update_callback is no longer driven from update_wall_time().
The fast path is now a single atomic check.
--- include/linux/clocksource.h | 2 kernel/time/clocksource.c | 183 +++++--------------------------------------- kernel/timer.c | 162 +++++++++++++++++++++++++++++++++----- 3 files changed, 164 insertions(+), 183 deletions(-)
include/linux/clocksource.h +2 -0
@@ -206,6 +206,8 @@ static inline void clocksource_calculate/* used to install a new clocksource */ extern int clocksource_register (struct clocksource *); +extern int clocksource_sysfs_register (struct sysdev_attribute *); +extern void clocksource_sysfs_unregister (struct sysdev_attribute *);extern void clocksource_rating_change (struct clocksource *);extern struct clocksource *clocksource_get_clock (char *);
kernel/time/clocksource.c +21 -162
256 lines not on this page · raw message
kernel/timer.c +141 -21
208 lines not on this page · raw message
--
PATCH 6/10 -mm clocksource: add block notifier
In reply to [email protected]Adds a call back interface for register/rating change events.
--- include/linux/clocksource.h | 9 +++++++++ kernel/time/clocksource.c | 19 ++++++++++++++++++- kernel/timer.c | 12 ++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-)
include/linux/clocksource.h +9 -0
@@ -14,6 +14,7 @@#include <linux/list.h> #include <linux/plist.h> #include <linux/sysdev.h> +#include <linux/notifier.h> #include <asm/div64.h> #include <asm/io.h>
@@ -26,6 +27,12 @@ typedef u64 cycle_t;*/ extern struct clocksource clocksource_jiffies; +/* +* Block notifier flags. +*/ +#define CLOCKSOURCE_NOTIFY_REGISTER 1 +#define CLOCKSOURCE_NOTIFY_RATING 2 +/** * struct clocksource - hardware abstraction for a free running counter * Provides mostly state-free accessors to the underlying hardware.
@@ -206,6 +213,8 @@ static inline void clocksource_calculate/* used to install a new clocksource */ extern int clocksource_register (struct clocksource *); +extern int clocksource_notifier_register (struct notifier_block *); +extern int clocksource_notifier_unregister (struct notifier_block *);extern int clocksource_sysfs_register (struct sysdev_attribute *);extern void clocksource_sysfs_unregister (struct sysdev_attribute *);extern void clocksource_rating_change (struct clocksource *);
kernel/time/clocksource.c +18 -1
@@ -44,6 +44,18 @@static struct plist_head clocksource_list =PLIST_HEAD_INIT (clocksource_list, clocksource_lock);static DEFINE_SPINLOCK (clocksource_lock); +static ATOMIC_NOTIFIER_HEAD (clocksource_list_notifier); + +/** +* clocksource_notifier_register - Registers a list change notifier +* @nb: pointer to a notifier block +* +* Returns zero always. +*/ +int clocksource_notifier_register (struct notifier_block *nb) +{ +return atomic_notifier_chain_register (&clocksource_list_notifier, nb); +}/** * __is_registered - Returns a clocksource if it's registered
@@ -135,6 +147,9 @@ int clocksource_register(struct clocksouplist_add (&c->list, &clocksource_list); }spin_unlock_irqrestore (&clocksource_lock, flags); + +atomic_notifier_call_chain (&clocksource_list_notifier, +CLOCKSOURCE_NOTIFY_REGISTER , c);return ret; }EXPORT_SYMBOL (clocksource_register);
@@ -162,7 +177,9 @@ void clocksource_rating_change(struct clplist_node_init (&c->list,CLOCKSOURCE_RATING (c->rating));plist_add (&c->list, &clocksource_list); -/* XXX: Add block notifier to signal new rating */ +atomic_notifier_call_chain (&clocksource_list_notifier, +CLOCKSOURCE_NOTIFY_RATING , c); +spin_unlock_irqrestore (&clocksource_lock, flags); }EXPORT_SYMBOL (clocksource_rating_change);
kernel/timer.c +12 -0
@@ -1030,6 +1030,17 @@ static int __init boot_override_clocksou }__setup ("timeofday_clocksource=" , boot_override_clocksource); +static int +clocksource_callback (struct notifier_block *nb,unsigned long op,void *c) +{ +atomic_inc (&clock_check); +return 0 ; +} + +static struct notifier_block clocksource_nb = { + .notifier_call = clocksource_callback, +}; +#else #define change_clocksource (x) do { 0; } while(0)#endif
@@ -1120,6 +1131,7 @@ static int __init timekeeping_init_devic#ifdef CONFIG_GENERIC_TIME atomic_inc (&clock_check); +clocksource_notifier_register (&clocksource_nb);clocksource_sysfs_register (&attr_timeofday_clocksource);#endif return error;
--
PATCH 7/10 -mm clocksource: remove update_callback
In reply to [email protected]With the new notifier block the update_callback becomes obsolete.
--- arch/i386/kernel/tsc.c | 5 +++-- include/linux/clocksource.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-)
arch/i386/kernel/tsc.c +3 -2
@@ -60,9 +60,12 @@ static inline int check_tsc_unstable(voireturn tsc_unstable; } +static int tsc_update_callback (void );void mark_tsc_unstable (void ) { tsc_unstable =1 ; + +tsc_update_callback (); }EXPORT_SYMBOL_GPL (mark_tsc_unstable);
@@ -322,7 +325,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 ) {
@@ -340,7 +342,6 @@ static struct clocksource clocksource_ts .mask = CLOCKSOURCE_MASK(64), .mult = 0, /* to be set */ .shift = 22, - .update_callback = tsc_update_callback, .is_continuous = 1, };
include/linux/clocksource.h +0 -2
@@ -60,7 +60,6 @@ extern struct clocksource clocksource_ji* 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 * @is_continuous: defines if clocksource is free-running. * @cycle_interval: Used internally by timekeeping core, please ignore. * @xtime_interval: Used internally by timekeeping core, please ignore.
@@ -73,7 +72,6 @@ struct clocksource {cycle_t mask;u32 mult;u32 shift; -int (*update_callback)(void );int is_continuous;/* timekeeping specific data, ignore */
--
Re: [PATCH 07/10] -mm clocksource: remove update_callback
Quoted 17 lines · On Thu, 2006-08-03 at 20:24 -0700, [email protected] wrote:
plain text document attachment (clocksource_remove_update_callback.patch) With the new notifier block the
update_callbackbecomes obsolete.Signed-off-by Daniel Walker <[email protected]>--- arch/i386/kernel/tsc.c | 5 +++-- include/linux/clocksource.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-)Index:
linux-2.6.17/arch/i386/kernel/tsc.c
===================================================================arch/i386/kernel/tsc.c +0
-0@@ -60,9 +60,12 @@ static inline int check_tsc_unstable(voireturn tsc_unstable;
arch/i386/kernel/tsc.c static inline int check_tsc_unstable(voi · line 70
Quoted 10 lines
arch/i386/kernel/tsc.c +3
-0} +static int tsc_update_callback (void );void mark_tsc_unstable (void ) { tsc_unstable =1 ; + +tsc_update_callback (); }EXPORT_SYMBOL_GPL (mark_tsc_unstable);
Hmm. I'd like to keep mark_tsc_unstable to just be a flag rather then the hook into the update_callback(), as it may be called quite frequently.
I do agree we can kill the update_callback all together, but we probably need to do sometihng like:
void mark_tsc_unstable(void)
{
if (unlikely(!tsc_unstable)) {
clocksource_tsc.rating = 50;
clocksource_rating_change(&clocksource_tsc);
}
tsc_unstable = 1;
}Quoted 30 lines
arch/i386/kernel/tsc.c +0
-2@@ -322,7 +325,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 ) {@@ -340,7 +342,6 @@ static struct clocksource clocksource_ts .mask = CLOCKSOURCE_MASK(64), .mult = 0, /* to be set */ .shift = 22, - .update_callback = tsc_update_callback, .is_continuous = 1, };Index:
linux-2.6.17/include/linux/clocksource.h
===================================================================include/linux/clocksource.h +0
-1@@ -60,7 +60,6 @@ extern struct clocksource clocksource_ji* 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 * @is_continuous: defines if clocksource is free-running. * @cycle_interval: Used internally by timekeeping core, please ignore. * @xtime_interval: Used internally by timekeeping core, please ignore.
include/linux/clocksource.h struct clocksource { · line 77
Quoted 7 lines
include/linux/clocksource.h +0
-1@@ -73,7 +72,6 @@ struct clocksource {cycle_t mask;u32 mult;u32 shift; -int (*update_callback)(void );int is_continuous;/* timekeeping specific data, ignore */
Other then the top bit I don't have an issue w/ this.
thanks
-john
PATCH 8/10 -mm clocksource: cleanup on -mm
In reply to [email protected]Some additional clean up only on the -mm tree. Moves the adjust functions into kernel/time/clocksource.c .
These functions directly modify the clocksource multiplier based on ntp error. These adjustments will effect other users of that clock. This hasn't been addressed in my patch set, since it needs some discussion.
--- include/linux/clocksource.h | 1 kernel/time/clocksource.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ kernel/timer.c | 83 ---------------------------------------- 3 files changed, 91 insertions(+), 83 deletions(-)
include/linux/clocksource.h +1 -0
@@ -217,6 +217,7 @@ extern int clocksource_sysfs_register(stextern void clocksource_sysfs_unregister (struct sysdev_attribute *);extern void clocksource_rating_change (struct clocksource *);extern struct clocksource *clocksource_get_clock (char *); +extern void clocksource_adjust (struct clocksource *,s64 );/** * clocksource_get_best_clock - Finds highest rated clocksource
kernel/time/clocksource.c +90 -0
96 lines not on this page · raw message
kernel/timer.c +0 -83
89 lines not on this page · raw message
--
Re: [PATCH 08/10] -mm clocksource: cleanup on -mm
Quoted 8 lines · On Thu, 2006-08-03 at 20:24 -0700, [email protected] wrote:
plain text document attachment (clocksource_api_cleanup_on_mm.patch) Some additional clean up only on the -mm tree. Moves the adjust functions into
kernel/time/clocksource.c.These functions directly modify the clocksource multiplier based on ntp error. These adjustments will effect other users of that clock. This hasn't been addressed in my patch set, since it needs some discussion.
Hmmmm. Yea, some additional discussion here would probably be needed
At the moment, I'd prefer to keep the clocksource_adjust bits with the timekeeping code, however I'd also prefer to remove the timekeeping specific fields (cycle_last, cycle_interval, xtime_nsec, xtime_interval, error) from the clocksource structure and instead keep them in a timekeeping specific structure (which may also point to a clocksource).
This would keep a clean separation between the clocksource's abstraction that keeps as little state as possible and the timekeeping code's internal state. However the point you bring up above is an interesting
issue: Do all users of the generic clocksource structure want the clocksource to be NTP adjusted?
If we allow for non-ntp adjusted access to the clocksources, we may have consistency issues between users comparing say sched_clock() and clock_gettime() intervals. Further, if those users do want NTP adjusted counters, why aren't they just using the timekeeping subsystem?
This does put some question as to what exactly would be the uses of the clocksource structure outside of the timekeeping realm. Sure, sched_clock() is a reasonable example, although since sched_clock has such specific latency needs (we probably shouldn't go touching off-chip hardware on every sched_clock call) and can be careful to avoid TSC skew unlike the timekeeping code, its selection algorithm is going to be very arch specific. So I'm not sure its really an ideal use of the clocksource interface (as its not too difficult to just keep sched_clock arch specific).
I do feel making the abstraction clean and generic is a good thing just for code readability (and I very much appreciate your work here!), but I'm not really sure that the need for clocksource access outside the timekeeping subsystem has been well expressed. Do you have some other examples other then sched_clock that might show further uses for this abstraction?
thanks
-john
Re: [PATCH 08/10] -mm clocksource: cleanup on -mm
Quoted 9 lines · john stultz
Hmmmm. Yea, some additional discussion here would probably be needed
At the moment, I'd prefer to keep the
clocksource_adjustbits with the timekeeping code, however I'd also prefer to remove the timekeeping specific fields (cycle_last,cycle_interval,xtime_nsec,xtime_interval, error) from the clocksource structure and instead keep them in a timekeeping specific structure (which may also point to a clocksource).
Quoted 5 lines
This would keep a clean separation between the clocksource's abstraction that keeps as little state as possible and the timekeeping code's internal state. However the point you bring up above is an interesting
issue: Do all users of the generic clocksource structure want the clocksource to be NTP adjusted?
Since the output from the clocksource is a lowlevel timestamp I don't think the users of it would want it to be ntp adjusted. It would also be a little odd, since the ntp adjustment would be attached only to a single clock.
Quoted 4 lines
If we allow for non-ntp adjusted access to the clocksources, we may have consistency issues between users comparing say
sched_clock()andclock_gettime()intervals. Further, if those users do want NTP adjusted counters, why aren't they just using the timekeeping subsystem?
I imagine the users of the interface would be compartmentalized. Taking sched_clock as an example the output is only compared to itself and not to output from other interfaces.
Quoted 9 lines
This does put some question as to what exactly would be the uses of the clocksource structure outside of the timekeeping realm. Sure,
sched_clock()is a reasonable example, although sincesched_clockhas such specific latency needs (we probably shouldn't go touching off-chip hardware on everysched_clockcall) and can be careful to avoid TSC skew unlike the timekeeping code, its selection algorithm is going to be very arch specific. So I'm not sure its really an ideal use of the clocksource interface (as its not too difficult to just keepsched_clockarch specific).
Part of the reason to have a generic sched_clock() (and the generic clocksource interface in general) is to eliminate the inefficienty of duplicating shift and mult functionality in each arch (and on ARM it's per board). So if you correctly implement a clocksource structure for your hardware you will at least expose a usable sched_clock() and generic timeofday. Then if we add more users of the interface then more functionality is exposed.
Another instances of this is when instrumentation is needing a of fast low level timestamp. In the past to accomplish this one would need a per arch change to read a clock, then potentially duplicate a shift and mult type computation in order to covert to nanosecond. One good example of this is latency tracing in the -rt tree. I can imagine some good and valid instrumentation having a long road of acceptable because the time stamping portion would need to flow through several different arch and potentially board maintainers.
I've also imagined that some usage of jiffies could be converted to use this interface if it was appropriate. Since jiffies is hooked to the tick, and the tick is getting more and more irregular, a clocksource might be a relatively good replacement.
Quoted 6 lines
I do feel making the abstraction clean and generic is a good thing just for code readability (and I very much appreciate your work here!), but I'm not really sure that the need for clocksource access outside the timekeeping subsystem has been well expressed. Do you have some other examples other then
sched_clockthat might show further uses for this abstraction?
I've converted latency tracing to an earlier version of the API , but I don't have any other examples prepared. I think it's important to get the API settled before I start converting anything else.
Daniel
Re: [PATCH 08/10] -mm clocksource: cleanup on -mm
Quoted 21 lines · Daniel Walker
Quoted 9 lines · john stultz
Hmmmm. Yea, some additional discussion here would probably be needed
At the moment, I'd prefer to keep the
clocksource_adjustbits with the timekeeping code, however I'd also prefer to remove the timekeeping specific fields (cycle_last,cycle_interval,xtime_nsec,xtime_interval, error) from the clocksource structure and instead keep them in a timekeeping specific structure (which may also point to a clocksource).Quoted 5 lines
This would keep a clean separation between the clocksource's abstraction that keeps as little state as possible and the timekeeping code's internal state. However the point you bring up above is an interesting
issue: Do all users of the generic clocksource structure want the clocksource to be NTP adjusted?Since the output from the clocksource is a lowlevel timestamp I don't think the users of it would want it to be ntp adjusted. It would also be a little odd, since the ntp adjustment would be attached only to a single clock.
Quoted 8 lines
Quoted 4 lines
If we allow for non-ntp adjusted access to the clocksources, we may have consistency issues between users comparing say
sched_clock()andclock_gettime()intervals. Further, if those users do want NTP adjusted counters, why aren't they just using the timekeeping subsystem?I imagine the users of the interface would be compartmentalized. Taking
sched_clockas an example the output is only compared to itself and not to output from other interfaces.
Agreed on both points. Although I suspect this point will need to be made explicit.
Quoted 10 lines
Quoted 9 lines
This does put some question as to what exactly would be the uses of the clocksource structure outside of the timekeeping realm. Sure,
sched_clock()is a reasonable example, although sincesched_clockhas such specific latency needs (we probably shouldn't go touching off-chip hardware on everysched_clockcall) and can be careful to avoid TSC skew unlike the timekeeping code, its selection algorithm is going to be very arch specific. So I'm not sure its really an ideal use of the clocksource interface (as its not too difficult to just keepsched_clockarch specific).
Quoted 4 lines
Part of the reason to have a generic
sched_clock()(and the generic clocksource interface in general) is to eliminate the inefficienty of duplicating shift and mult functionality in each arch (and on ARM it's per board).
Well, a coherent accumulation and NTP adjustment method for continuous clocksources was a big motivator for the timekeeping work. Also the quantity of duplicated arch specific time code is a bit larger then the sched_clock(), but that itself isn't a mark against utilizing clocksources for sched_clock().
Quoted 4 lines
So if you correctly implement a clocksource structure for
your hardware you will at least expose a usablesched_clock()and generic timeofday. Then if we add more users of the interface then more functionality is exposed.
Well, this point might need some work. sched_clock has quite a different correctness/performance tradeoff when compared against timeofday. If one correctly implements a clocksource for something like the ACPI PM, I doubt they'd want to use it for sched_clock (due to its ~1us access latency). Additionally, since sched_clock doesn't require (for its original purpose, at least) the TSC synchronization that is essential for timekeeping, how will sched_clock determine which clocksource to use on a system were the TSC is unsyched and marked bad?
Quoted 8 lines
Another instances of this is when instrumentation is needing a of fast low level timestamp. In the past to accomplish this one would need a per arch change to read a clock, then potentially duplicate a shift and mult type computation in order to covert to nanosecond. One good example of this is latency tracing in the -rt tree. I can imagine some good and valid instrumentation having a long road of acceptable because the time stamping portion would need to flow through several different arch and potentially board maintainers.
This sounds reasonable, but also I'd question if sched_clock or get_cycles would be appropriate here. Further, if the mult/shift cost is acceptable, why not just use the timeofday as the cost will be similar.
Quoted 4 lines
I've also imagined that some usage of jiffies could be converted to use this interface if it was appropriate. Since jiffies is hooked to the tick, and the tick is getting more and more irregular, a clocksource might be a relatively good replacement.
Hmmm. That'd be a harder sell for me. Probably would want those users to move to the timeofday, or alternatively, drive jiffies off of the timekeeping code rather then the interrupt handler to ensure it stays synced (something I'm plotting once the timekeeping code settles down).
Quoted 10 lines
Quoted 6 lines
I do feel making the abstraction clean and generic is a good thing just for code readability (and I very much appreciate your work here!), but I'm not really sure that the need for clocksource access outside the timekeeping subsystem has been well expressed. Do you have some other examples other then
sched_clockthat might show further uses for this abstraction?I've converted latency tracing to an earlier version of the API , but I don't have any other examples prepared. I think it's important to get the API settled before I start converting anything else.
Again, I think your patch set looks good for the most part (its just the last few bits I worry about). I'm very much interested to see where you go with this, as I feel sched_clock (on i386 atleast) needs some love and attention and I'm excited to see new uses for the clocksource abstraction. However, I do want to make sure that we think the use cases out to avoid over-engineering the wrong bits.
thanks
-john
Re: [PATCH 08/10] -mm clocksource: cleanup on -mm
Quoted 6 lines · john stultz
Quoted 3 lines
I imagine the users of the interface would be compartmentalized. Taking
sched_clockas an example the output is only compared to itself and not to output from other interfaces.Agreed on both points. Although I suspect this point will need to be made explicit.
Yeah, that's a good idea.
Quoted 5 lines
Quoted 4 lines
So if you correctly implement a clocksource structure for
your hardware you will at least expose a usablesched_clock()and generic timeofday. Then if we add more users of the interface then more functionality is exposed.
Quoted 8 lines
Well, this point might need some work.
sched_clockhas quite a different correctness/performance tradeoff when compared against timeofday. If one correctly implements a clocksource for something like the ACPI PM, I doubt they'd want to use it forsched_clock(due to its ~1us access latency). Additionally, sincesched_clockdoesn't require (for its original purpose, at least) the TSC synchronization that is essential for timekeeping, how willsched_clockdetermine which clocksource to use on a system were the TSC is unsyched and marked bad?
sched_clock would use the highest rated clock in the system, and if that becomes unstable it uses jiffies. That could mean using the acpi_pm if it's the highest rated clock. Some code would have the be added to force sched_clock to use the tsc.
I did some hackbench runs using the tsc vs. acpi_pm, and there was only minimal differences (within the margin of error). It could be different with other pm timers, but that was the result on mine. I also did some tests of tsc vs. pit which showed some extensive differences. It added 10 seconds to "hackbench 80" . So I'm not entirely convinced that acpi_pm is totally inappropriate as a fall back, in the case of un-synced TSC.
I wish I had an HPET to test.
Quoted 9 lines
Quoted 8 lines
Another instances of this is when instrumentation is needing a of fast low level timestamp. In the past to accomplish this one would need a per arch change to read a clock, then potentially duplicate a shift and mult type computation in order to covert to nanosecond. One good example of this is latency tracing in the -rt tree. I can imagine some good and valid instrumentation having a long road of acceptable because the time stamping portion would need to flow through several different arch and potentially board maintainers.
Quoted 3 lines
This sounds reasonable, but also I'd question if
sched_clockorget_cycleswould be appropriate here. Further, if the mult/shift cost is acceptable, why not just use the timeofday as the cost will be similar.
get_cycles() isn't implemented on all arches. sched_clock() sometimes returns jiffies converted to nanosecond depending on the arch (it does this sometimes on i386 even). Also sched_clock() has the disadvantage of converting to nanosecond each time it runs, which isn't always ideal. get_cycles(), if it's implemented, doesn't come with a standard way to find a) the clock it accesses b) the frequency of the clock.
So they both have disadvantages over the clocksource interface.
Quoted 9 lines
Quoted 4 lines
I've also imagined that some usage of jiffies could be converted to use this interface if it was appropriate. Since jiffies is hooked to the tick, and the tick is getting more and more irregular, a clocksource might be a relatively good replacement.
Hmmm. That'd be a harder sell for me. Probably would want those users to move to the timeofday, or alternatively, drive jiffies off of the timekeeping code rather then the interrupt handler to ensure it stays synced (something I'm plotting once the timekeeping code settles down).
It's case by case. I wouldn't say all jiffies uses could use timeofday calls, and I wouldn't say they could all use a clocksource. I'd imagine some could be converted to a clocksource though.
I'd be interested to see any jiffies changes you make.
Quoted 11 lines
Quoted 10 lines
Quoted 6 lines
I do feel making the abstraction clean and generic is a good thing just for code readability (and I very much appreciate your work here!), but I'm not really sure that the need for clocksource access outside the timekeeping subsystem has been well expressed. Do you have some other examples other then
sched_clockthat might show further uses for this abstraction?I've converted latency tracing to an earlier version of the API , but I don't have any other examples prepared. I think it's important to get the API settled before I start converting anything else.
Quoted 6 lines
Again, I think your patch set looks good for the most part (its just the last few bits I worry about). I'm very much interested to see where you go with this, as I feel
sched_clock(on i386 atleast) needs some love and attention and I'm excited to see new uses for the clocksource abstraction. However, I do want to make sure that we think the use cases out to avoid over-engineering the wrong bits.
Your questions are certainly appropriate, and I appreciate the review. There's not to many other responses so far.
Daniel
PATCH 9/10 -mm clocksource: initialize list value
In reply to [email protected]This is an optional change to the clocksource structures. If the list field is initialized it allows clocksource_register to complete faster since it doesn't have the scan the list of clocks doing strcmp on each.
--- arch/i386/kernel/hpet.c | 1 + arch/i386/kernel/i8253.c | 1 + arch/i386/kernel/tsc.c | 1 + drivers/clocksource/acpi_pm.c | 1 + drivers/clocksource/cyclone.c | 1 + drivers/clocksource/scx200_hrt.c | 1 + include/linux/clocksource.h | 3 +++ 7 files changed, 9 insertions(+)
arch/i386/kernel/hpet.c +1 -0
@@ -27,6 +27,7 @@ static struct clocksource clocksource_hp .mult = 0, /* set below */ .shift = HPET_SHIFT, .is_continuous = 1, + .list = CLOCKSOURCE_LIST_INIT(clocksource_hpet.list), };static int __init init_hpet_clocksource (void )
arch/i386/kernel/i8253.c +1 -0
@@ -105,6 +105,7 @@ static struct clocksource clocksource_pi .mask = CLOCKSOURCE_MASK(32), .mult = 0, .shift = 20, + .list = CLOCKSOURCE_LIST_INIT(clocksource_pit.list), };static int __init init_pit_clocksource (void )
arch/i386/kernel/tsc.c +1 -0
@@ -282,6 +282,7 @@ static struct clocksource clocksource_ts .mult = 0, /* to be set */ .shift = 22, .is_continuous = 1, + .list = CLOCKSOURCE_LIST_INIT(clocksource_tsc.list), };static int tsc_update_callback (void )
drivers/clocksource/acpi_pm.c +1 -0
@@ -73,6 +73,7 @@ static struct clocksource clocksource_ac .mult = 0, /*to be caluclated*/ .shift = 22, .is_continuous = 1, + .list = CLOCKSOURCE_LIST_INIT(clocksource_acpi_pm.list), };
drivers/clocksource/cyclone.c +1 -0
@@ -32,6 +32,7 @@ static struct clocksource clocksource_cy .mult = 10, .shift = 0, .is_continuous = 1, + .list = CLOCKSOURCE_LIST_INIT(clocksource_cyclone.list), };static int __init init_cyclone_clocksource (void )
drivers/clocksource/scx200_hrt.c +1 -0
@@ -58,6 +58,7 @@ static struct clocksource cs_hrt = { .read = read_hrt, .mask = CLOCKSOURCE_MASK(32), .is_continuous = 1, + .list = CLOCKSOURCE_LIST_INIT(cs_hrt.list),/* mult, shift are set based on mhz27 flag */ };
include/linux/clocksource.h +3 -0
@@ -82,6 +82,9 @@ struct clocksource {/* simplify initialization of mask field */ #define CLOCKSOURCE_MASK (bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1) +/* Abstracted list initialization */ +#define CLOCKSOURCE_LIST_INIT (x) PLIST_NODE_INIT(x, 0) +/** * clocksource_khz2mult - calculates mult from khz and shift * @khz: Clocksource frequency in KHz
--
PATCH 10/10 -mm clocksource: add generic sched_clock()
In reply to [email protected]Adds a generic sched_clock, along with a boot time override for the scheduler clocksource. Hopefully the config option would eventually be removed.
--- arch/i386/Kconfig | 4 +++ arch/i386/kernel/tsc.c | 61 ------------------------------------------------ kernel/sched.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 61 deletions(-)
arch/i386/Kconfig +4 -0
@@ -18,6 +18,10 @@ config GENERIC_TIME bool default y +config GENERIC_SCHED_CLOCK + bool + default y + config LOCKDEP_SUPPORT bool default y
arch/i386/kernel/tsc.c +0 -61
79 lines not on this page · raw message
kernel/sched.c +62 -0
80 lines not on this page · raw message
--