public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Levent Serinol <lserinol@gmail.com>
To: William Lee Irwin III <wli@holomorphy.com>
Cc: Andrew Morton <akpm@osdl.org>,
	linux-kernel@vger.kernel.org, riel@redhat.com
Subject: Re: [PATCH] enable/disable profiling via proc/sysctl
Date: Mon, 27 Jun 2005 18:40:27 +0300	[thread overview]
Message-ID: <2c1942a705062708402d07657e@mail.gmail.com> (raw)
In-Reply-To: <20050627125649.GJ3334@holomorphy.com>

[-- Attachment #1: Type: text/plain, Size: 2565 bytes --]

Hi William,

 You're right. As you suggest I reverted memory barrier part. Also,
added memory barriers while allocating and freeing memory.

Can you confirm that if it's okay now or missed anything else ?

PS. I couldn't figure out how to reverse function of hotcpu_notifier.
That's why I used  register_cpu_notifier and #ifdefs.



On 6/27/05, William Lee Irwin III <wli@holomorphy.com> wrote:
> On Mon, Jun 27, 2005 at 03:13:13PM +0300, Levent Serinol wrote:
> > +#ifdef CONFIG_SMP
> > +int remove_hash_tables(void)
> > +{
> > +     int cpu;
> > +
> > +
> > +     for_each_online_cpu(cpu) {
> > +             struct page *page;
> > +
> > +             if (per_cpu(cpu_profile_hits, cpu)[0]) {
> > +                     page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]);
> > +                     per_cpu(cpu_profile_hits, cpu)[0] = NULL;
> > +                     __free_page(page);
> > +             }
> > +             if (per_cpu(cpu_profile_hits, cpu)[1]) {
> > +                     page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[1]);
> > +                     per_cpu(cpu_profile_hits, cpu)[1] = NULL;
> > +                     __free_page(page);
> > +             }
> > +     }
> > +     return -1;
> 
> Big problem. Timer interrupts can be firing while this is in progress.
> The reason for profile_nop() is so that the code I have running during
> timer interrupts (protected by local_irq_save()) runs to completion,
> where it will afterward discover the flags or variables set to updated
> states. You'll probably have to add more (e.g. memory barriers) since
> you can tolerate less once you're dynamically allocating and freeing etc.
> 
> 
> On Mon, Jun 27, 2005 at 03:13:13PM +0300, Levent Serinol wrote:
> > @@ -560,7 +668,11 @@ static int __init create_proc_profile(vo
> >               return 0;
> >       entry->proc_fops = &proc_profile_operations;
> >       entry->size = (1+prof_len) * sizeof(atomic_t);
> > -     hotcpu_notifier(profile_cpu_callback, 0);
> > +#ifdef CONFIG_HOTPLUG_CPU
> > +     register_cpu_notifier(&profile_cpu_notifier);
> > +#endif
> > +     profile_params[0] = prof_on;
> > +     profile_params[1] = prof_shift;
> >       return 0;
> >  }
> >  module_init(create_proc_profile);
> 
> hotcpu_notifier() is there to avoid the #ifdef; you shouldn't need to
> rearrange that.
> 
> Anyway, just keep fixing it up. There should be a few more after this.
> 
> 
> -- wli
> 


-- 

Stay out of the road, if you want to grow old. 
~ Pink Floyd ~.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: profile.patch --]
[-- Type: text/x-patch; name="profile.patch", Size: 7169 bytes --]

diff -uprN -X dontdiff linux-2.6.12-rc6.orig/include/linux/profile.h linux-2.6.12-rc6/include/linux/profile.h
--- linux-2.6.12-rc6.orig/include/linux/profile.h	2005-03-02 09:38:08.000000000 +0200
+++ linux-2.6.12-rc6/include/linux/profile.h	2005-06-27 10:19:43.000000000 +0300
@@ -6,14 +6,21 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/sysctl.h>
 #include <linux/cpumask.h>
 #include <asm/errno.h>
 
 #define CPU_PROFILING	1
 #define SCHED_PROFILING	2
 
+struct ctl_table;
+struct file;
 struct proc_dir_entry;
 struct pt_regs;
