Re: [profile] amortize atomic hit count increments

William Lee Irwin III
2004-09-14T20:08:08Z

On Tue, Sep 14, 2004 at 09:16:48AM -0700, Jesse Barnes wrote:
>> It looks like the 512p we have here is pretty heavily reserved this
>> week, so I'm not sure if I'll be able to test this (someone else
>> might, John?). I think the balance we're looking for is between
>> simplicity and non-brokenness. Builtin profiling is *supposed* to be
>> simple and dumb, and were it not for the readprofile times, I'd say
>> per-cpu would be the way to go just because it retains the simplicity
>> of the current approach while allowing it to work on large machines
>> (as well as limiting the performance impact of builtin profiling in
>> general). wli's approach seems like a reasonable tradeoff though,
>> assuming what you suggest doesn't work.

On Tue, Sep 14, 2004 at 12:00:30PM -0700, William Lee Irwin III wrote:
> Goddamn fscking short-format VHPT crap. Rusty, how the hell do I
> hotplug-ize this?

Okay, here's an attempt to hotplug-ize it. I have no clue whether this
actually works, compiles, or follows whatever rules there are about
dynamically allocated data referenced by per_cpu areas.

-- wli

Index: mm5-2.6.9-rc1/kernel/profile.c
===================================================================
--- mm5-2.6.9-rc1.orig/kernel/profile.c 2004-09-14 10:20:43.000000000 -0700
+++ mm5-2.6.9-rc1/kernel/profile.c 2004-09-14 12:52:16.064352624 -0700
@@ -20,6 +20,7 @@
#include <linux/notifier.h>
#include <linux/mm.h>
#include <linux/cpumask.h>
+#include <linux/cpu.h>
#include <linux/profile.h>
#include <asm/sections.h>
#include <asm/semaphore.h>
@@ -297,6 +298,44 @@
local_irq_restore(flags);
put_cpu();
}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __devinit profile_cpu_callback(struct notifier_block *info,
+ unsigned long action, void *__cpu)
+{
+ int cpu = (unsigned long)__cpu;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ per_cpu(cpu_profile_flip, cpu) = 0;
+ if (!per_cpu(cpu_profile_hits, cpu)[1])
+ per_cpu(cpu_profile_hits, cpu)[1]
+ = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!per_cpu(cpu_profile_hits, cpu)[1])
+ return NOTIFY_BAD;
+ if (!per_cpu(cpu_profile_hits, cpu)[0])
+ per_cpu(cpu_profile_hits, cpu)[0]
+ = (void *)get_zeroed_page(GFP_KERNEL);
+ if (per_cpu(cpu_profile_hits, cpu)[0])
+ break;
+ free_page((unsigned long)per_cpu(cpu_profile_hits, cpu)[1]);
+ return NOTIFY_BAD;
+ break;
+ case CPU_ONLINE:
+ cpu_set(cpu, prof_cpu_mask);
+ break;
+ case CPU_UP_CANCELED:
+ case CPU_DEAD:
+ cpu_clear(cpu, prof_cpu_mask);
+ free_page((unsigned long)per_cpu(cpu_profile_hits, cpu)[0]);
+ per_cpu(cpu_profile_hits, cpu)[0] = NULL;
+ free_page((unsigned long)per_cpu(cpu_profile_hits, cpu)[1]);
+ per_cpu(cpu_profile_hits, cpu)[1] = NULL;
+ break;
+ }
+ return NOTIFY_OK;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
#else /* !CONFIG_SMP */
#define profile_flip_buffers() do { } while (0)