public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Performance Stats: Kernel patch
@ 2007-04-03 12:54 Maxim Uvarov
  2007-04-03 23:01 ` Valdis.Kletnieks
  0 siblings, 1 reply; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-03 12:54 UTC (permalink / raw)
  To: linux-kernel

Hello all,

I have idea to include to the user the following new per-process 
(thread) performance statistics:

    * Involuntary Context Switches
    * Voluntary Context Switches
    * Number of system calls

What do you think about it? Patch is bellow.

Best regards,
Max Uvarov.


Description:
    Patch adds Process Performance Statistics.

 arch/i386/kernel/entry.S       |    3 +++
 arch/mips/kernel/entry.S       |    3 +++
 arch/powerpc/kernel/entry_32.S |    3 +++
 arch/x86_64/kernel/entry.S     |    3 +++
 fs/proc/array.c                |   13 +++++++++++++
 include/linux/sched.h          |    3 +++
 kernel/fork.c                  |    3 +++
 kernel/sys.c                   |    8 ++++++++
 lib/Kconfig.debug              |   10 ++++++++++
 9 files changed, 49 insertions(+)

Index: linux-2.6.18/fs/proc/array.c
===================================================================
--- linux-2.6.18.orig/fs/proc/array.c
+++ linux-2.6.18/fs/proc/array.c
@@ -295,6 +295,18 @@ static inline char *task_cap(struct task
                            cap_t(p->cap_effective));
 }

+#ifdef THREAD_PERF_STAT
+static inline char *task_perf(struct task_struct *p, char *buffer)
+{
+    return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
+                           "Nivcsw:\t%lu\n"
+                           "Syscalls:\t%d\n",
+                           cap_t(p->nvcsw),
+                           cap_t(p->nivcsw),
+                           cap_t(p->sysc_cnt));
+}
+#endif /* THREAD_PERF_STAT */
+
 #define get_blocked_on(t)      (-1)

 static char *show_blocked_on(struct task_struct *task, char *buffer)
@@ -327,6 +339,7 @@ int proc_pid_status(struct task_struct *
        buffer = task_show_regs(task, buffer);
 #endif
        buffer = show_blocked_on(task,buffer);
+       buffer = task_perf(task, buffer);
        return buffer - orig;
 }

Index: linux-2.6.18/include/linux/sched.h
===================================================================
--- linux-2.6.18.orig/include/linux/sched.h
+++ linux-2.6.18/include/linux/sched.h
@@ -1193,6 +1193,9 @@ struct task_struct {
        ltt_facility_t ltt_facilities[LTT_FAC_PER_PROCESS];
 #endif //CONFIG_LTT_USERSPACE_GENERIC

+#ifdef THREAD_PERF_STAT
+       int sysc_cnt;           /* Syscall counter */
+#endif /* THREAD_PERF_STAT */
        /*
         * task-specic data
         * XXX: for a future release, MontaVista-only
Index: linux-2.6.18/kernel/sys.c
===================================================================
--- linux-2.6.18.orig/kernel/sys.c
+++ linux-2.6.18/kernel/sys.c
@@ -2071,3 +2071,11 @@ asmlinkage long sys_prctl(int option, un
        }
        return error;
 }
+#ifdef THREAD_PERF_STAT
+asmlinkage void inc_syscallcnt(void)
+{
+       current->sysc_cnt += 1;
+       return;
+}
+#endif /* THREAD_PERF_STAT */
+
Index: linux-2.6.18/kernel/fork.c
===================================================================
--- linux-2.6.18.orig/kernel/fork.c
+++ linux-2.6.18/kernel/fork.c
@@ -1079,6 +1079,9 @@ static struct task_struct *copy_process(
        p->wchar = 0;           /* I/O counter: bytes written */
        p->syscr = 0;           /* I/O counter: read syscalls */
        p->syscw = 0;           /* I/O counter: write syscalls */
+#ifdef THREAD_PERF_STAT
+       p->sysc_cnt = 0;        /* Syscall counter: total numbers of 
syscalls */
+#endif /* THREAD_PERF_STAT */
        acct_clear_integrals(p);

        p->it_virt_expires = cputime_zero;
Index: linux-2.6.18/arch/i386/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/i386/kernel/entry.S
+++ linux-2.6.18/arch/i386/kernel/entry.S
@@ -394,6 +394,9 @@ syscall_exit:
        cli                             # make sure we don't miss an 
interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
+#ifdef THREAD_PERF_STAT
+       call inc_syscallcnt             # Increment syscalls counter 
current->sysc_cnt
+#endif /* THREAD_PERF_STAT */
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx   # current->work
Index: linux-2.6.18/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.18/arch/x86_64/kernel/entry.S
@@ -388,6 +388,9 @@ ENTRY(int_ret_from_sys_call)
        /* edi: mask to check */
 int_with_check:
        GET_THREAD_INFO(%rcx)
+#ifdef THREAD_PERF_STAT
+       call inc_syscallcnt     # Increment syscalls counter 
current->sysc_cnt
+#endif /* THREAD_PERF_STAT */
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
        jnz   int_careful
Index: linux-2.6.18/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-2.6.18.orig/arch/powerpc/kernel/entry_32.S
+++ linux-2.6.18/arch/powerpc/kernel/entry_32.S
@@ -236,6 +236,9 @@ ret_from_syscall:
 #ifdef SHOW_SYSCALLS
        bl      do_show_syscall_exit
 #endif
+#ifdef THREAD_PERF_STAT
+       bl      inc_syscallcnt  /* Increment syscalls counter 
current->sysc_cnt */
+#endif /* THREAD_PERF_STAT */
 #ifdef CONFIG_MICROSTATE
        /* FIXME: this is too early since this might not return to
           user space just yet because of syscall_exit_work */
Index: linux-2.6.18/arch/mips/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/mips/kernel/entry.S
+++ linux-2.6.18/arch/mips/kernel/entry.S
@@ -75,6 +75,9 @@ FEXPORT(syscall_exit)
        raw_local_irq_disable   # make sure need_resched and
                                        # signals dont change between
                                        # sampling and return
+#ifdef THREAD_PERF_STAT
+       jal     inc_syscallcnt          # Increment syscalls counter 
current->sysc_cnt
+#endif /* THREAD_PERF_STAT */
        LONG_L  a2, TI_FLAGS($28)       # current->work
        li      t0, _TIF_ALLWORK_MASK
        and     t0, a2, t0
Index: linux-2.6.18/lib/Kconfig.debug
===================================================================
--- linux-2.6.18.orig/lib/Kconfig.debug
+++ linux-2.6.18/lib/Kconfig.debug
@@ -539,4 +539,14 @@ config RCU_TORTURE_TEST
          Say M if you want the RCU torture tests to build as a module.
          Say N if you are unsure.

+config THREAD_PERF_STAT
+       bool "Per-process (thread) performance statistics"
+       depends on (X86 || PPC || MIPS)
+       help
+         Make available to the user the following new per-process 
(thread) performance statistics:
+           * Involuntary Context Switches
+           * Voluntary Context Switches
+           * Number of system calls
+         This information is available via /proc/PID/status.
+
 source "lib/Kconfig.kgdb"

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-03 12:54 Maxim Uvarov
@ 2007-04-03 23:01 ` Valdis.Kletnieks
  2007-04-04 13:15   ` Maxim Uvarov
  0 siblings, 1 reply; 28+ messages in thread
From: Valdis.Kletnieks @ 2007-04-03 23:01 UTC (permalink / raw)
  To: Maxim Uvarov; +Cc: linux-kernel

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

On Tue, 03 Apr 2007 16:54:43 +0400, Maxim Uvarov said:

> What do you think about it? Patch is bellow.

Was this patch actually compile and run tested?

> Index: linux-2.6.18/fs/proc/array.c
> ===================================================================
> --- linux-2.6.18.orig/fs/proc/array.c
> +++ linux-2.6.18/fs/proc/array.c
> @@ -295,6 +295,18 @@ static inline char *task_cap(struct task
>                             cap_t(p->cap_effective));
>  }
> 
> +#ifdef THREAD_PERF_STAT

This needs to be CONFIG_THREAD_PERF_STAT everyplace except the Kconfig stuff.

> +static inline char *task_perf(struct task_struct *p, char *buffer)
> +{
> +    return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
> +                           "Nivcsw:\t%lu\n"
> +                           "Syscalls:\t%d\n",
> +                           cap_t(p->nvcsw),
> +                           cap_t(p->nivcsw),
> +                           cap_t(p->sysc_cnt));
> +}

You might want a #else that defines a null body for this inline, to
avoid a problem a bit later.

> +#endif /* THREAD_PERF_STAT */
> +
>  #define get_blocked_on(t)      (-1)
> 
>  static char *show_blocked_on(struct task_struct *task, char *buffer)
> @@ -327,6 +339,7 @@ int proc_pid_status(struct task_struct *
>         buffer = task_show_regs(task, buffer);
>  #endif
>         buffer = show_blocked_on(task,buffer);
> +       buffer = task_perf(task, buffer);

What will this call if you don't have THREAD_PERF_STAT defined?

Here's where you need the #else clause providing a null body for you....

I don't see how this could possibly have built cleanly, since the CONFIG_
issue above would have prevented you from defining a task_perf() function...



[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-03 23:01 ` Valdis.Kletnieks
@ 2007-04-04 13:15   ` Maxim Uvarov
  2007-04-04 13:46     ` Eric Dumazet
                       ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-04 13:15 UTC (permalink / raw)
  To: Valdis.Kletnieks; +Cc: linux-kernel

