| From: |
| "Villacis, Juan" <juan.villacis@intel.com> |
| To: |
| <linux-kernel@vger.kernel.org> |
| Subject: |
| [PATCH] additional kernel event notifications |
| Date: |
| Sun, 3 Aug 2003 00:59:38 -0700 |
Hi,
We request that the following patch for additional kernel event notifications
be included in the upcoming 2.6.0 kernel.
The current profiling hooks provide notifications at the end of a task's
lifetime (i.e., task exit, mmap exit, and exec unmap). We would like to have
additional notifications on the start of a task (i.e., fork, execve, kernel
image loads, and user image loads).
We believe that profiling tools such as Oprofile, Perfmon, and VTune would
benefit from the additional hooks by improving the accuracy and completeness
of the performance data, especially when working in environments that can
dynamically create and destroy executable code (such as Java). Furthermore,
these hooks could be used to measure different types of performance data
(e.g., "forks per second") which are currently not available any other way.
Our patch follows the conventions used by the current profiling hooks, and is
relatively small.
We would appreciate comments/feedback on our proposal.
Regards,
Juan Villacis
Intel Corporation
Santa Clara, CA 95052
diff -urN linux-2.6.0-test2/arch/i386/oprofile/Kconfig
linux-2.6.0-test2-intel-vtune/arch/i386/oprofile/Kconfig
--- linux-2.6.0-test2/arch/i386/oprofile/Kconfig Sun Jul 27 10:02:49 2003
+++ linux-2.6.0-test2-intel-vtune/arch/i386/oprofile/Kconfig Sat Aug 2
20:38:37 2003
@@ -1,16 +1,16 @@
menu "Profiling support"
- depends on EXPERIMENTAL
config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
+ bool "Profiling support"
+ default y
help
Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
+ by profilers such as OProfile and VTune.
config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
+ tristate "OProfile system profiling"
depends on PROFILING
help
OProfile is a profiling system capable of profiling the
diff -urN linux-2.6.0-test2/Makefile linux-2.6.0-test2-intel-vtune/Makefile
--- linux-2.6.0-test2/Makefile Sun Jul 27 10:04:49 2003
+++ linux-2.6.0-test2-intel-vtune/Makefile Sat Aug 2 20:31:15 2003
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 0
-EXTRAVERSION = -test2
+EXTRAVERSION = -test2-intel-vtune
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
diff -urN linux-2.6.0-test2/MAINTAINERS
linux-2.6.0-test2-intel-vtune/MAINTAINERS
--- linux-2.6.0-test2/MAINTAINERS Sun Jul 27 10:03:51 2003
+++ linux-2.6.0-test2-intel-vtune/MAINTAINERS Sun Aug 3 02:07:37 2003
@@ -2151,6 +2151,13 @@
M: kraxel@bytesex.org
S: Maintained
+VTUNE
+P: Juan Villacis
+M: juan.del.villacis@intel.com
+W: http://www.intel.com/software/products/opensource/vdk/
+W: http://www.intel.com/software/products/vtune/
+S: Maintained
+
WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO
HDLC)
P: Nenad Corbic
M: ncorbic@sangoma.com
diff -urN linux-2.6.0-test2/include/linux/profile.h
linux-2.6.0-test2-intel-vtune/include/linux/profile.h
--- linux-2.6.0-test2/include/linux/profile.h Sun Jul 27 10:01:51 2003
+++ linux-2.6.0-test2-intel-vtune/include/linux/profile.h Sat Aug 2 20:02:45
2003
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/errno.h>
/* parse command line */
@@ -23,7 +24,11 @@
enum profile_type {
EXIT_TASK,
EXIT_MMAP,
- EXEC_UNMAP
+ EXEC_UNMAP,
+ DO_FORK,
+ DO_EXECVE,
+ LOAD_KERNEL_IMAGE,
+ LOAD_USER_IMAGE
};
#ifdef CONFIG_PROFILING
@@ -41,6 +46,20 @@
/* exit of all vmas for a task */
void profile_exit_mmap(struct mm_struct * mm);
+/* handler for DO_FORK event */
+void profile_do_fork(struct task_struct * task);
+
+/* handler for DO_EXECVE event */
+void profile_do_execve(struct task_struct * task);
+
+/* handler for LOAD_KERNEL_IMAGE event */
+void profile_load_kernel_image(struct module * mod, unsigned int
sechdr_index,
+ unsigned long addr, unsigned long size);
+
+/* handler for LOAD_USER_IMAGE */
+void profile_load_user_image(struct task_struct * task,
+ struct vm_area_struct * vma);
+
int profile_event_register(enum profile_type, struct notifier_block * n);
int profile_event_unregister(enum profile_type, struct notifier_block * n);
@@ -66,6 +85,10 @@
#define profile_exit_task(a) do { } while (0)
#define profile_exec_unmap(a) do { } while (0)
#define profile_exit_mmap(a) do { } while (0)
+#define profile_do_fork(a) do { } while (0)
+#define profile_do_execve(a) do { } while (0)
+#define profile_load_kernel_image(a) do { } while (0)
+#define profile_load_user_image(a) do { } while (0)
static inline int register_profile_notifier(struct notifier_block * nb)
{
diff -urN linux-2.6.0-test2/kernel/profile.c
linux-2.6.0-test2-intel-vtune/kernel/profile.c
--- linux-2.6.0-test2/kernel/profile.c Sun Jul 27 10:09:41 2003
+++ linux-2.6.0-test2-intel-vtune/kernel/profile.c Sat Aug 2 20:28:11 2003
@@ -50,6 +50,10 @@
static struct notifier_block * exit_task_notifier;
static struct notifier_block * exit_mmap_notifier;
static struct notifier_block * exec_unmap_notifier;
+static struct notifier_block * do_fork_notifier;
+static struct notifier_block * do_execve_notifier;
+static struct notifier_block * load_kernel_image_notifier;
+static struct notifier_block * load_user_image_notifier;
void profile_exit_task(struct task_struct * task)
{
@@ -72,6 +76,37 @@
up_read(&profile_rwsem);
}
+void profile_do_fork(struct task_struct * task)
+{
+ down_read(&profile_rwsem);
+ notifier_call_chain(&do_fork_notifier, 0, task);
+ up_read(&profile_rwsem);
+}
+
+void profile_do_execve(struct task_struct * task)
+{
+ down_read(&profile_rwsem);
+ notifier_call_chain(&do_execve_notifier, 0, task);
+ up_read(&profile_rwsem);
+}
+
+void profile_load_kernel_image(struct module * mod, unsigned int
sechdr_index,
+ unsigned long addr, unsigned long size)
+{
+ down_read(&profile_rwsem);
+ notifier_call_chain(&load_kernel_image_notifier, sechdr_index, mod);
+ up_read(&profile_rwsem);
+}
+
+void profile_load_user_image(struct task_struct * task,
+ struct vm_area_struct * vma)
+{
+ down_read(&profile_rwsem);
+ notifier_call_chain(&load_user_image_notifier,(unsigned long) task,
+ vma);
+ up_read(&profile_rwsem);
+}
+
int profile_event_register(enum profile_type type, struct notifier_block * n)
{
int err = -EINVAL;
@@ -88,6 +123,18 @@
case EXEC_UNMAP:
err = notifier_chain_register(&exec_unmap_notifier, n);
break;
+ case DO_FORK:
+ err = notifier_chain_register(&do_fork_notifier, n);
+ break;
+ case DO_EXECVE:
+ err = notifier_chain_register(&do_execve_notifier, n);
+ break;
+ case LOAD_KERNEL_IMAGE:
+ err = notifier_chain_register(&load_kernel_image_notifier, n);
+ break;
+ case LOAD_USER_IMAGE:
+ err = notifier_chain_register(&load_user_image_notifier, n);
+ break;
}
up_write(&profile_rwsem);
@@ -112,6 +159,18 @@
case EXEC_UNMAP:
err = notifier_chain_unregister(&exec_unmap_notifier, n);
break;
+ case DO_FORK:
+ err = notifier_chain_unregister(&do_fork_notifier, n);
+ break;
+ case DO_EXECVE:
+ err = notifier_chain_unregister(&do_execve_notifier, n);
+ break;
+ case LOAD_KERNEL_IMAGE:
+ err = notifier_chain_unregister(&load_kernel_image_notifier, n);
+ break;
+ case LOAD_USER_IMAGE:
+ err = notifier_chain_unregister(&load_user_image_notifier, n);
+ break;
}
up_write(&profile_rwsem);
diff -urN linux-2.6.0-test2/kernel/fork.c
linux-2.6.0-test2-intel-vtune/kernel/fork.c
--- linux-2.6.0-test2/kernel/fork.c Sun Jul 27 09:57:39 2003
+++ linux-2.6.0-test2-intel-vtune/kernel/fork.c Sat Aug 2 20:18:56 2003
@@ -30,6 +30,7 @@
#include <linux/futex.h>
#include <linux/ptrace.h>
#include <linux/mount.h>
+#include <linux/profile.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -1084,6 +1085,8 @@
set_tsk_thread_flag(p, TIF_SIGPENDING);
}
+ profile_do_fork(p);
+
p->state = TASK_STOPPED;
if (!(clone_flags & CLONE_STOPPED))
wake_up_forked_process(p); /* do this last */
diff -urN linux-2.6.0-test2/kernel/module.c
linux-2.6.0-test2-intel-vtune/kernel/module.c
--- linux-2.6.0-test2/kernel/module.c Sun Jul 27 10:06:11 2003
+++ linux-2.6.0-test2-intel-vtune/kernel/module.c Sat Aug 2 20:22:50 2003
@@ -27,6 +27,7 @@
#include <linux/fcntl.h>
#include <linux/rcupdate.h>
#include <linux/cpu.h>
+#include <linux/profile.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/err.h>
@@ -1653,6 +1654,21 @@
if (err < 0)
goto cleanup;
+ /* track address of each loaded section in kernel module;
+ * only profile those which lie within the module's address
+ * range; we do it here since by this time all the sections
+ * have been properly layed out
+ */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if ( (sechdrs[i].sh_addr >= (unsigned long) mod->module_core) &&
+ (sechdrs[i].sh_addr < (unsigned long) (mod->module_core +
+ mod->core_size))) {
+ profile_load_kernel_image(mod, i,
+ (unsigned long)(sechdrs[i].sh_addr),
+ (unsigned long)(sechdrs[i].sh_size));
+ }
+ }
+
/* Get rid of temporary copy */
vfree(hdr);
diff -urN linux-2.6.0-test2/fs/exec.c linux-2.6.0-test2-intel-vtune/fs/exec.c
--- linux-2.6.0-test2/fs/exec.c Sun Jul 27 10:00:36 2003
+++ linux-2.6.0-test2-intel-vtune/fs/exec.c Sat Aug 2 20:01:30 2003
@@ -45,6 +45,7 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/rmap-locking.h>
+#include <linux/profile.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -1099,6 +1100,8 @@
if (retval >= 0) {
free_arg_pages(&bprm);
+ profile_do_execve(current);
+
/* execve success */
security_bprm_free(&bprm);
return retval;
diff -urN linux-2.6.0-test2/mm/mmap.c linux-2.6.0-test2-intel-vtune/mm/mmap.c
--- linux-2.6.0-test2/mm/mmap.c Sun Jul 27 10:04:01 2003
+++ linux-2.6.0-test2-intel-vtune/mm/mmap.c Sat Aug 2 20:33:15 2003
@@ -674,6 +674,11 @@
}
kmem_cache_free(vm_area_cachep, vma);
}
+
+ if (vma->vm_flags & VM_EXEC) {
+ profile_load_user_image(current, vma);
+ }
+
out:
mm->total_vm += len >> PAGE_SHIFT;
if (vm_flags & VM_LOCKED) {