public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Levent Serinol <lserinol@gmail.com>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Andrew Morton <akpm@osdl.org>, Rik van Riel <riel@redhat.com>,
	William Lee Irwin III <wli@holomorphy.com>
Subject: [PATCH] enable/disable profiling via proc/sysctl
Date: Mon, 27 Jun 2005 09:41:28 +0300	[thread overview]
Message-ID: <2c1942a705062623411b7e88c3@mail.gmail.com> (raw)

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

This patch enables controlling kernel profiling through proc/sysctl inferface.

With this patch profiling will be available without rebooting the
machine (especially for
production servers) with some drawbacks of vmalloc(tlb). So, bootime
algorithm part is left unchanged for anyone who wishes to use
profiling as usual without tlb drawback by rebooting the machine.


PS. This patch is against  2.6.12-rc6

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

--- include/linux/sysctl.h.org	2005-06-13 16:05:17.000000000 +0300
+++ include/linux/sysctl.h	2005-06-25 15:05:06.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 */
 };
 
 
--- include/linux/profile.h.org	2005-03-02 09:38:08.000000000 +0200
+++ include/linux/profile.h	2005-06-26 01:56:46.000000000 +0300
@@ -6,14 +6,20 @@
 #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;
+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);
--- kernel/profile.c.org	2005-06-13 16:05:23.000000000 +0300
+++ kernel/profile.c	2005-06-26 21:34:28.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,11 @@ struct profile_hit {
 /* Oprofile timer tick hook */
 int (*timer_hook)(struct pt_regs *);
 
+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_on = 0;
+static int prof_booton = 0;
 static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -80,6 +81,7 @@ void __init profile_init(void)
 	/* 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 +369,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)
@@ -548,6 +556,96 @@ out_cleanup:
 #define create_hash_tables()			({ 0; })
 #endif
 
+#ifdef CONFIG_SMP
+static int remove_hash_tables(void)
+{
+	int cpu;
+
+	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;
+
+	if (prof_booton && write) return 0;
+	err=proc_dointvec(table, write, file, buffer, length, ppos);
+	if ((err >= 0) && write) {
+	prof_shift = profile_params[1];
+	switch(profile_params[0])
+	{
+	case 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();
+			vfree(prof_buffer);
+			printk(KERN_INFO "kernel profiling disabled\n");
+		     } 
+		break;
+	case SCHED_PROFILING || CPU_PROFILING:
+		if (prof_on) return -1;
+        	prof_len = (_etext - _stext) >> prof_shift;
+        	prof_buffer = vmalloc(prof_len*sizeof(atomic_t));
+		if (!prof_buffer) return(-ENOMEM);
+		if (create_hash_tables()) {
+			vfree(prof_buffer);
+			return -1;
+			}
+		prof_on = profile_params[0];
+		if (!(entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL))) {
+			remove_hash_tables();
+			vfree(prof_buffer);
+			return 0;
+			}
+		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;
+				} 
+			break;
+			}
+		}
+	return 0;
+}
+
 static int __init create_proc_profile(void)
 {
 	struct proc_dir_entry *entry;
@@ -560,7 +658,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);
--- kernel/sysctl.c.org	2005-06-13 16:05:23.000000000 +0300
+++ kernel/sysctl.c	2005-06-26 02:06:23.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>
@@ -65,6 +66,7 @@ extern int min_free_kbytes;
 extern int printk_ratelimit_jiffies;
 extern int printk_ratelimit_burst;
 extern int pid_max_min, pid_max_max;
+extern int profile_params[];
 
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
 int unknown_nmi_panic;
@@ -642,7 +644,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  6:49 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-27  6:41 Levent Serinol [this message]
2005-06-27  7:01 ` [PATCH] enable/disable profiling via proc/sysctl 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

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=2c1942a705062623411b7e88c3@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