Hello again,

Please see my answers bellow:

Valdis.Kletnieks@vt.edu wrote:

>On Tue, 03 Apr 2007 16:54:43 +0400, Maxim Uvarov said:
>
>  
>
>>What do you think about it? Patch is bellow.
>>    
>>
>
>Was this patch actually compile and run tested?
>  
>
Yes I have tested it on PPC, X86, X86_64, Mips targets.
It works.

>  
>
>>Index: linux-2.6.18/fs/proc/array.c
>>===================================================================
>>--- linux-2.6.18.orig/fs/proc/array.c
>>+++ linux-2.6.18/fs/proc/array.c
>>@@ -295,6 +295,18 @@ static inline char *task_cap(struct task
>>                            cap_t(p->cap_effective));
>> }
>>
>>+#ifdef THREAD_PERF_STAT
>>    
>>
>
>This needs to be CONFIG_THREAD_PERF_STAT everyplace except the Kconfig stuff.
>  
>
Yes you are right. I have not check it after adding ifdef :(

>  
>
>>+static inline char *task_perf(struct task_struct *p, char *buffer)
>>+{
>>+    return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
>>+                           "Nivcsw:\t%lu\n"
>>+                           "Syscalls:\t%d\n",
>>+                           cap_t(p->nvcsw),
>>+                           cap_t(p->nivcsw),
>>+                           cap_t(p->sysc_cnt));
>>+}
>>    
>>
>
>You might want a #else that defines a null body for this inline, to
>avoid a problem a bit later.
>
>  
>
>>+#endif /* THREAD_PERF_STAT */
>>+
>> #define get_blocked_on(t)      (-1)
>>
>> static char *show_blocked_on(struct task_struct *task, char *buffer)
>>@@ -327,6 +339,7 @@ int proc_pid_status(struct task_struct *
>>        buffer = task_show_regs(task, buffer);
>> #endif
>>        buffer = show_blocked_on(task,buffer);
>>+       buffer = task_perf(task, buffer);
>>    
>>
>
>What will this call if you don't have THREAD_PERF_STAT defined?
>
>Here's where you need the #else clause providing a null body for you....
>
>I don't see how this could possibly have built cleanly, since the CONFIG_
>issue above would have prevented you from defining a task_perf() function...
>
>
>  
>
New version of this patch. Please flay it.


Signed-off-by: Max Uvarov <muvarov@ru.mvista.com>
Description:
    Patch adds Process Performance Statistics.

 arch/i386/kernel/entry.S       |    3 +++
 arch/mips/kernel/entry.S       |    3 +++
 arch/powerpc/kernel/entry_32.S |    3 +++
 arch/x86_64/kernel/entry.S     |    3 +++
 fs/proc/array.c                |   17 +++++++++++++++++
 include/linux/sched.h          |    3 +++
 kernel/fork.c                  |    3 +++
 kernel/sys.c                   |    8 ++++++++
 lib/Kconfig.debug              |   17 +++++++++++++++++
 9 files changed, 60 insertions(+)

Index: linux-2.6.18/fs/proc/array.c
===================================================================
--- linux-2.6.18.orig/fs/proc/array.c
+++ linux-2.6.18/fs/proc/array.c
@@ -295,6 +295,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 THREAD_PERF_STAT_SYSC
+       buffer += sprintf(buffer, "Syscalls:\t%d\n", cap_t(p->sysc_cnt));
+#endif /* THREAD_PERF_STAT_SYSC */
+
+       return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
+                           "Nivcsw:\t%lu\n",
+                           cap_t(p->nvcsw),
+                           cap_t(p->nivcsw));
+}
+#endif /* CONFIG_THREAD_PERF_STAT */
+
 #define get_blocked_on(t)      (-1)

 static char *show_blocked_on(struct task_struct *task, char *buffer)
@@ -327,6 +341,9 @@ int proc_pid_status(struct task_struct *
        buffer = task_show_regs(task, buffer);
 #endif
        buffer = show_blocked_on(task,buffer);
+#ifdef CONFIG_THREAD_PERF_STAT
+       buffer = task_perf(task, buffer);
+#endif /* CONFIG_THREAD_PERF_STAT */
        return buffer - orig;
 }

