Scheduler Profiling - Use Immediate Values
PATCH 1/1 Scheduler Profiling - Use Immediate Values
Scheduler Profiling - Use Immediate Values
Use immediate values with lower d-cache hit in optimized version as a condition for scheduler profiling call.
Depends on the Immediate values patches, applies to 2.6.23-rc4-mm1.
--- drivers/kvm/svm.c | 2 +- drivers/kvm/vmx.c | 2 +- include/linux/profile.h | 10 ++++------ kernel/profile.c | 38 ++++++++++++++++++++++++++------------ kernel/sched.c | 3 ++- 5 files changed, 34 insertions(+), 21 deletions(-)
kernel/profile.c +26 -12
@@ -42,9 +42,6 @@ static int (*timer_hook)(struct pt_regsstatic atomic_t *prof_buffer;static unsigned long prof_len, prof_shift; -int prof_on__read_mostly ; -EXPORT_SYMBOL_GPL (prof_on); -static cpumask_t prof_cpu_mask =CPU_MASK_ALL ;#ifdef CONFIG_SMP static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -52,6 +49,14 @@ static DEFINE_PER_CPU(int, cpu_profile_fstatic DEFINE_MUTEX (profile_flip_mutex);#endif /* CONFIG_SMP */ +/* Immediate values */ +immediate_char_t sleep_profiling__read_mostly , + sched_profiling__read_mostly , + kvm_profiling__read_mostly , + cpu_profiling__read_mostly ; +EXPORT_SYMBOL_GPL (kvm_profiling); +EXPORT_SYMBOL_GPL (cpu_profiling); +static int __init profile_setup (char * str) {static char __initdata schedstr[] ="schedule" ;
@@ -60,7 +65,7 @@ static int __init profile_setup(char * sint par;if (!strncmp (str, sleepstr,strlen (sleepstr))) { - prof_on =SLEEP_PROFILING ; +immediate_set_early (&sleep_profiling,1 );if (str[strlen (sleepstr)] ==',' ) str +=strlen (sleepstr) +1 ;if (get_option (&str, &par))
@@ -69,7 +74,7 @@ static int __init profile_setup(char * s"kernel sleep profiling enabled (shift: %ld)\n" , prof_shift); }else if (!strncmp (str, schedstr,strlen (schedstr))) { - prof_on =SCHED_PROFILING ; +immediate_set_early (&sched_profiling,1 );if (str[strlen (schedstr)] ==',' ) str +=strlen (schedstr) +1 ;if (get_option (&str, &par))
@@ -78,7 +83,7 @@ static int __init profile_setup(char * s"kernel schedule profiling enabled (shift: %ld)\n" , prof_shift); }else if (!strncmp (str, kvmstr,strlen (kvmstr))) { - prof_on =KVM_PROFILING ; +immediate_set_early (&kvm_profiling,1 );if (str[strlen (kvmstr)] ==',' ) str +=strlen (kvmstr) +1 ;if (get_option (&str, &par))
@@ -88,7 +93,7 @@ static int __init profile_setup(char * s prof_shift); }else if (get_option (&str, &par)) { prof_shift = par; - prof_on =CPU_PROFILING ; +immediate_set_early (&cpu_profiling,1 );printk (KERN_INFO "kernel profiling enabled (shift: %ld)\n" , prof_shift); }
@@ -99,7 +104,10 @@ __setup("profile=", profile_setup);void __init profile_init (void ) { -if (!prof_on) +if (!_immediate_read (&sleep_profiling) && + !_immediate_read (&sched_profiling) && + !_immediate_read (&kvm_profiling) && + !_immediate_read (&cpu_profiling))return ;/* only text is profiled */
@@ -288,7 +296,7 @@ void profile_hits(int type, void *__pc,int i, j, cpu;struct profile_hit *hits; -if (prof_on != type || !prof_buffer) +if (!prof_buffer)return ; pc =min ((pc - (unsigned long )_stext) >> prof_shift, prof_len -1 ); i = primary = (pc & (NR_PROFILE_GRP -1 )) <<PROFILE_GRPSHIFT ;
@@ -398,7 +406,7 @@ void profile_hits(int type, void *__pc, {unsigned long pc; -if (prof_on != type || !prof_buffer) +if (!prof_buffer)return ; pc = ((unsigned long )__pc - (unsigned long )_stext) >> prof_shift;atomic_add (nr_hits, &prof_buffer[min (pc, prof_len -1 )]);
@@ -555,7 +563,10 @@ static int __init create_hash_tables(voi }return 0 ; out_cleanup: - prof_on =0 ; +immediate_set_early (&sleep_profiling,0 ); +immediate_set_early (&sched_profiling,0 ); +immediate_set_early (&kvm_profiling,0 ); +immediate_set_early (&cpu_profiling,0 );smp_mb ();on_each_cpu (profile_nop,NULL ,0 ,1 );for_each_online_cpu (cpu) {
@@ -582,7 +593,10 @@ static int __init create_proc_profile(vo {struct proc_dir_entry *entry; -if (!prof_on) +if (!_immediate_read (&sleep_profiling) && + !_immediate_read (&sched_profiling) && + !_immediate_read (&kvm_profiling) && + !_immediate_read (&cpu_profiling))return 0 ;if (create_hash_tables ())return -1 ;
include/linux/profile.h +4 -6
@@ -7,10 +7,12 @@#include <linux/init.h> #include <linux/cpumask.h> #include <linux/cache.h> +#include <linux/immediate.h> #include <asm/errno.h> -extern int prof_on__read_mostly ; +extern immediate_char_t sleep_profiling, sched_profiling, kvm_profiling, + cpu_profiling;#define CPU_PROFILING 1#define SCHED_PROFILING 2
@@ -35,11 +37,7 @@ void profile_hits(int, void *ip, unsigne*/ static inline void profile_hit (int type,void *ip) { -/* -* Speedup for the common (no profiling enabled) case: -*/ -if (unlikely (prof_on == type)) -profile_hits (type, ip,1 ); +profile_hits (type, ip,1 ); }#ifdef CONFIG_PROC_FS
kernel/sched.c +2 -1
@@ -3458,7 +3458,8 @@ static inline void schedule_debug(structif (unlikely (in_atomic_preempt_off ()) &&unlikely (!prev->exit_state))__schedule_bug (prev); -profile_hit (SCHED_PROFILING ,__builtin_return_address (0 )); + immediate_if (&sched_profiling) +profile_hit (SCHED_PROFILING ,__builtin_return_address (0 ));schedstat_inc (this_rq (), sched_cnt); }
drivers/kvm/svm.c +1 -1
@@ -1570,7 +1570,7 @@ again:/* * Profile KVM exit RIPs: */ -if (unlikely (prof_on ==KVM_PROFILING )) + immediate_if (&kvm_profiling)profile_hit (KVM_PROFILING , (void *)(unsigned long )svm->vmcb->save.rip);
drivers/kvm/vmx.c +1 -1
@@ -2234,7 +2234,7 @@ again:/* * Profile KVM exit RIPs: */ -if (unlikely (prof_on ==KVM_PROFILING )) + immediate_if (&kvm_profiling)profile_hit (KVM_PROFILING , (void *)vmcs_readl (GUEST_RIP )); r =kvm_handle_exit (kvm_run, vcpu);
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Quoted 46 lines · On Thu, 6 Sep 2007 16:05:37 -0400 Mathieu Desnoyers wrote:
Scheduler Profiling - Use Immediate Values
Use immediate values with lower d-cache hit in optimized version as a condition for scheduler profiling call.
Depends on the Immediate values patches, applies to 2.6.23-rc4-mm1.
Signed-off-by Mathieu Desnoyers <[email protected]>--- drivers/kvm/svm.c | 2 +- drivers/kvm/vmx.c | 2 +- include/linux/profile.h | 10 ++++------ kernel/profile.c | 38 ++++++++++++++++++++++++++------------ kernel/sched.c | 3 ++- 5 files changed, 34 insertions(+), 21 deletions(-)Index:
linux-2.6-lttng/kernel/profile.c
===================================================================kernel/profile.c +8
-3@@ -42,9 +42,6 @@ static int (*timer_hook)(struct pt_regsstatic atomic_t *prof_buffer;static unsigned long prof_len, prof_shift; -int prof_on__read_mostly ; -EXPORT_SYMBOL_GPL (prof_on); -static cpumask_t prof_cpu_mask =CPU_MASK_ALL ;#ifdef CONFIG_SMP static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);@@ -52,6 +49,14 @@ static DEFINE_PER_CPU(int, cpu_profile_fstatic DEFINE_MUTEX (profile_flip_mutex);#endif /* CONFIG_SMP */ +/* Immediate values */ +immediate_char_t sleep_profiling__read_mostly , + sched_profiling__read_mostly , + kvm_profiling__read_mostly , + cpu_profiling__read_mostly ; +EXPORT_SYMBOL_GPL (kvm_profiling); +EXPORT_SYMBOL_GPL (cpu_profiling); +static int __init profile_setup (char * str) {static char __initdata schedstr[] ="schedule" ;
kernel/profile.c static int __init profile_setup(char * s · line 68
Quoted 5 lines
kernel/profile.c +1
-1@@ -60,7 +65,7 @@ static int __init profile_setup(char * sint par;if (!strncmp (str, sleepstr,strlen (sleepstr))) { - prof_on =SLEEP_PROFILING ; +immediate_set_early (&sleep_profiling,1 );
These are booleans, eh? so one could use , true);
etc.
kernel/profile.c __setup("profile=", profile_setup); · line 110
Quoted 12 lines
kernel/profile.c +4
-1if (str[strlen (sleepstr)] ==',' ) str +=strlen (sleepstr) +1 ;if (get_option (&str, &par))@@ -99,7 +104,10 @@ __setup("profile=", profile_setup);void __init profile_init (void ) { -if (!prof_on) +if (!_immediate_read (&sleep_profiling) && + !_immediate_read (&sched_profiling) && + !_immediate_read (&kvm_profiling) && + !_immediate_read (&cpu_profiling))
Looks like this (in multiple places) needs to use prof_on, where prof_on is set earlier as the logical 'or' of all (4 now, could be more) profiling flags.
Or below, sometimes you just check prof_buffer. Is that sufficient here also?
Quoted 35 lines
kernel/profile.c +6
-3return ;/* only text is profiled */ @@ -288,7 +296,7 @@ void profile_hits(int type, void *__pc,int i, j, cpu;struct profile_hit *hits; -if (prof_on != type || !prof_buffer) +if (!prof_buffer)return ; pc =min ((pc - (unsigned long )_stext) >> prof_shift, prof_len -1 ); i = primary = (pc & (NR_PROFILE_GRP -1 )) <<PROFILE_GRPSHIFT ;@@ -398,7 +406,7 @@ void profile_hits(int type, void *__pc, {unsigned long pc; -if (prof_on != type || !prof_buffer) +if (!prof_buffer)return ; pc = ((unsigned long )__pc - (unsigned long )_stext) >> prof_shift;atomic_add (nr_hits, &prof_buffer[min (pc, prof_len -1 )]);@@ -555,7 +563,10 @@ static int __init create_hash_tables(voi }return 0 ; out_cleanup: - prof_on =0 ; +immediate_set_early (&sleep_profiling,0 ); +immediate_set_early (&sched_profiling,0 ); +immediate_set_early (&kvm_profiling,0 ); +immediate_set_early (&cpu_profiling,0 );smp_mb ();on_each_cpu (profile_nop,NULL ,0 ,1 );for_each_online_cpu (cpu) {@@ -582,7 +593,10 @@ static int __init create_proc_profile(vo {
kernel/profile.c static int __init create_proc_profile(vo · line 602
Quoted 10 lines
kernel/profile.c +4
-1struct proc_dir_entry *entry; -if (!prof_on) +if (!_immediate_read (&sleep_profiling) && + !_immediate_read (&sched_profiling) && + !_immediate_read (&kvm_profiling) && + !_immediate_read (&cpu_profiling))return 0 ;if (create_hash_tables ())return -1 ;
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Hi Randy,
Quoted 63 lines · * Randy Dunlap ([email protected]) wrote:
Quoted 46 lines · On Thu, 6 Sep 2007 16:05:37 -0400 Mathieu Desnoyers wrote:
Scheduler Profiling - Use Immediate Values
Use immediate values with lower d-cache hit in optimized version as a condition for scheduler profiling call.
Depends on the Immediate values patches, applies to 2.6.23-rc4-mm1.
Signed-off-by Mathieu Desnoyers <[email protected]>--- drivers/kvm/svm.c | 2 +- drivers/kvm/vmx.c | 2 +- include/linux/profile.h | 10 ++++------ kernel/profile.c | 38 ++++++++++++++++++++++++++------------ kernel/sched.c | 3 ++- 5 files changed, 34 insertions(+), 21 deletions(-)Index:
linux-2.6-lttng/kernel/profile.c
===================================================================kernel/profile.c +8
-3@@ -42,9 +42,6 @@ static int (*timer_hook)(struct pt_regsstatic atomic_t *prof_buffer;static unsigned long prof_len, prof_shift; -int prof_on__read_mostly ; -EXPORT_SYMBOL_GPL (prof_on); -static cpumask_t prof_cpu_mask =CPU_MASK_ALL ;#ifdef CONFIG_SMP static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);@@ -52,6 +49,14 @@ static DEFINE_PER_CPU(int, cpu_profile_fstatic DEFINE_MUTEX (profile_flip_mutex);#endif /* CONFIG_SMP */ +/* Immediate values */ +immediate_char_t sleep_profiling__read_mostly , + sched_profiling__read_mostly , + kvm_profiling__read_mostly , + cpu_profiling__read_mostly ; +EXPORT_SYMBOL_GPL (kvm_profiling); +EXPORT_SYMBOL_GPL (cpu_profiling); +static int __init profile_setup (char * str) {static char __initdata schedstr[] ="schedule" ;kernel/profile.c static int __init profile_setup(char * s · line 68
Quoted 5 lines
kernel/profile.c +1
-1@@ -60,7 +65,7 @@ static int __init profile_setup(char * sint par;if (!strncmp (str, sleepstr,strlen (sleepstr))) { - prof_on =SLEEP_PROFILING ; +immediate_set_early (&sleep_profiling,1 );These are booleans, eh? so one could use , true);
etc.
Quoted 5 lines
kernel/profile.c +0
-0if (str[strlen (sleepstr)] ==',' ) str +=strlen (sleepstr) +1 ;if (get_option (&str, &par))@@ -99,7 +104,10 @@ __setup("profile=", profile_setup);
Quoted 11 lines
kernel/profile.c __setup("profile=", profile_setup); · line 110
Quoted 7 lines
kernel/profile.c +4
-1void __init profile_init (void ) { -if (!prof_on) +if (!_immediate_read (&sleep_profiling) && + !_immediate_read (&sched_profiling) && + !_immediate_read (&kvm_profiling) && + !_immediate_read (&cpu_profiling))Looks like this (in multiple places) needs to use
prof_on, whereprof_onis set earlier as the logical 'or' of all (4 now, could be more) profiling flags.
I first did this patch when the immediate values only supported booleans. I just redid it encoding the original prof_on values in a signle immediate_char_t variable. It makes the change must less intrusive.
Since there seem to be only one type of profiling possible at a given time, there is no need for a bitfield : just doing the same as prof_on currently does seems ok.
Quoted 3 lines
Or below, sometimes you just check
prof_buffer. Is that sufficient here also?
Yes, before we already do the check early in profile_hit (inline function checking the same condition). In this patch, I moved the check out of profile_hit, but since I now re-use prof_on with values, I can put it back in profile_hit().
Quoted 50 lines
Quoted 35 lines
kernel/profile.c +6
-3return ;/* only text is profiled */ @@ -288,7 +296,7 @@ void profile_hits(int type, void *__pc,int i, j, cpu;struct profile_hit *hits; -if (prof_on != type || !prof_buffer) +if (!prof_buffer)return ; pc =min ((pc - (unsigned long )_stext) >> prof_shift, prof_len -1 ); i = primary = (pc & (NR_PROFILE_GRP -1 )) <<PROFILE_GRPSHIFT ;@@ -398,7 +406,7 @@ void profile_hits(int type, void *__pc, {unsigned long pc; -if (prof_on != type || !prof_buffer) +if (!prof_buffer)return ; pc = ((unsigned long )__pc - (unsigned long )_stext) >> prof_shift;atomic_add (nr_hits, &prof_buffer[min (pc, prof_len -1 )]);@@ -555,7 +563,10 @@ static int __init create_hash_tables(voi }return 0 ; out_cleanup: - prof_on =0 ; +immediate_set_early (&sleep_profiling,0 ); +immediate_set_early (&sched_profiling,0 ); +immediate_set_early (&kvm_profiling,0 ); +immediate_set_early (&cpu_profiling,0 );smp_mb ();on_each_cpu (profile_nop,NULL ,0 ,1 );for_each_online_cpu (cpu) {@@ -582,7 +593,10 @@ static int __init create_proc_profile(vo {kernel/profile.c static int __init create_proc_profile(vo · line 602
Quoted 10 lines
kernel/profile.c +4
-1struct proc_dir_entry *entry; -if (!prof_on) +if (!_immediate_read (&sleep_profiling) && + !_immediate_read (&sched_profiling) && + !_immediate_read (&kvm_profiling) && + !_immediate_read (&cpu_profiling))return 0 ;if (create_hash_tables ())return -1 ;---
~Randy
*** Remember to useDocumentation/SubmitChecklistwhen testing your code ***
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
kernel/sched.c static inline void schedule_debug(struct · line 3461
Quoted 3 lines · Mathieu Desnoyers
kernel/sched.c +1
-1-profile_hit (SCHED_PROFILING ,__builtin_return_address (0 )); +immediate_if (&sched_profiling)
I must say I really dislike immediate_if(). You complained earlier that something breaks coloring, but adding such macros will definitely break a lot of editors (especially if you use it without {} like here)
It would be much nicer and readable to just use if (unlikely(immediate_read(&x)) or if you prefer to hide the unlikely if (immediate_bool_test(&x)) with an implicit unlikely().
-Andi
Quoted 9 lines · * Andi Kleen ([email protected]) wrote:
kernel/sched.c static inline void schedule_debug(struct · line 3461
Quoted 3 lines · Mathieu Desnoyers
kernel/sched.c +1
-1-profile_hit (SCHED_PROFILING ,__builtin_return_address (0 )); +immediate_if (&sched_profiling)I must say I really dislike
immediate_if(). You complained earlier that something breaks coloring, but adding such macros will definitely break a lot of editors (especially if you use it without {} like here)
Quoted 5 lines
It would be much nicer and readable to just use if (unlikely(immediate_read(&x)) or if you prefer to hide the unlikely if (
immediate_bool_test(&x)) with an implicitunlikely().-Andi
Please refer to :
http://lkml.org/lkml/2007/7/3/301
The idea is not to hide the unlikely, but to leave the opportunity to make this primitive evolve in something that won't depend on a load immediate and only require patching of a jump, given the appropriate gcc support (yet to come).
Mathieu
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Quoted 4 lines
The idea is not to hide the unlikely, but to leave the opportunity to make this primitive evolve in something that won't depend on a load immediate and only require patching of a jump, given the appropriate gcc support (yet to come).
If that ever happens the code can be still changed. But i don't think it's a good idea to uglify the code for something that if it ever exists will be a long time away.
Besides if gcc supports it I assume the gcc support could also be written in a way that makes it possible to hide it inside a standard if ()
-Andi