+extern int profile_params[];
+int profile_sysctl_handler(ctl_table *table, int write,
+               struct file *file, void __user *buffer, size_t
+*length, loff_t *ppos);
 
 /* init basic kernel profiler */
 void __init profile_init(void);
diff -uprN -X dontdiff linux-2.6.12-rc6.orig/include/linux/sysctl.h linux-2.6.12-rc6/include/linux/sysctl.h
--- linux-2.6.12-rc6.orig/include/linux/sysctl.h	2005-06-27 18:25:13.000000000 +0300
+++ linux-2.6.12-rc6/include/linux/sysctl.h	2005-06-27 10:15:54.000000000 +0300
@@ -136,6 +136,7 @@ enum
 	KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
 	KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
 	KERN_RANDOMIZE=68, /* int: randomize virtual address space */
+	KERN_PROFILE=69, /* int: profile on/off */
 };
 
 
diff -uprN -X dontdiff linux-2.6.12-rc6.orig/kernel/profile.c linux-2.6.12-rc6/kernel/profile.c
--- linux-2.6.12-rc6.orig/kernel/profile.c	2005-06-27 18:25:13.000000000 +0300
+++ linux-2.6.12-rc6/kernel/profile.c	2005-06-27 18:23:47.000000000 +0300
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/cpumask.h>
 #include <linux/cpu.h>
-#include <linux/profile.h>
 #include <linux/highmem.h>
 #include <asm/sections.h>
 #include <asm/semaphore.h>
@@ -37,9 +36,12 @@ struct profile_hit {
 /* Oprofile timer tick hook */
 int (*timer_hook)(struct pt_regs *);
 
+struct semaphore prof_sem;
+int profile_params[2] = {0, 0};
 static atomic_t *prof_buffer;
 static unsigned long prof_len, prof_shift;
 static int prof_on;
+static int prof_booton;
 static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -74,12 +76,14 @@ __setup("profile=", profile_setup);
 
 void __init profile_init(void)
 {
+	init_MUTEX(&prof_sem);
 	if (!prof_on) 
 		return;
  
 	/* only text is profiled */
 	prof_len = (_etext - _stext) >> prof_shift;
 	prof_buffer = alloc_bootmem(prof_len*sizeof(atomic_t));
+	prof_booton = 1;
 }
 
 /* Profile event notifications */
@@ -367,6 +371,12 @@ static int __devinit profile_cpu_callbac
 	}
 	return NOTIFY_OK;
 }
+static struct notifier_block profile_cpu_notifier =
+{
+         .notifier_call = profile_cpu_callback,
+         .priority = 0,
+};
+
 #endif /* CONFIG_HOTPLUG_CPU */
 #else /* !CONFIG_SMP */
 #define profile_flip_buffers()		do { } while (0)
@@ -500,11 +510,11 @@ static struct file_operations proc_profi
 };
 
 #ifdef CONFIG_SMP
-static void __init profile_nop(void *unused)
+static void profile_nop(void *unused)
 {
 }
 