Index: linux-2.6.18/include/linux/sched.h
===================================================================
--- linux-2.6.18.orig/include/linux/sched.h
+++ linux-2.6.18/include/linux/sched.h
@@ -1193,6 +1193,9 @@ struct task_struct {
        ltt_facility_t ltt_facilities[LTT_FAC_PER_PROCESS];
 #endif //CONFIG_LTT_USERSPACE_GENERIC

+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       int sysc_cnt;           /* Syscall counter */
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
        /*
         * task-specic data
         * XXX: for a future release, MontaVista-only
Index: linux-2.6.18/kernel/sys.c
===================================================================
--- linux-2.6.18.orig/kernel/sys.c
+++ linux-2.6.18/kernel/sys.c
@@ -2071,3 +2071,11 @@ asmlinkage long sys_prctl(int option, un
        }
        return error;
 }
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+asmlinkage void inc_syscallcnt(void)
+{
+       current->sysc_cnt += 1;
+       return;
+}
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+
Index: linux-2.6.18/kernel/fork.c
===================================================================
--- linux-2.6.18.orig/kernel/fork.c
+++ linux-2.6.18/kernel/fork.c
@@ -1079,6 +1079,9 @@ static struct task_struct *copy_process(
        p->wchar = 0;           /* I/O counter: bytes written */
        p->syscr = 0;           /* I/O counter: read syscalls */
        p->syscw = 0;           /* I/O counter: write syscalls */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       p->sysc_cnt = 0;        /* Syscall counter: total numbers of 
syscalls */
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
        acct_clear_integrals(p);

        p->it_virt_expires = cputime_zero;
Index: linux-2.6.18/arch/i386/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/i386/kernel/entry.S
+++ linux-2.6.18/arch/i386/kernel/entry.S
@@ -394,6 +394,9 @@ syscall_exit:
        cli                             # make sure we don't miss an 
interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       call inc_syscallcnt             # Increment syscalls counter 
current->sysc_cnt
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx   # current->work
Index: linux-2.6.18/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.18/arch/x86_64/kernel/entry.S
@@ -388,6 +388,9 @@ ENTRY(int_ret_from_sys_call)
        /* edi: mask to check */
 int_with_check:
        GET_THREAD_INFO(%rcx)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       call inc_syscallcnt     # Increment syscalls counter 
current->sysc_cnt
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
        jnz   int_careful
Index: linux-2.6.18/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-2.6.18.orig/arch/powerpc/kernel/entry_32.S
+++ linux-2.6.18/arch/powerpc/kernel/entry_32.S
@@ -236,6 +236,9 @@ ret_from_syscall:
 #ifdef SHOW_SYSCALLS
        bl      do_show_syscall_exit
 #endif
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       bl      inc_syscallcnt  /* Increment syscalls counter 
current->sysc_cnt */
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 #ifdef CONFIG_MICROSTATE
        /* FIXME: this is too early since this might not return to
           user space just yet because of syscall_exit_work */
Index: linux-2.6.18/arch/mips/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/mips/kernel/entry.S
+++ linux-2.6.18/arch/mips/kernel/entry.S
@@ -75,6 +75,9 @@ FEXPORT(syscall_exit)
        raw_local_irq_disable   # make sure need_resched and
                                        # signals dont change between
                                        # sampling and return
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       jal     inc_syscallcnt          # Increment syscalls counter 
current->sysc_cnt
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
        LONG_L  a2, TI_FLAGS($28)       # current->work
        li      t0, _TIF_ALLWORK_MASK
        and     t0, a2, t0
Index: linux-2.6.18/lib/Kconfig.debug
===================================================================
--- linux-2.6.18.orig/lib/Kconfig.debug
+++ linux-2.6.18/lib/Kconfig.debug
@@ -539,4 +539,21 @@ config RCU_TORTURE_TEST
          Say M if you want the RCU torture tests to build as a module.
          Say N if you are unsure.

+config THREAD_PERF_STAT
+       bool "Per-process (thread) performance statistics"
+       depends on (X86 || PPC || MIPS)
+       help
+         Make available to the user the following new per-process 
(thread) performance statistics:
+           * Involuntary Context Switches
+           * Voluntary Context Switches
+           * Number of system calls (option)
+         This information is available via /proc/PID/status.
+
+config THREAD_PERF_STAT_SYSC
+       bool "enable syscall counter"
+       depends on THREAD_PERF_STAT
+       help
+          This option add syscalls counter to  /proc/PID/status.
+
+
 source "lib/Kconfig.kgdb"


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 13:15   ` Maxim Uvarov
@ 2007-04-04 13:46     ` Eric Dumazet
  2007-04-04 16:52       ` Maxim Uvarov
  2007-04-04 21:54       ` Valdis.Kletnieks
  2007-04-04 13:59     ` Jesper Juhl
                       ` (2 subsequent siblings)
  3 siblings, 2 replies; 28+ messages in thread
From: Eric Dumazet @ 2007-04-04 13:46 UTC (permalink / raw)
  To: Maxim Uvarov; +Cc: Valdis.Kletnieks, linux-kernel

On Wed, 04 Apr 2007 17:15:43 +0400
Maxim Uvarov <muvarov@ru.mvista.com> wrote:

>
> --- linux-2.6.18.orig/arch/i386/kernel/entry.S
> +++ linux-2.6.18/arch/i386/kernel/entry.S
> @@ -394,6 +394,9 @@ syscall_exit:
>         cli                             # make sure we don't miss an 
> interrupt
>                                         # setting need_resched or sigpending
>                                         # between sampling and the iret
> +#ifdef CONFIG_THREAD_PERF_STAT_SYSC
> +       call inc_syscallcnt             # Increment syscalls counter 
> current->sysc_cnt
> +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */

Please dont call a function to do one increment !

You are touching one of the most critical part of the kernel...

Also, dont do this while interrupts are masked, this is not necessary.

Maybe better to place sysc_cnt in 'struct thread_info' because %ebp point to it.

Also you missed the fact that syscalls on i386 can use sysenter (around line 343)

>         TRACE_IRQS_OFF
>         movl TI_flags(%ebp), %ecx
>         testw $_TIF_ALLWORK_MASK, %cx   # current->work
>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 13:15   ` Maxim Uvarov
  2007-04-04 13:46     ` Eric Dumazet
@ 2007-04-04 13:59     ` Jesper Juhl
  2007-04-04 21:50     ` Valdis.Kletnieks
  2007-04-08 16:58     ` Pavel Machek
  3 siblings, 0 replies; 28+ messages in thread
From: Jesper Juhl @ 2007-04-04 13:59 UTC (permalink / raw)
  To: Maxim Uvarov; +Cc: Valdis.Kletnieks, linux-kernel

On 04/04/07, Maxim Uvarov <muvarov@ru.mvista.com> wrote:
> Hello again,
>
[snip]
> New version of this patch. Please flay it.
>

A few small comments below.

>
> +config THREAD_PERF_STAT
> +       bool "Per-process (thread) performance statistics"
> +       depends on (X86 || PPC || MIPS)
> +       help
> +         Make available to the user the following new per-process
> (thread) performance statistics:

Get rid of the word "new" - it won't continue to be a "new" feature forever :-)

> +           * Involuntary Context Switches
> +           * Voluntary Context Switches
> +           * Number of system calls (option)

In the first two lines you Capitalize Each Word, but in the last line
you don't - why?
Shouldn't the first two have "Number of" prepended?
Perhaps it's just me, but I would write "(optional)" instead of "(option)".

In short, I'd suggest this :

           * Number of involuntary context switches
           * Number of voluntary context switches
           * Number of system calls (optional)

> +         This information is available via /proc/PID/status.

What about tools that currently parse /proc/PID/status ?  Don't you
risk breaking userland stuff by changing this file?   Wouldn't it be
better to use a new file?

> +
> +config THREAD_PERF_STAT_SYSC
> +       bool "enable syscall counter"

Capitalize the first word; "Enable syscall counter" .

> +       depends on THREAD_PERF_STAT
> +       help
> +          This option add syscalls counter to  /proc/PID/status.

I'd probably have written "This option adds a syscall counter to
/proc/PID/status."


-- 
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post  http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please      http://www.expita.com/nomime.html

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 13:46     ` Eric Dumazet
@ 2007-04-04 16:52       ` Maxim Uvarov
  2007-04-04 18:04         ` Eric Dumazet
  2007-04-04 21:54       ` Valdis.Kletnieks
  1 sibling, 1 reply; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-04 16:52 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Valdis.Kletnieks, linux-kernel

Hello Eric,

I changed patch according to your comments.
Could you please take a look at it?

Eric Dumazet wrote:

>On Wed, 04 Apr 2007 17:15:43 +0400
>Maxim Uvarov <muvarov@ru.mvista.com> wrote:
>
>  
>
>>--- linux-2.6.18.orig/arch/i386/kernel/entry.S
>>+++ linux-2.6.18/arch/i386/kernel/entry.S
>>@@ -394,6 +394,9 @@ syscall_exit:
>>        cli                             # make sure we don't miss an 
>>interrupt
>>                                        # setting need_resched or sigpending
>>                                        # between sampling and the iret
>>+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
>>+       call inc_syscallcnt             # Increment syscalls counter 
>>current->sysc_cnt
>>+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
>>    
>>
>
>Please dont call a function to do one increment !
>  
>
Yes, you are right. I have changed it.

>You are touching one of the most critical part of the kernel...
>
>Also, dont do this while interrupts are masked, this is not necessary.
>
>Maybe better to place sysc_cnt in 'struct thread_info' because %ebp point to it.
>  
>

>Also you missed the fact that syscalls on i386 can use sysenter (around line 343)
>
>  
>
>>        TRACE_IRQS_OFF
>>        movl TI_flags(%ebp), %ecx
>>        testw $_TIF_ALLWORK_MASK, %cx   # current->work
>>
>>    
>>
I rewrote this patch for x86.   And I have question. Should /proc/PID/status
be used for these counters and this option be selectable or it will 
better to
create another file in /proc/PID/  directory?

I will include syscall counters for other arches later.

P.S.
Jesper Juhl, thank you.

Best regards,
Maxim.

Signed-off-by: Max Uvarov <muvarov@ru.mvista.com>
Description:
    Patch adds Process Performance Statistics.

 arch/i386/kernel/asm-offsets.c |    3 +++
 arch/i386/kernel/entry.S       |    6 ++++++
 fs/proc/array.c                |   14 ++++++++++++++
 include/asm/thread_info.h      |    3 +++
 kernel/fork.c                  |    3 +++
 lib/Kconfig.debug              |   16 ++++++++++++++++
 6 files changed, 45 insertions(+)

Index: linux-2.6.18/fs/proc/array.c
===================================================================
--- linux-2.6.18.orig/fs/proc/array.c
+++ linux-2.6.18/fs/proc/array.c
@@ -295,6 +295,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", 
cap_t(p->thread_info->sysc_cnt));
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+
+       return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
+                           "Nivcsw:\t%lu\n",
+                           cap_t(p->nvcsw),
+                           cap_t(p->nivcsw));
+}
+#endif /* CONFIG_THREAD_PERF_STAT */
+
 #define get_blocked_on(t)      (-1)

 static char *show_blocked_on(struct task_struct *task, char *buffer)
Index: linux-2.6.18/arch/i386/kernel/entry.S
===================================================================
--- linux-2.6.18.orig/arch/i386/kernel/entry.S
+++ linux-2.6.18/arch/i386/kernel/entry.S
@@ -334,6 +334,9 @@ sysenter_past_esp:
        jae syscall_badsys
        call *sys_call_table(,%eax,4)
        movl %eax,EAX(%esp)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       incl    TI_sysc_cnt(%ebp)       # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 #ifdef CONFIG_MICROSTATE
        call msa_end_syscall
 #endif
@@ -388,6 +391,9 @@ syscall_call:
        call *sys_call_table(,%eax,4)
        movl %eax,EAX(%esp)             # store the return value
 syscall_exit:
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       incl    TI_sysc_cnt(%ebp)       # Increment syscalls counter 
current->sysc_cnt
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 #ifdef CONFIG_MICROSTATE
        call msa_end_syscall
 #endif
Index: linux-2.6.18/lib/Kconfig.debug
===================================================================
--- linux-2.6.18.orig/lib/Kconfig.debug
+++ linux-2.6.18/lib/Kconfig.debug
@@ -539,4 +539,20 @@ config RCU_TORTURE_TEST
          Say M if you want the RCU torture tests to build as a module.
          Say N if you are unsure.

+config THREAD_PERF_STAT
+       bool "Per-process (thread) performance statistics"
+       depends on X86
+       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
+       help
+         This option adds a syscall counter to /proc/PID/status.
+
 source "lib/Kconfig.kgdb"
Index: linux-2.6.18/include/asm/thread_info.h
===================================================================
--- linux-2.6.18.orig/include/asm/thread_info.h
+++ linux-2.6.18/include/asm/thread_info.h
@@ -44,6 +44,9 @@ struct thread_info {
                                                   of nested (IRQ) stacks
                                                */
        __u8                    supervisor_stack[0];
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       unsigned long           sysc_cnt;           /* Syscall counter */
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 };

 #else /* !__ASSEMBLY__ */
Index: linux-2.6.18/kernel/fork.c
===================================================================
--- linux-2.6.18.orig/kernel/fork.c
+++ linux-2.6.18/kernel/fork.c
@@ -1079,6 +1079,9 @@ static struct task_struct *copy_process(
        p->wchar = 0;           /* I/O counter: bytes written */
        p->syscr = 0;           /* I/O counter: read syscalls */
        p->syscw = 0;           /* I/O counter: write syscalls */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+       p->thread_info->sysc_cnt = 0;   /* Syscall counter: total 
numbers of syscalls */
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
        acct_clear_integrals(p);

        p->it_virt_expires = cputime_zero;
Index: linux-2.6.18/arch/i386/kernel/asm-offsets.c
===================================================================
--- linux-2.6.18.orig/arch/i386/kernel/asm-offsets.c
+++ linux-2.6.18/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();


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 16:52       ` Maxim Uvarov
@ 2007-04-04 18:04         ` Eric Dumazet
  0 siblings, 0 replies; 28+ messages in thread
From: Eric Dumazet @ 2007-04-04 18:04 UTC (permalink / raw)
  To: Maxim Uvarov; +Cc: Valdis.Kletnieks, linux-kernel

On Wed, 04 Apr 2007 20:52:34 +0400
Maxim Uvarov <muvarov@ru.mvista.com> wrote:


> Index: linux-2.6.18/include/asm/thread_info.h
> ===================================================================
> --- linux-2.6.18.orig/include/asm/thread_info.h
> +++ linux-2.6.18/include/asm/thread_info.h
> @@ -44,6 +44,9 @@ struct thread_info {
>                                                    of nested (IRQ) stacks
>                                                 */
>         __u8                    supervisor_stack[0];
> +#ifdef CONFIG_THREAD_PERF_STAT_SYSC
> +       unsigned long           sysc_cnt;           /* Syscall counter */
> +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
>  };
> 
>  #else /* !__ASSEMBLY__ */

You probably meant include/asm-i386/thread_info.h, not include/asm/thread_info.h

Then, you should not place sysc_cnt after supervisor_stack[0], since supervisor_stack[0] should be the last element of struct thread_info.

Better to put sysc_cnt right after preempt_count for example.

Also, is there any reason your patches are against 2.6.18, and not current kernel ?


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 13:15   ` Maxim Uvarov
  2007-04-04 13:46     ` Eric Dumazet
  2007-04-04 13:59     ` Jesper Juhl
@ 2007-04-04 21:50     ` Valdis.Kletnieks
  2007-04-04 22:03       ` Randy Dunlap
  2007-04-06 21:50       ` Bill Davidsen
  2007-04-08 16:58     ` Pavel Machek
  3 siblings, 2 replies; 28+ messages in thread
From: Valdis.Kletnieks @ 2007-04-04 21:50 UTC (permalink / raw)
  To: Maxim Uvarov; +Cc: linux-kernel

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

On Wed, 04 Apr 2007 17:15:43 +0400, Maxim Uvarov said:

> New version of this patch. Please flay it.
> 
> 
> Signed-off-by: Max Uvarov <muvarov@ru.mvista.com>

> Index: linux-2.6.18/fs/proc/array.c
> ===================================================================
> --- linux-2.6.18.orig/fs/proc/array.c
> +++ linux-2.6.18/fs/proc/array.c
> @@ -295,6 +295,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 THREAD_PERF_STAT_SYSC

Missed the CONFIG_ here.

> +       return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
> +                           "Nivcsw:\t%lu\n",
> +                           cap_t(p->nvcsw),
> +                           cap_t(p->nivcsw));

