Patch adds Process Performance Statistics. arch/i386/kernel/asm-offsets.c | 3 +++ arch/i386/kernel/entry.S | 6 ++++++ fs/proc/array.c | 17 +++++++++++++++++ include/asm-i386/thread_info.h | 5 +++-- kernel/fork.c | 4 ++++ lib/Kconfig.debug | 15 +++++++++++++++ 6 files changed, 48 insertions(+), 2 deletions(-) Index: linux-2.6.21-rc5/fs/proc/array.c =================================================================== --- linux-2.6.21-rc5.orig/fs/proc/array.c +++ linux-2.6.21-rc5/fs/proc/array.c @@ -291,6 +291,20 @@ static inline char *task_cap(struct task cap_t(p->cap_effective)); } +#ifdef CONFIG_THREAD_PERF_STAT +static inline char *task_perf(struct task_struct *p, char *buffer) +{ +#ifdef CONFIG_THREAD_PERF_STAT_SYSC + buffer += sprintf(buffer, "Syscalls:\t%lu\n", p->thread_info->sysc_cnt); +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */ + + return buffer + sprintf(buffer, "Nvcsw:\t%lu\n" + "Nivcsw:\t%lu\n", + p->nvcsw, + p->nivcsw); +} +#endif /* CONFIG_THREAD_PERF_STAT */ + int proc_pid_status(struct task_struct *task, char * buffer) { char * orig = buffer; @@ -309,6 +323,9 @@ int proc_pid_status(struct task_struct * #if defined(CONFIG_S390) buffer = task_show_regs(task, buffer); #endif +#ifdef CONFIG_THREAD_PERF_STAT + buffer = task_perf(task, buffer); +#endif /* CONFIG_THREAD_PERF_STAT */ return buffer - orig; } Index: linux-2.6.21-rc5/kernel/fork.c =================================================================== --- linux-2.6.21-rc5.orig/kernel/fork.c +++ linux-2.6.21-rc5/kernel/fork.c @@ -1044,6 +1044,10 @@ static struct task_struct *copy_process( p->syscr = 0; /* I/O counter: read syscalls */ p->syscw = 0; /* I/O counter: write syscalls */ #endif +#ifdef CONFIG_THREAD_PERF_STAT_SYSC + p->thread_info->sysc_cnt = 0; /* Syscall counter: total numbers of syscalls */ +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */ + task_io_accounting_init(p); acct_clear_integrals(p); Index: linux-2.6.21-rc5/lib/Kconfig.debug =================================================================== --- linux-2.6.21-rc5.orig/lib/Kconfig.debug +++ linux-2.6.21-rc5/lib/Kconfig.debug @@ -446,3 +446,18 @@ config FAULT_INJECTION_STACKTRACE_FILTER select FRAME_POINTER help Provide stacktrace filter for fault-injection capabilities + +config THREAD_PERF_STAT + bool "Per-process (thread) performance statistics" + help + Make available to the user the following per-process (thread) performance statistics: + * Number of involuntary context switches + * Number of voluntary context switches + * Number of system calls (optional) + This information is available via /proc/PID/status. + +config THREAD_PERF_STAT_SYSC + bool "Enable syscall counter" + depends on THREAD_PERF_STAT && X86_32 + help + This option adds a syscall counter to /proc/PID/status. Index: linux-2.6.21-rc5/arch/i386/kernel/entry.S =================================================================== --- linux-2.6.21-rc5.orig/arch/i386/kernel/entry.S +++ linux-2.6.21-rc5/arch/i386/kernel/entry.S @@ -342,6 +342,9 @@ sysenter_past_esp: jae syscall_badsys call *sys_call_table(,%eax,4) movl %eax,PT_EAX(%esp) +#ifdef CONFIG_THREAD_PERF_STAT_SYSC + incl TI_sysc_cnt(%ebp) # Increment syscalls counter +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */ DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX) TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx @@ -385,6 +388,9 @@ syscall_call: call *sys_call_table(,%eax,4) movl %eax,PT_EAX(%esp) # store the return value syscall_exit: +#ifdef CONFIG_THREAD_PERF_STAT_SYSC + incl TI_sysc_cnt(%ebp) # Increment syscalls counter +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */ DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret Index: linux-2.6.21-rc5/arch/i386/kernel/asm-offsets.c =================================================================== --- linux-2.6.21-rc5.orig/arch/i386/kernel/asm-offsets.c +++ linux-2.6.21-rc5/arch/i386/kernel/asm-offsets.c @@ -56,6 +56,9 @@ void foo(void) OFFSET(TI_addr_limit, thread_info, addr_limit); OFFSET(TI_restart_block, thread_info, restart_block); OFFSET(TI_sysenter_return, thread_info, sysenter_return); +#ifdef CONFIG_THREAD_PERF_STAT_SYSC + OFFSET(TI_sysc_cnt, thread_info, sysc_cnt); +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */ BLANK(); OFFSET(GDS_size, Xgt_desc_struct, size); Index: linux-2.6.21-rc5/include/asm-i386/thread_info.h =================================================================== --- linux-2.6.21-rc5.orig/include/asm-i386/thread_info.h +++ linux-2.6.21-rc5/include/asm-i386/thread_info.h @@ -31,8 +31,9 @@ struct thread_info { unsigned long status; /* thread-synchronous flags */ __u32 cpu; /* current CPU */ int preempt_count; /* 0 => preemptable, <0 => BUG */ - - +#ifdef CONFIG_THREAD_PERF_STAT_SYSC + unsigned long sysc_cnt; /* Syscall counter */ +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */ mm_segment_t addr_limit; /* thread address space: 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernel-thread