]> git.hungrycats.org Git - linux/commitdiff
[PATCH] schedule profileing
authorArjan van de Ven <arjanv@redhat.com>
Fri, 27 Aug 2004 03:30:55 +0000 (20:30 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 27 Aug 2004 03:30:55 +0000 (20:30 -0700)
From: William Lee Irwin III <wli@holomorphy.com>

The patch (from Ingo) below is quite interesting, it allows the use of
readprofile not for statistical tine sampling, but for seeing where calls to
schedule() come from, so it can give some insight to the "where do my context
switches come from" question.

Boot with `profile=schedul2' to activate this feature.

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Documentation/kernel-parameters.txt
include/asm-i386/hw_irq.h
kernel/profile.c
kernel/sched.c

index c0d8bee481461b4bdf06d910676728f114889a1c..ae0eb1a3d4e4a30f06a677dd6c3d8688e0a61f5c 100644 (file)
@@ -914,7 +914,10 @@ running once the system is up.
                        Ranges are in pairs (memory base and size).
 
        profile=        [KNL] Enable kernel profiling via /proc/profile
-                       (param: profile step/bucket size as a power of 2)
+                       { schedule | <number> }
+                       (param: schedule - profile schedule points}
+                       (param: profile step/bucket size as a power of 2 for
+                               statistical time based profiling)
 
        prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
                        before loading.
index 25b7baadbb5713f302202a61f474a84cae5c5d84..0f2eabc304ef96d5a43e286189b5fa7341f484e4 100644 (file)
@@ -68,27 +68,13 @@ extern atomic_t irq_mis_count;
 
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void x86_do_profile(struct pt_regs * regs)
+static inline void __do_profile(unsigned long eip)
 {
-       unsigned long eip;
        extern unsigned long prof_cpu_mask;
  
-       profile_hook(regs);
- 
-       if (user_mode(regs))
-               return;
- 
        if (!prof_buffer)
                return;
 
-       eip = regs->eip;
- 
        /*
         * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
         * (default is all CPUs.)
@@ -108,6 +94,24 @@ static inline void x86_do_profile(struct pt_regs * regs)
        atomic_inc((atomic_t *)&prof_buffer[eip]);
 }
  
+#define kern_profile(eip) __do_profile(eip)
+
+/*
+ * The profiling function is SMP safe. (nothing can mess
+ * around with "current", and the profiling counters are
+ * updated with atomic operations). This is especially
+ * useful with a profiling multiplier != 1
+ */
+static inline void x86_do_profile(struct pt_regs * regs)
+{
+       profile_hook(regs);
+
+       if (prof_on != 1 || user_mode(regs))
+               return;
+
+       __do_profile(regs->eip);
+}
+
 #if defined(CONFIG_X86_IO_APIC)
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
 {
index 5c02ac0fbbdad6e539622b79f425541cdb97ea33..bfd3d2cabb782566a5ee0b12b0da264be03d5ff8 100644 (file)
@@ -18,10 +18,18 @@ int prof_on;
 int __init profile_setup(char * str)
 {
        int par;
+
+       if (!strncmp(str, "schedule", 8)) {
+               prof_on = 2;
+               printk(KERN_INFO "kernel schedule profiling enabled\n");
+               if (str[7] == ',')
+                       str += 8;
+       }
        if (get_option(&str,&par)) {
                prof_shift = par;
                prof_on = 1;
-               printk(KERN_INFO "kernel profiling enabled\n");
+               printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
+                       prof_shift);
        }
        return 1;
 }
index 4b44d5219c36604374dc661fdb7f6acf6d7781da..bdf0f19947bae364dcacb8c98616f2fde3a39ce2 100644 (file)
@@ -3220,6 +3220,10 @@ static int setscheduler(pid_t pid, int policy, struct sched_param __user *param)
                                policy != SCHED_NORMAL)
                        goto out_unlock;
        }
+#ifdef kern_profile
+       if (unlikely(prof_on == 2))
+               __do_profile((unsigned long)__builtin_return_address(0));
+#endif
 
        /*
         * Valid priorities for SCHED_FIFO and SCHED_RR are