cap_t()??!?  That's from include/linux/capability.h, and looks something like:

#ifdef STRICT_CAP_T_TYPECHECKS
#define cap_t(x) (x).cap
#else
#define cap_t(x) (x)
#endif

and you're probably picking up the second part, making it a no-op.  And if you
ever hit the first part of that ifdef, you'll throw a compile error.

Somebody else can comment on the use of #ifdef - we tend to frown on it inside
open C code, but I'm not seeing a really brilliant way to avoid them entirely
(the 'static inline task_perf' can probably move to a .h, but it's hard to
find a clean way to avoid the ifdefs given that we have Kconfig variables
to select it. array.c already has a CONFIG_S390 in it, anyhow. :)

There's a mostly-hypothetical race between inc_syscall() and the places that
increment the context switch counters, and where we read the values - but at
worst, we'll output a stale off-by-one-ish value.  Certainly not worth
grabbing a lock on the task struct for *this* usage, but the sort of thing you
want to keep in mind as you write other code.

Other random comments:

1) You probably want to rebase against something more recent (2.6.21-rc<mumble>
or the final .21 when it's released).

2) It arrived here with some line-wrapping damage, most likely to the fact
that you posted it with Thunderbird.  There's a mystic Thunderbird incantation
to make it not do that, but I have no idea what it is - it's in the list
archives someplace.

[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 13:46     ` Eric Dumazet
  2007-04-04 16:52       ` Maxim Uvarov
@ 2007-04-04 21:54       ` Valdis.Kletnieks
  1 sibling, 0 replies; 28+ messages in thread
From: Valdis.Kletnieks @ 2007-04-04 21:54 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Maxim Uvarov, linux-kernel

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

On Wed, 04 Apr 2007 15:46:24 +0200, Eric Dumazet said:
> On Wed, 04 Apr 2007 17:15:43 +0400
> Maxim Uvarov <muvarov@ru.mvista.com> wrote:

> > +#ifdef CONFIG_THREAD_PERF_STAT_SYSC
> > +       call inc_syscallcnt             # Increment syscalls counter 
> > current->sysc_cnt
> > +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
> 
> Please dont call a function to do one increment !
> 
> You are touching one of the most critical part of the kernel...

Obviously Eric and I looked at this looking for totally different things. :)

Thanks for spotting that, I totally failed to notice that part....


[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 21:50     ` Valdis.Kletnieks
@ 2007-04-04 22:03       ` Randy Dunlap
  2007-04-06 21:50       ` Bill Davidsen
  1 sibling, 0 replies; 28+ messages in thread
From: Randy Dunlap @ 2007-04-04 22:03 UTC (permalink / raw)
  To: Valdis.Kletnieks; +Cc: Maxim Uvarov, linux-kernel

On Wed, 04 Apr 2007 17:50:50 -0400 Valdis.Kletnieks@vt.edu wrote:

> Other random comments:
> 
> 1) You probably want to rebase against something more recent (2.6.21-rc<mumble>
> or the final .21 when it's released).
> 
> 2) It arrived here with some line-wrapping damage, most likely to the fact
> that you posted it with Thunderbird.  There's a mystic Thunderbird incantation
> to make it not do that, but I have no idea what it is - it's in the list
> archives someplace.

This may help (or not):
  http://mbligh.org/linuxdocs/Email/Clients/Thunderbird

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 21:50     ` Valdis.Kletnieks
  2007-04-04 22:03       ` Randy Dunlap
@ 2007-04-06 21:50       ` Bill Davidsen
  1 sibling, 0 replies; 28+ messages in thread
From: Bill Davidsen @ 2007-04-06 21:50 UTC (permalink / raw)
  To: Valdis.Kletnieks; +Cc: Maxim Uvarov, linux-kernel

Valdis.Kletnieks@vt.edu wrote:

> 2) It arrived here with some line-wrapping damage, most likely to the fact
> that you posted it with Thunderbird.  There's a mystic Thunderbird incantation
> to make it not do that, but I have no idea what it is - it's in the list
> archives someplace.

I don't use TBird (seamonkey fan) but I assume the patch can just be 
attached rather than inlined. Some mailers are pretty arcane otherwise.

But I do like the idea, but the issue of things which parse 
/proc/PID/status hasn't had comments. A good parser would ignore what it 
didn't understand, or take everything, not everyone has a good parser. ;-)

-- 
Bill Davidsen <davidsen@tmr.com>
   "We have more to fear from the bungling of the incompetent than from
the machinations of the wicked."  - from Slashdot

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-04 13:15   ` Maxim Uvarov
                       ` (2 preceding siblings ...)
  2007-04-04 21:50     ` Valdis.Kletnieks
@ 2007-04-08 16:58     ` Pavel Machek
  3 siblings, 0 replies; 28+ messages in thread
From: Pavel Machek @ 2007-04-08 16:58 UTC (permalink / raw)
  To: Maxim Uvarov; +Cc: Valdis.Kletnieks, linux-kernel

Hi!

> Yes I have tested it on PPC, X86, X86_64, Mips targets.
> It works.

> >>+                           cap_t(p->nvcsw),
> >>+                           cap_t(p->nivcsw),

Nvcsw? W dn't s ncrptd dntfrs lk nvcsw n krnl. (:-)

						Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Performance Stats: Kernel patch
@ 2007-04-09 14:22 Maxim Uvarov
  2007-04-10  8:21 ` Eric Dumazet
  2007-04-15  9:47 ` Pavel Machek
  0 siblings, 2 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-09 14:22 UTC (permalink / raw)
  To: linux-kernel; +Cc: davidsen, randy.dunlap, dada1, Valdis.Kletnieks, jesper.juhl

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

Hello collogues,

Patches make available to the user the following new per-process 
(thread) performance statistics:

    * Involuntary Context Switches
    * Voluntary Context Switches
    * Number of system calls

This data is useful for detecting hyperactivity patterns between processes.

I have attached 3 patches  perf_stat.patch, perf_stat_x86_64.patch and 
perf_stat_ppc.patch for linux-2.6.21-rc5
and corrected all notes which were before.  Do you have any objections? 
I need your opinion again.

Best regards,
Maxim Uvarov.










[-- Attachment #2: perf_stat.patch --]
[-- Type: text/plain, Size: 5368 bytes --]

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

[-- Attachment #3: perf_stat_x86_64.patch --]
[-- Type: text/plain, Size: 2671 bytes --]

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
@@ -458,6 +458,6 @@ config THREAD_PERF_STAT
 
 config THREAD_PERF_STAT_SYSC
        bool "Enable syscall counter"
-       depends on THREAD_PERF_STAT && X86_32
+       depends on THREAD_PERF_STAT && X86
        help
          This option adds a syscall counter to /proc/PID/status.
Index: linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-x86_64/thread_info.h
+++ linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
@@ -30,7 +30,9 @@ struct thread_info {
 	__u32			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;	
 	struct restart_block    restart_block;
 };
Index: linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
@@ -236,6 +236,11 @@ ENTRY(system_call)
 	movq %r10,%rcx
 	call *sys_call_table(,%rax,8)  # XXX:	 rip relative
 	movq %rax,RAX-ARGOFFSET(%rsp)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	GET_THREAD_INFO(%rcx)
+	addq $1, threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+
 /*
  * Syscall return path ending with SYSRET (fast path)
  * Has incomplete stack frame and undefined top of stack. 
@@ -319,6 +324,10 @@ tracesys:			 
 	call *sys_call_table(,%rax,8)
 1:	movq %rax,RAX-ARGOFFSET(%rsp)
 	/* Use IRET because user could have changed frame */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	GET_THREAD_INFO(%rcx)
+	addq $1, threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 		
 /* 
  * Syscall return path ending with IRET.
Index: linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
@@ -35,6 +35,9 @@ int main(void)
 	ENTRY(addr_limit);
 	ENTRY(preempt_count);
 	ENTRY(status);
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC 
+	ENTRY(sysc_cnt);
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	BLANK();
 #undef ENTRY
 #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry))

[-- Attachment #4: perf_stat_ppc.patch --]
[-- Type: text/plain, Size: 2501 bytes --]

Index: linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-powerpc/thread_info.h
+++ linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
@@ -35,6 +35,9 @@ struct thread_info {
 	int		cpu;			/* cpu we're on */
 	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 */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
Index: linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
@@ -94,6 +94,10 @@ int main(void)
 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        DEFINE(TI_SYSC_CNT, offsetof(struct thread_info, sysc_cnt)); 
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+		
 #ifdef CONFIG_PPC32
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_32.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
@@ -223,6 +223,11 @@ ret_from_syscall:
 #endif
 	mr	r6,r3
 	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	lwz r9,TI_SYSC_CNT(r12)
+	addi r9,r9,1
+	stw r9,TI_SYSC_CNT(r12)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	/* disable interrupts so current_thread_info()->flags can't change */
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)	/* doesn't include MSR_EE */
 	SYNC
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
@@ -458,6 +458,6 @@ config THREAD_PERF_STAT
 
 config THREAD_PERF_STAT_SYSC
        bool "Enable syscall counter"
-       depends on THREAD_PERF_STAT && X86
+       depends on THREAD_PERF_STAT && (X86 || PPC32)
        help
          This option adds a syscall counter to /proc/PID/status.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-09 14:22 Performance Stats: Kernel patch Maxim Uvarov
@ 2007-04-10  8:21 ` Eric Dumazet
  2007-04-11 11:59   ` Maxim Uvarov
  2007-04-15  9:47 ` Pavel Machek
  1 sibling, 1 reply; 28+ messages in thread
From: Eric Dumazet @ 2007-04-10  8:21 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

On Mon, 09 Apr 2007 18:22:22 +0400
Maxim Uvarov <muvarov@ru.mvista.com> wrote:



> --- linux-2.6.21-rc5.orig/arch/x86_64/kernel/entry.S
> +++ linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
> @@ -236,6 +236,11 @@ ENTRY(system_call)
>  	movq %r10,%rcx
>  	call *sys_call_table(,%rax,8)  # XXX:	 rip relative
>  	movq %rax,RAX-ARGOFFSET(%rsp)
> +#ifdef CONFIG_THREAD_PERF_STAT_SYSC
> +	GET_THREAD_INFO(%rcx)
> +	addq $1, threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
> +#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
> +

Please reorganize the code so that you dont duplicate GET_THREAD_INFO() stuff
You can do this for example before calling the syscall, not after.

   ja badsys
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+  incq threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
   movq %r10,%rcx
   call *sys_call_table(,%rax,8)  # XXX:    rip relative

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-10  8:21 ` Eric Dumazet
@ 2007-04-11 11:59   ` Maxim Uvarov
  2007-04-11 12:26     ` Eric Dumazet
  2007-04-11 14:15     ` Eric Dumazet
  0 siblings, 2 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-11 11:59 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

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

Eric Dumazet wrote:
[snip]

> Please reorganize the code so that you dont duplicate 
> GET_THREAD_INFO() stuff


Thanks Eric, I's really better. I have done changes. Do you have any 
others objections now?
All is in attached perf_stat.patch.

Best regards,
Maxim Uvarov.

[-- Attachment #2: perf_stat.patch --]
[-- Type: text/plain, Size: 10056 bytes --]

Patch adds Process Performance Statistics.
It make available to the user the following 
new per-process (thread) performance statistics:
   * Involuntary Context Switches
   * Voluntary Context Switches
   * Number of system calls
   
This data is useful for detecting hyperactivity 
patterns between processes.

Signed-off-by: Maxim Uvarov muvarov@ru.mvista.com

 arch/i386/kernel/asm-offsets.c    |    3 +++
 arch/i386/kernel/entry.S          |    3 +++
 arch/powerpc/kernel/asm-offsets.c |    4 ++++
 arch/powerpc/kernel/entry_32.S    |    5 +++++
 arch/powerpc/kernel/entry_64.S    |    5 +++++
 arch/x86_64/kernel/asm-offsets.c  |    3 +++
 arch/x86_64/kernel/entry.S        |    3 +++
 fs/proc/array.c                   |   17 +++++++++++++++++
 include/asm-i386/thread_info.h    |    5 +++--
 include/asm-powerpc/thread_info.h |    3 +++
 include/asm-x86_64/thread_info.h  |    4 +++-
 kernel/fork.c                     |    4 ++++
 lib/Kconfig.debug                 |   15 +++++++++++++++
 13 files changed, 71 insertions(+), 3 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 || PPC)
+       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
@@ -334,6 +334,9 @@ sysenter_past_esp:
 	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        incl    TI_sysc_cnt(%ebp)       # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
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
Index: linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
@@ -94,6 +94,10 @@ int main(void)
 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        DEFINE(TI_SYSC_CNT, offsetof(struct thread_info, sysc_cnt));
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+
 #ifdef CONFIG_PPC32
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_32.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
@@ -202,6 +202,11 @@ _GLOBAL(DoSyscall)
 	bl	do_show_syscall
 #endif /* SHOW_SYSCALLS */
 	rlwinm	r10,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	lwz r11,TI_SYSC_CNT(r10)
+	addi r11,r11,1
+	stw r11,TI_SYSC_CNT(r10)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	lwz	r11,TI_FLAGS(r10)
 	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_64.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