-static int __init create_hash_tables(void)
+int create_hash_tables(void)
 {
 	int cpu;
 
@@ -548,6 +558,113 @@ out_cleanup:
 #define create_hash_tables()			({ 0; })
 #endif
 
+#ifdef CONFIG_SMP
+int remove_hash_tables(void)
+{
+	int cpu;
+
+
+	prof_on = 0;
+	smp_mb();
+	on_each_cpu(profile_nop, NULL, 0, 1);
+
+	for_each_online_cpu(cpu) {
+		struct page *page;
+
+		if (per_cpu(cpu_profile_hits, cpu)[0]) {
+			page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]);
+			per_cpu(cpu_profile_hits, cpu)[0] = NULL;
+			__free_page(page);
+		}
+		if (per_cpu(cpu_profile_hits, cpu)[1]) {
+			page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[1]);
+			per_cpu(cpu_profile_hits, cpu)[1] = NULL;
+			__free_page(page);
+		}
+	}
+	return -1;
+}
+#else
+#define remove_hash_tables()			({ 0; })
+#endif
+
+int profile_sysctl_handler(ctl_table *table, int write, struct file *file, 
+		void __user *buffer, size_t *length, loff_t *ppos)
+{
+	int err;
+	struct proc_dir_entry *entry;
+
+
+	down(&prof_sem);
+
+	if (prof_booton && write) 
+		goto out;
+
+	err=proc_dointvec(table, write, file, buffer, length, ppos);
+	if (err < 0 || !write)
+		goto out;
+
+	prof_shift = profile_params[1];
+
+	if (!profile_params[0]) {
+		if (prof_on) {
+			prof_on = 0;
+			remove_proc_entry("profile",NULL);
+#ifdef CONFIG_HOTPLUG_CPU
+			unregister_cpu_notifier(&profile_cpu_notifier);
+#endif
+			remove_hash_tables();
+			smp_mb();
+			on_each_cpu(profile_nop, NULL, 0, 1);
+			vfree(prof_buffer);
+			printk(KERN_INFO "kernel profiling disabled\n");
+		}
+	}
+
+	if ((profile_params[0]==SCHED_PROFILING) || (profile_params[0]==CPU_PROFILING)) {
+		if (prof_on)
+			goto out;
+        	prof_len = (_etext - _stext) >> prof_shift;
+		smp_mb();
+        	prof_buffer = vmalloc(prof_len*sizeof(atomic_t));
+		if (!prof_buffer)
+			goto out;
+		if (create_hash_tables()) {
+			vfree(prof_buffer);
+			goto out;
+		}
+		prof_on = profile_params[0];
+		if (!(entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL))) {
+			remove_hash_tables();
+			smp_mb();
+			on_each_cpu(profile_nop, NULL, 0, 1);
+			vfree(prof_buffer);
+			goto out;
+		}
+		entry->proc_fops = &proc_profile_operations;
+		entry->size = (1+prof_len) * sizeof(atomic_t);
+#ifdef CONFIG_HOTPLUG_CPU
+		register_cpu_notifier(&profile_cpu_notifier);
+#endif
+		profile_discard_flip_buffers();
+        	memset(prof_buffer, 0, prof_len * sizeof(atomic_t));
+			switch(prof_on) {
+			case SCHED_PROFILING:
+				printk(KERN_INFO "kernel schedule profiling enabled (shift: %ld)\n",
+						prof_shift);
+				break;
+			case CPU_PROFILING:
+				printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
+						prof_shift);
+				break;
+			} 
+	}
+
+out:
+	up(&prof_sem);
+	return 0;
+}
+
 static int __init create_proc_profile(void)
 {
 	struct proc_dir_entry *entry;
@@ -560,7 +677,11 @@ static int __init create_proc_profile(vo
 		return 0;
 	entry->proc_fops = &proc_profile_operations;
 	entry->size = (1+prof_len) * sizeof(atomic_t);
-	hotcpu_notifier(profile_cpu_callback, 0);
+#ifdef CONFIG_HOTPLUG_CPU
+	register_cpu_notifier(&profile_cpu_notifier);
+#endif
+	profile_params[0] = prof_on;
+	profile_params[1] = prof_shift;
 	return 0;
 }
 module_init(create_proc_profile);
diff -uprN -X dontdiff linux-2.6.12-rc6.orig/kernel/sysctl.c linux-2.6.12-rc6/kernel/sysctl.c
--- linux-2.6.12-rc6.orig/kernel/sysctl.c	2005-06-27 18:25:13.000000000 +0300
+++ linux-2.6.12-rc6/kernel/sysctl.c	2005-06-27 10:19:07.000000000 +0300
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/profile.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
@@ -642,7 +643,15 @@ static ctl_table kern_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
-
+	{
+		.ctl_name       = KERN_PROFILE,
+		.procname       = "profile",
+		.data           = &profile_params,
+		.maxlen         = 2*sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &profile_sysctl_handler,
+		.strategy       = &sysctl_intvec,
+	},
 	{ .ctl_name = 0 }
 };
 

      reply	other threads:[~2005-06-27 15:48 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-27  6:41 [PATCH] enable/disable profiling via proc/sysctl Levent Serinol
2005-06-27  7:01 ` Andrew Morton
2005-06-27 12:13   ` Levent Serinol
2005-06-27 12:56     ` William Lee Irwin III
2005-06-27 15:40       ` Levent Serinol [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2c1942a705062708402d07657e@mail.gmail.com \
    --to=lserinol@gmail.com \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=riel@redhat.com \
    --cc=wli@holomorphy.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox