linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / kernel / profile.c
index ff62fa9..f89248e 100644 (file)
@@ -35,11 +35,11 @@ struct profile_hit {
 #define NR_PROFILE_GRP         (NR_PROFILE_HIT/PROFILE_GRPSZ)
 
 /* Oprofile timer tick hook */
-int (*timer_hook)(struct pt_regs *);
+int (*timer_hook)(struct pt_regs *) __read_mostly;
 
 static atomic_t *prof_buffer;
 static unsigned long prof_len, prof_shift;
-static int prof_on;
+static int prof_on __read_mostly;
 static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -49,15 +49,19 @@ static DECLARE_MUTEX(profile_flip_mutex);
 
 static int __init profile_setup(char * str)
 {
+       static char __initdata schedstr[] = "schedule";
        int par;
 
-       if (!strncmp(str, "schedule", 8)) {
+       if (!strncmp(str, schedstr, strlen(schedstr))) {
                prof_on = SCHED_PROFILING;
-               printk(KERN_INFO "kernel schedule profiling enabled\n");
-               if (str[7] == ',')
-                       str += 8;
-       }
-       if (get_option(&str,&par)) {
+               if (str[strlen(schedstr)] == ',')
+                       str += strlen(schedstr) + 1;
+               if (get_option(&str, &par))
+                       prof_shift = par;
+               printk(KERN_INFO
+                       "kernel schedule profiling enabled (shift: %ld)\n",
+                       prof_shift);
+       } else if (get_option(&str, &par)) {
                prof_shift = par;
                prof_on = CPU_PROFILING;
                printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
@@ -83,7 +87,7 @@ void __init profile_init(void)
 #ifdef CONFIG_PROFILING
  
 static DECLARE_RWSEM(profile_rwsem);
-static rwlock_t handoff_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(handoff_lock);
 static struct notifier_block * task_exit_notifier;
 static struct notifier_block * task_free_notifier;
 static struct notifier_block * munmap_notifier;
@@ -184,7 +188,7 @@ void unregister_timer_hook(int (*hook)(struct pt_regs *))
        WARN_ON(hook != timer_hook);
        timer_hook = NULL;
        /* make sure all CPUs see the NULL hook */
-       synchronize_kernel();
+       synchronize_sched();  /* Allow ongoing interrupts to complete. */
 }
 
 EXPORT_SYMBOL_GPL(register_timer_hook);
@@ -326,17 +330,15 @@ static int __devinit profile_cpu_callback(struct notifier_block *info,
                node = cpu_to_node(cpu);
                per_cpu(cpu_profile_flip, cpu) = 0;
                if (!per_cpu(cpu_profile_hits, cpu)[1]) {
-                       page = alloc_pages_node(node, GFP_KERNEL, 0);
+                       page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
                        if (!page)
                                return NOTIFY_BAD;
-                       clear_highpage(page);
                        per_cpu(cpu_profile_hits, cpu)[1] = page_address(page);
                }
                if (!per_cpu(cpu_profile_hits, cpu)[0]) {
-                       page = alloc_pages_node(node, GFP_KERNEL, 0);
+                       page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
                        if (!page)
                                goto out_free;
-                       clear_highpage(page);
                        per_cpu(cpu_profile_hits, cpu)[0] = page_address(page);
                }
                break;
@@ -510,23 +512,21 @@ static int __init create_hash_tables(void)
                int node = cpu_to_node(cpu);
                struct page *page;
 
-               page = alloc_pages_node(node, GFP_KERNEL, 0);
+               page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
                if (!page)
                        goto out_cleanup;
-               clear_highpage(page);
                per_cpu(cpu_profile_hits, cpu)[1]
                                = (struct profile_hit *)page_address(page);
-               page = alloc_pages_node(node, GFP_KERNEL, 0);
+               page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
                if (!page)
                        goto out_cleanup;
-               clear_highpage(page);
                per_cpu(cpu_profile_hits, cpu)[0]
                                = (struct profile_hit *)page_address(page);
        }
        return 0;
 out_cleanup:
        prof_on = 0;
-       mb();
+       smp_mb();
        on_each_cpu(profile_nop, NULL, 0, 1);
        for_each_online_cpu(cpu) {
                struct page *page;