@@ -115,6 +115,11 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 #endif
 	clrrdi	r11,r1,THREAD_SHIFT
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	lwz r10,TI_SYSC_CNT(r11)
+	addi r10,r10,1
+	stw r10,TI_SYSC_CNT(r11)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	ld	r10,TI_FLAGS(r11)
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
Index: linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
@@ -35,6 +35,9 @@ int main(void)
 	ENTRY(addr_limit);
 	ENTRY(preempt_count);
 	ENTRY(status);
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	ENTRY(sysc_cnt);
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	BLANK();
 #undef ENTRY
 #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry))
Index: linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
@@ -229,6 +229,9 @@ ENTRY(system_call)
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	GET_THREAD_INFO(%rcx)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	addq $1, threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
Index: linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-powerpc/thread_info.h
+++ linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
@@ -35,6 +35,9 @@ struct thread_info {
 	int		cpu;			/* cpu we're on */
 	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 */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
Index: linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-x86_64/thread_info.h
+++ linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
@@ -30,7 +30,9 @@ struct thread_info {
 	__u32			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;	
 	struct restart_block    restart_block;
 };

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 11:59   ` Maxim Uvarov
@ 2007-04-11 12:26     ` Eric Dumazet
  2007-04-11 13:15       ` Maxim Uvarov
  2007-04-11 14:15     ` Eric Dumazet
  1 sibling, 1 reply; 28+ messages in thread
From: Eric Dumazet @ 2007-04-11 12:26 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

On Wed, 11 Apr 2007 15:59:16 +0400
Maxim Uvarov <muvarov@ru.mvista.com> wrote:

> Thanks Eric, I's really better. I have done changes. Do you have any 
> others objections now?
> All is in attached perf_stat.patch.

Hi Maxim

I know *nothing* about powerpc assembly, but I think there is a problem :

Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_64.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
@@ -115,6 +115,11 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 #endif
 	clrrdi	r11,r1,THREAD_SHIFT
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	lwz r10,TI_SYSC_CNT(r11)
+	addi r10,r10,1
+	stw r10,TI_SYSC_CNT(r11)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	ld	r10,TI_FLAGS(r11)
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace

sysc_cnt being an 'unsigned long', its a 64 bits long integer...
So you probably need ld/std instructions instead of lwz/stw


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 12:26     ` Eric Dumazet
@ 2007-04-11 13:15       ` Maxim Uvarov
  0 siblings, 0 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-11 13:15 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

Eric Dumazet wrote:

>
>sysc_cnt being an 'unsigned long', its a 64 bits long integer...
>So you probably need ld/std instructions instead of lwz/stw
>
>  
>
Seems you are right again :(

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 11:59   ` Maxim Uvarov
  2007-04-11 12:26     ` Eric Dumazet
@ 2007-04-11 14:15     ` Eric Dumazet
  2007-04-11 15:33       ` Bill Davidsen
  2007-04-11 15:53       ` Maxim Uvarov
  1 sibling, 2 replies; 28+ messages in thread
From: Eric Dumazet @ 2007-04-11 14:15 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

On Wed, 11 Apr 2007 15:59:16 +0400
Maxim Uvarov <muvarov@ru.mvista.com> wrote:

> Patch adds Process Performance Statistics.
> It make available to the user the following 
> new per-process (thread) performance statistics:
>    * Involuntary Context Switches
>    * Voluntary Context Switches
>    * Number of system calls
>    
> This data is useful for detecting hyperactivity 
> patterns between processes.

Your description is not very clear about the semantic of your stats.

You currently returns stats only for thread(s) (not process as you claimed)

Please check kernel/sys.c:k_getrusage() to see how getrusage() has to sum *lot* of individual fields to get precise process numbers (even counting stats for dead threads)


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 14:15     ` Eric Dumazet
@ 2007-04-11 15:33       ` Bill Davidsen
  2007-04-11 15:57         ` Maxim Uvarov
  2007-04-11 15:53       ` Maxim Uvarov
  1 sibling, 1 reply; 28+ messages in thread
From: Bill Davidsen @ 2007-04-11 15:33 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Maxim Uvarov, linux-kernel, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

Eric Dumazet wrote:
> On Wed, 11 Apr 2007 15:59:16 +0400
> Maxim Uvarov <muvarov@ru.mvista.com> wrote:
>
>   
>> Patch adds Process Performance Statistics.
>> It make available to the user the following 
>> new per-process (thread) performance statistics:
>>    * Involuntary Context Switches
>>    * Voluntary Context Switches
>>    * Number of system calls
>>    
>> This data is useful for detecting hyperactivity 
>> patterns between processes.
>>     
>
> Your description is not very clear about the semantic of your stats.
>
> You currently returns stats only for thread(s) (not process as you claimed)
>   
I'm not sure if you were confused by his use of thread in parenthesis, 
but isn't the whole point of this to see which threads are doing what? 
Or am I misreading his result as intentional?
> Please check kernel/sys.c:k_getrusage() to see how getrusage() has to sum *lot* of individual fields to get precise process numbers (even counting stats for dead threads)
>
>   
-- 
bill davidsen <davidsen@tmr.com>
  CTO TMR Associates, Inc
  Doing interesting things with small computers since 1979


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 14:15     ` Eric Dumazet
  2007-04-11 15:33       ` Bill Davidsen
@ 2007-04-11 15:53       ` Maxim Uvarov
  2007-04-11 19:22         ` Eric Dumazet
  1 sibling, 1 reply; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-11 15:53 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

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

Eric Dumazet wrote:

 >Please check kernel/sys.c:k_getrusage() to see how getrusage() has to 
sum *lot* of individual fields to get precise process numbers (even 
counting stats for dead threads)



Thanks for helping me and for this link. But it is not enough clear for 
me what do you mean at this time.  Inside of patch I am using 2 default 
counters
task_struct->nivcsw and task_struct->nvcsw. And also one new syscall 
counter. And there is only one way to increment this counter, it is from 
entry.S.

If you are speaking about locks,  in my point of view, they are not 
needed in this code. Because increment syscall counter is atomic for X86 
(just one assembly instruction) and in case with PPC (3 instructions) 
there 1) nothing wrong will not happen in any case 2) only own thread 
can increase it's syscall counter. So here should be not any race 
conditions.

I've tested this patch on x86,x86_64,and ppc_32. And I should work now 
with ppc_64 (I didn't check).
And  also updated description.

Best regards,
Maxim Uvarov.

[-- Attachment #2: perf_stat.patch --]
[-- Type: text/plain, Size: 10187 bytes --]

Patch adds Process Performance Statistics.
It make available to the user the following 
thread performance statistics:
   * Involuntary Context Switches (task_struct->nivcsw)
   * Voluntary Context Switches (task_struct->nvcsw)
   * Number of system calls (added new counter 
     thread_info->sysc_cnt)

Statistics information is available from
/proc/PID/status
   
This data is useful for detecting hyperactivity 
patterns between processes.

Signed-off-by: Maxim Uvarov muvarov@ru.mvista.com

 arch/i386/kernel/asm-offsets.c    |    3 +++
 arch/i386/kernel/entry.S          |    3 +++
 arch/powerpc/kernel/asm-offsets.c |    4 ++++
 arch/powerpc/kernel/entry_32.S    |    5 +++++
 arch/powerpc/kernel/entry_64.S    |    5 +++++
 arch/x86_64/kernel/asm-offsets.c  |    3 +++
 arch/x86_64/kernel/entry.S        |    3 +++
 fs/proc/array.c                   |   17 +++++++++++++++++
 include/asm-i386/thread_info.h    |    5 +++--
 include/asm-powerpc/thread_info.h |    3 +++
 include/asm-x86_64/thread_info.h  |    4 +++-
 kernel/fork.c                     |    4 ++++
 lib/Kconfig.debug                 |   15 +++++++++++++++
 13 files changed, 71 insertions(+), 3 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 || PPC)
+       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
@@ -334,6 +334,9 @@ sysenter_past_esp:
 	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        incl    TI_sysc_cnt(%ebp)       # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
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
Index: linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
@@ -94,6 +94,10 @@ int main(void)
 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        DEFINE(TI_SYSC_CNT, offsetof(struct thread_info, sysc_cnt));
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+
 #ifdef CONFIG_PPC32
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_32.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
@@ -202,6 +202,11 @@ _GLOBAL(DoSyscall)
 	bl	do_show_syscall
 #endif /* SHOW_SYSCALLS */
 	rlwinm	r10,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	lwz r11,TI_SYSC_CNT(r10)
+	addi r11,r11,1
+	stw r11,TI_SYSC_CNT(r10)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	lwz	r11,TI_FLAGS(r10)
 	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_64.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
@@ -115,6 +115,11 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 #endif
 	clrrdi	r11,r1,THREAD_SHIFT
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	ld r10,TI_SYSC_CNT(r11)
+	addi r10,r10,1
+	std r10,TI_SYSC_CNT(r11)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	ld	r10,TI_FLAGS(r11)
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
Index: linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
@@ -35,6 +35,9 @@ int main(void)
 	ENTRY(addr_limit);
 	ENTRY(preempt_count);
 	ENTRY(status);
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	ENTRY(sysc_cnt);
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	BLANK();
 #undef ENTRY
 #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry))
Index: linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
@@ -229,6 +229,9 @@ ENTRY(system_call)
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	GET_THREAD_INFO(%rcx)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	addq $1, threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
Index: linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-powerpc/thread_info.h
+++ linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
@@ -35,6 +35,9 @@ struct thread_info {
 	int		cpu;			/* cpu we're on */
 	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 */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
Index: linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-x86_64/thread_info.h
+++ linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
@@ -30,7 +30,9 @@ struct thread_info {
 	__u32			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;	
 	struct restart_block    restart_block;
 };

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 15:33       ` Bill Davidsen
@ 2007-04-11 15:57         ` Maxim Uvarov
  0 siblings, 0 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-11 15:57 UTC (permalink / raw)
  To: Bill Davidsen
  Cc: Eric Dumazet, linux-kernel, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

Bill Davidsen wrote:

> [snip]
>
>>
>> Your description is not very clear about the semantic of your stats.
>>
>> You currently returns stats only for thread(s) (not process as you 
>> claimed)
>>   
>
> I'm not sure if you were confused by his use of thread in parenthesis, 
> but isn't the whole point of this to see which threads are doing what? 
> Or am I misreading his result as intentional?

Yes the point is to get some statistics from thread in other words to 
see which threads are doing what.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 15:53       ` Maxim Uvarov
@ 2007-04-11 19:22         ` Eric Dumazet
  2007-04-12 13:46           ` Maxim Uvarov
  0 siblings, 1 reply; 28+ messages in thread
From: Eric Dumazet @ 2007-04-11 19:22 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

Maxim Uvarov a écrit :
> Eric Dumazet wrote:
> 
>  >Please check kernel/sys.c:k_getrusage() to see how getrusage() has to 
> sum *lot* of individual fields to get precise process numbers (even 
> counting stats for dead threads)
> 
> 
> 
> Thanks for helping me and for this link. But it is not enough clear for 
> me what do you mean at this time.  Inside of patch I am using 2 default 
> counters
> task_struct->nivcsw and task_struct->nvcsw. And also one new syscall 
> counter. And there is only one way to increment this counter, it is from 
> entry.S.
> 
> If you are speaking about locks,  in my point of view, they are not 
> needed in this code. Because increment syscall counter is atomic for X86 
> (just one assembly instruction) and in case with PPC (3 instructions) 
> there 1) nothing wrong will not happen in any case 2) only own thread 
> can increase it's syscall counter. So here should be not any race 
> conditions.

I was not speaking about locks.

> 
> I've tested this patch on x86,x86_64,and ppc_32. And I should work now 
> with ppc_64 (I didn't check).
> And  also updated description.
> 
> Best regards,
> Maxim Uvarov.
> 
> 
> ------------------------------------------------------------------------
> 
> Patch adds Process Performance Statistics.
> It make available to the user the following 
> thread performance statistics:
>    * Involuntary Context Switches (task_struct->nivcsw)
>    * Voluntary Context Switches (task_struct->nvcsw)
>    * Number of system calls (added new counter 
>      thread_info->sysc_cnt)
> 
> Statistics information is available from
> /proc/PID/status
>    
> This data is useful for detecting hyperactivity 
> patterns between processes.
> 

What I meant is : You falsely speak of 'PROCESS performance statistics'.

Your implementation only cares about threads, not processes.
There is a slight difference, that getrusage() can do.

So if you do "cat /proc/PID/status", you'll get counters not for the PROCESS, 
only the main thread of the process.

If you want an analogy, imagine a "ps aux" that doesnt show the cpu time of 
all threads of a process, but only the cpu time of the main thread. Quite 
meaningless isnt it ?

So either :

1) You change all your description to mention 'thread' instead of 'process'.

2) You change your implementation to match your claim.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-11 19:22         ` Eric Dumazet
@ 2007-04-12 13:46           ` Maxim Uvarov
  0 siblings, 0 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-12 13:46 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: linux-kernel, davidsen, randy.dunlap, Valdis.Kletnieks,
	jesper.juhl

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

Eric Dumazet wrote:

> [snip]
> What I meant is : You falsely speak of 'PROCESS performance statistics'.
>
> Your implementation only cares about threads, not processes.
> There is a slight difference, that getrusage() can do.
>
> So if you do "cat /proc/PID/status", you'll get counters not for the 
> PROCESS, only the main thread of the process.
>
> If you want an analogy, imagine a "ps aux" that doesnt show the cpu 
> time of all threads of a process, but only the cpu time of the main 
> thread. Quite meaningless isnt it ?
>
> So either :
>
> 1) You change all your description to mention 'thread' instead of 
> 'process'.
>
> 2) You change your implementation to match your claim.


Thanks again Eric, very useful notes. 

Important information is per-thread counters. So I changed only description.
Seems no issues now?

Patch is attached.

Best regards,
Maxim.

[-- Attachment #2: perf_stat.patch --]
[-- Type: text/plain, Size: 10124 bytes --]

Patch makes available to the user the following 
thread performance statistics:
   * Involuntary Context Switches (task_struct->nivcsw)
   * Voluntary Context Switches (task_struct->nvcsw)
   * Number of system calls (added new counter 
     thread_info->sysc_cnt)

Statistics information is available from
/proc/PID/status
   
This data is useful for detecting hyperactivity 
patterns between processes.

Signed-off-by: Maxim Uvarov muvarov@ru.mvista.com

 arch/i386/kernel/asm-offsets.c    |    3 +++
 arch/i386/kernel/entry.S          |    3 +++
 arch/powerpc/kernel/asm-offsets.c |    4 ++++
 arch/powerpc/kernel/entry_32.S    |    5 +++++
 arch/powerpc/kernel/entry_64.S    |    5 +++++
 arch/x86_64/kernel/asm-offsets.c  |    3 +++
 arch/x86_64/kernel/entry.S        |    3 +++
 fs/proc/array.c                   |   17 +++++++++++++++++
 include/asm-i386/thread_info.h    |    5 +++--
 include/asm-powerpc/thread_info.h |    3 +++
 include/asm-x86_64/thread_info.h  |    4 +++-
 kernel/fork.c                     |    4 ++++
 lib/Kconfig.debug                 |   15 +++++++++++++++
 13 files changed, 71 insertions(+), 3 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 "Thread performance statistics"
+       help
+         Make available to the user the following per-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 || PPC)
+       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
@@ -334,6 +334,9 @@ sysenter_past_esp:
 	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        incl    TI_sysc_cnt(%ebp)       # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
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
Index: linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/powerpc/kernel/asm-offsets.c
@@ -94,6 +94,10 @@ int main(void)
 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+        DEFINE(TI_SYSC_CNT, offsetof(struct thread_info, sysc_cnt));
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
+
 #ifdef CONFIG_PPC32
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_32.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_32.S
@@ -202,6 +202,11 @@ _GLOBAL(DoSyscall)
 	bl	do_show_syscall
 #endif /* SHOW_SYSCALLS */
 	rlwinm	r10,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	lwz r11,TI_SYSC_CNT(r10)
+	addi r11,r11,1
+	stw r11,TI_SYSC_CNT(r10)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	lwz	r11,TI_FLAGS(r10)
 	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
Index: linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/powerpc/kernel/entry_64.S
+++ linux-2.6.21-rc5/arch/powerpc/kernel/entry_64.S
@@ -115,6 +115,11 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 #endif
 	clrrdi	r11,r1,THREAD_SHIFT
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	ld r10,TI_SYSC_CNT(r11)
+	addi r10,r10,1
+	std r10,TI_SYSC_CNT(r11)
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	ld	r10,TI_FLAGS(r11)
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
Index: linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/asm-offsets.c
+++ linux-2.6.21-rc5/arch/x86_64/kernel/asm-offsets.c
@@ -35,6 +35,9 @@ int main(void)
 	ENTRY(addr_limit);
 	ENTRY(preempt_count);
 	ENTRY(status);
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	ENTRY(sysc_cnt);
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	BLANK();
 #undef ENTRY
 #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry))
Index: linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
===================================================================
--- linux-2.6.21-rc5.orig/arch/x86_64/kernel/entry.S
+++ linux-2.6.21-rc5/arch/x86_64/kernel/entry.S
@@ -229,6 +229,9 @@ ENTRY(system_call)
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	GET_THREAD_INFO(%rcx)
+#ifdef CONFIG_THREAD_PERF_STAT_SYSC
+	addq $1, threadinfo_sysc_cnt(%rcx)   # Increment syscalls counter
+#endif /* CONFIG_THREAD_PERF_STAT_SYSC */
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
Index: linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-powerpc/thread_info.h
+++ linux-2.6.21-rc5/include/asm-powerpc/thread_info.h
@@ -35,6 +35,9 @@ struct thread_info {
 	int		cpu;			/* cpu we're on */
 	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 */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
Index: linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-x86_64/thread_info.h
+++ linux-2.6.21-rc5/include/asm-x86_64/thread_info.h
@@ -30,7 +30,9 @@ struct thread_info {
 	__u32			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;	
 	struct restart_block    restart_block;
 };

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-09 14:22 Performance Stats: Kernel patch Maxim Uvarov
  2007-04-10  8:21 ` Eric Dumazet
@ 2007-04-15  9:47 ` Pavel Machek
  2007-04-15 10:21   ` William Lee Irwin III
  1 sibling, 1 reply; 28+ messages in thread
From: Pavel Machek @ 2007-04-15  9:47 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: linux-kernel, davidsen, randy.dunlap, dada1, Valdis.Kletnieks,
	jesper.juhl

Hi!

> +       return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
> +                           "Nivcsw:\t%lu\n",
> +                           p->nvcsw,
> +                           p->nivcsw);

We don't encrypt variable names like this.
							Pavel


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-15  9:47 ` Pavel Machek
@ 2007-04-15 10:21   ` William Lee Irwin III
  2007-04-15 20:10     ` Pavel Machek
  0 siblings, 1 reply; 28+ messages in thread
From: William Lee Irwin III @ 2007-04-15 10:21 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Maxim Uvarov, linux-kernel, davidsen, randy.dunlap, dada1,
	Valdis.Kletnieks, jesper.juhl

At some point in the past, someone's attribution was stripped from:
>> +       return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
>> +                           "Nivcsw:\t%lu\n",
>> +                           p->nvcsw,
>> +                           p->nivcsw);

On Sun, Apr 15, 2007 at 09:47:07AM +0000, Pavel Machek wrote:
> We don't encrypt variable names like this.

nvcsw and nivcsw are conventional variable names for these quantities.


-- wli

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-15 10:21   ` William Lee Irwin III
@ 2007-04-15 20:10     ` Pavel Machek
  2007-04-16  1:04       ` William Lee Irwin III
  0 siblings, 1 reply; 28+ messages in thread
From: Pavel Machek @ 2007-04-15 20:10 UTC (permalink / raw)
  To: William Lee Irwin III
  Cc: Maxim Uvarov, linux-kernel, davidsen, randy.dunlap, dada1,
	Valdis.Kletnieks, jesper.juhl

Hi!

On Sun 2007-04-15 03:21:57, William Lee Irwin III wrote:
> At some point in the past, someone's attribution was stripped from:

Maxim's.

> >> +       return buffer + sprintf(buffer, "Nvcsw:\t%lu\n"
> >> +                           "Nivcsw:\t%lu\n",
> >> +                           p->nvcsw,
> >> +                           p->nivcsw);
> 
> On Sun, Apr 15, 2007 at 09:47:07AM +0000, Pavel Machek wrote:
> > We don't encrypt variable names like this.
> 
> nvcsw and nivcsw are conventional variable names for these quantities.

I can't decipher them and would not want users see them in /proc.


Would nonvoluntary_ctxt_switch be that much worse?

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-15 20:10     ` Pavel Machek
@ 2007-04-16  1:04       ` William Lee Irwin III
  2007-04-16  9:24         ` Maxim Uvarov
  0 siblings, 1 reply; 28+ messages in thread
From: William Lee Irwin III @ 2007-04-16  1:04 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Maxim Uvarov, linux-kernel, davidsen, randy.dunlap, dada1,
	Valdis.Kletnieks, jesper.juhl

On Sun 2007-04-15 03:21:57, William Lee Irwin III wrote:
>> nvcsw and nivcsw are conventional variable names for these quantities.

On Sun, Apr 15, 2007 at 08:10:24PM +0000, Pavel Machek wrote:
> I can't decipher them and would not want users see them in /proc.
> Would nonvoluntary_ctxt_switch be that much worse?

I'm not too attached to a particular name. I just think that the
traditional counter names should pass readability/etc. criteria on
account of the very strong historical precedent. I'd consider more
verbose affairs for the sake of putative legibility as equivalent
in quality. Maybe that means others voting for the more verbose
names should result in an aggregate decision in favor of verbosity.


-- wli

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Performance Stats: Kernel patch
  2007-04-16  1:04       ` William Lee Irwin III
@ 2007-04-16  9:24         ` Maxim Uvarov
  0 siblings, 0 replies; 28+ messages in thread
From: Maxim Uvarov @ 2007-04-16  9:24 UTC (permalink / raw)
  To: William Lee Irwin III
  Cc: Pavel Machek, linux-kernel, davidsen, randy.dunlap, dada1,
	Valdis.Kletnieks, jesper.juhl

William Lee Irwin III wrote:

>On Sun 2007-04-15 03:21:57, William Lee Irwin III wrote:
>  
>
>>>nvcsw and nivcsw are conventional variable names for these quantities.
>>>      
>>>
>
>On Sun, Apr 15, 2007 at 08:10:24PM +0000, Pavel Machek wrote:
>  
>
>>I can't decipher them and would not want users see them in /proc.
>>Would nonvoluntary_ctxt_switch be that much worse?
>>    
>>
>
>I'm not too attached to a particular name. I just think that the
>traditional counter names should pass readability/etc. criteria on
>account of the very strong historical precedent. I'd consider more
>verbose affairs for the sake of putative legibility as equivalent
>in quality. Maybe that means others voting for the more verbose
>names should result in an aggregate decision in favor of verbosity.
>
>
>-- wli
>  
>
The standard /proc output is:
root@192.168.3.2:~# cat /proc/$$/status
Name:   bash
State:  S (sleeping)
SleepAVG:       88%
Tgid:   836
Pid:    836
PPid:   1
TracerPid:      0
Uid:    0       0       0       0
Gid:    0       0       0       0
FDSize: 256
Groups: 0 1 2 4
VmPeak:     2360 kB
VmSize:     2360 kB
VmLck:         0 kB
VmHWM:      1400 kB
VmRSS:      1400 kB
VmData:      196 kB
VmStk:        88 kB
VmExe:       564 kB
VmLib:      1412 kB
VmPTE:        12 kB
Threads:        1
SigQ:   0/1024
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000010000
SigIgn: 0000000000384004
SigCgt: 000000004b813efb
CapInh: 0000000000000000
CapPrm: 00000000fffffeff
CapEff: 00000000fffffeff

I can't say that "Nvcsw" and "Nivcsw" is something less verbose as 
output above.
It is more usual  so it is more clear for you. But if you need this counters
you should know what are they and how to use them.

As for me "nonvoluntary_ctxt_switch" and "voluntary_ctxt_switch" is more 
verbose,
and it is not big deal to change names. But I think that information about
this counters and verbose name should be in user space tools, like ps.



^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2007-04-16  9:24 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-09 14:22 Performance Stats: Kernel patch Maxim Uvarov
2007-04-10  8:21 ` Eric Dumazet
2007-04-11 11:59   ` Maxim Uvarov
2007-04-11 12:26     ` Eric Dumazet
2007-04-11 13:15       ` Maxim Uvarov
2007-04-11 14:15     ` Eric Dumazet
2007-04-11 15:33       ` Bill Davidsen
2007-04-11 15:57         ` Maxim Uvarov
2007-04-11 15:53       ` Maxim Uvarov
2007-04-11 19:22         ` Eric Dumazet
2007-04-12 13:46           ` Maxim Uvarov
2007-04-15  9:47 ` Pavel Machek
2007-04-15 10:21   ` William Lee Irwin III
2007-04-15 20:10     ` Pavel Machek
2007-04-16  1:04       ` William Lee Irwin III
2007-04-16  9:24         ` Maxim Uvarov
  -- strict thread matches above, loose matches on Subject: below --
2007-04-03 12:54 Maxim Uvarov
2007-04-03 23:01 ` Valdis.Kletnieks
2007-04-04 13:15   ` Maxim Uvarov
2007-04-04 13:46     ` Eric Dumazet
2007-04-04 16:52       ` Maxim Uvarov
2007-04-04 18:04         ` Eric Dumazet
2007-04-04 21:54       ` Valdis.Kletnieks
2007-04-04 13:59     ` Jesper Juhl
2007-04-04 21:50     ` Valdis.Kletnieks
2007-04-04 22:03       ` Randy Dunlap
2007-04-06 21:50       ` Bill Davidsen
2007-04-08 16:58     ` Pavel Machek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox