2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
/*
* Copyright ( c ) 1991 , 1992 Paul Kranenburg < pk @ cs . few . eur . nl >
* Copyright ( c ) 1993 Branko Lankester < branko @ hacktic . nl >
* Copyright ( c ) 1993 , 1994 , 1995 , 1996 Rick Sladkey < jrs @ world . std . com >
* Copyright ( c ) 1996 - 1999 Wichert Akkerman < wichert @ cistron . nl >
* Copyright ( c ) 1999 IBM Deutschland Entwicklung GmbH , IBM Corporation
* Linux for s390 port by D . J . Barrow
* < barrow_dj @ mail . yahoo . com , djbarrow @ de . ibm . com >
* Copyright ( c ) 2004 Roland McGrath < roland @ redhat . com >
* Copyright ( c ) 2006 Dmitry V . Levin < ldv @ altlinux . org >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* $ Id $
*/
# include "defs.h"
struct call_counts {
struct timeval time ;
int calls , errors ;
} ;
static struct call_counts * countv [ SUPPORTED_PERSONALITIES ] ;
# define counts (countv[current_personality])
static struct timeval shortest = { 1000000 , 0 } ;
2011-08-21 19:47:40 +04:00
void
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
count_syscall ( struct tcb * tcp , struct timeval * tv )
{
2011-08-25 03:13:43 +04:00
if ( ! SCNO_IN_RANGE ( tcp - > scno ) )
2011-08-21 19:47:40 +04:00
return ;
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
2011-06-22 16:32:43 +04:00
if ( ! counts ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
counts = calloc ( nsyscalls , sizeof ( * counts ) ) ;
2011-06-22 16:32:43 +04:00
if ( ! counts ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
fprintf ( stderr ,
" strace: out of memory for call counts \n " ) ;
exit ( 1 ) ;
}
}
counts [ tcp - > scno ] . calls + + ;
if ( tcp - > u_error )
counts [ tcp - > scno ] . errors + + ;
tv_sub ( tv , tv , & tcp - > etime ) ;
# ifdef LINUX
2011-06-22 16:32:43 +04:00
if ( tv_cmp ( tv , & tcp - > dtime ) > 0 ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
static struct timeval one_tick ;
2011-06-22 16:32:43 +04:00
if ( one_tick . tv_usec = = 0 ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
/* Initialize it. */
struct itimerval it ;
memset ( & it , 0 , sizeof it ) ;
it . it_interval . tv_usec = 1 ;
setitimer ( ITIMER_REAL , & it , NULL ) ;
getitimer ( ITIMER_REAL , & it ) ;
one_tick = it . it_interval ;
}
if ( tv_nz ( & tcp - > dtime ) )
* tv = tcp - > dtime ;
2011-06-22 16:32:43 +04:00
else if ( tv_cmp ( tv , & one_tick ) > 0 ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
if ( tv_cmp ( & shortest , & one_tick ) < 0 )
* tv = shortest ;
else
* tv = one_tick ;
}
}
# endif /* LINUX */
if ( tv_cmp ( tv , & shortest ) < 0 )
shortest = * tv ;
tv_add ( & counts [ tcp - > scno ] . time , & counts [ tcp - > scno ] . time , tv ) ;
}
static int
time_cmp ( void * a , void * b )
{
return - tv_cmp ( & counts [ * ( ( int * ) a ) ] . time ,
& counts [ * ( ( int * ) b ) ] . time ) ;
}
static int
syscall_cmp ( void * a , void * b )
{
return strcmp ( sysent [ * ( ( int * ) a ) ] . sys_name ,
sysent [ * ( ( int * ) b ) ] . sys_name ) ;
}
static int
count_cmp ( void * a , void * b )
{
int m = counts [ * ( ( int * ) a ) ] . calls ;
int n = counts [ * ( ( int * ) b ) ] . calls ;
return ( m < n ) ? 1 : ( m > n ) ? - 1 : 0 ;
}
static int ( * sortfun ) ( ) ;
static struct timeval overhead = { - 1 , - 1 } ;
void
2010-09-07 02:08:24 +04:00
set_sortby ( const char * sortby )
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
{
if ( strcmp ( sortby , " time " ) = = 0 )
sortfun = time_cmp ;
else if ( strcmp ( sortby , " calls " ) = = 0 )
sortfun = count_cmp ;
else if ( strcmp ( sortby , " name " ) = = 0 )
sortfun = syscall_cmp ;
else if ( strcmp ( sortby , " nothing " ) = = 0 )
sortfun = NULL ;
2011-06-22 16:32:43 +04:00
else {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
fprintf ( stderr , " invalid sortby: `%s' \n " , sortby ) ;
exit ( 1 ) ;
}
}
void set_overhead ( int n )
{
overhead . tv_sec = n / 1000000 ;
overhead . tv_usec = n % 1000000 ;
}
static void
call_summary_pers ( FILE * outf )
{
int i , j ;
int call_cum , error_cum ;
struct timeval tv_cum , dtv ;
double percent ;
2010-09-07 02:08:24 +04:00
const char * dashes = " ------------------------- " ;
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
char error_str [ 16 ] ;
int * sorted_count = calloc ( sizeof ( int ) , nsyscalls ) ;
2011-06-22 16:32:43 +04:00
if ( ! sorted_count ) {
2008-04-19 18:12:49 +04:00
fprintf ( stderr , " strace: out of memory for call summary \n " ) ;
return ;
}
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
call_cum = error_cum = tv_cum . tv_sec = tv_cum . tv_usec = 0 ;
2011-06-22 16:32:43 +04:00
if ( overhead . tv_sec = = - 1 ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
tv_mul ( & overhead , & shortest , 8 ) ;
tv_div ( & overhead , & overhead , 10 ) ;
}
2011-06-22 16:32:43 +04:00
for ( i = 0 ; i < nsyscalls ; i + + ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
sorted_count [ i ] = i ;
if ( counts = = NULL | | counts [ i ] . calls = = 0 )
continue ;
tv_mul ( & dtv , & overhead , counts [ i ] . calls ) ;
tv_sub ( & counts [ i ] . time , & counts [ i ] . time , & dtv ) ;
call_cum + = counts [ i ] . calls ;
error_cum + = counts [ i ] . errors ;
tv_add ( & tv_cum , & tv_cum , & counts [ i ] . time ) ;
}
if ( counts & & sortfun )
qsort ( ( void * ) sorted_count , nsyscalls , sizeof ( int ) , sortfun ) ;
fprintf ( outf , " %6.6s %11.11s %11.11s %9.9s %9.9s %s \n " ,
" % time " , " seconds " , " usecs/call " ,
" calls " , " errors " , " syscall " ) ;
fprintf ( outf , " %6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s \n " ,
dashes , dashes , dashes , dashes , dashes , dashes ) ;
2011-06-22 16:32:43 +04:00
if ( counts ) {
for ( i = 0 ; i < nsyscalls ; i + + ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
j = sorted_count [ i ] ;
if ( counts [ j ] . calls = = 0 )
continue ;
tv_div ( & dtv , & counts [ j ] . time , counts [ j ] . calls ) ;
if ( counts [ j ] . errors )
sprintf ( error_str , " %d " , counts [ j ] . errors ) ;
else
error_str [ 0 ] = ' \0 ' ;
percent = ( 100.0 * tv_float ( & counts [ j ] . time )
/ tv_float ( & tv_cum ) ) ;
2007-07-11 13:04:23 +04:00
fprintf ( outf , " %6.2f %11.6f %11ld %9d %9.9s %s \n " ,
percent , tv_float ( & counts [ j ] . time ) ,
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
( long ) 1000000 * dtv . tv_sec + dtv . tv_usec ,
counts [ j ] . calls ,
error_str , sysent [ j ] . sys_name ) ;
}
}
free ( sorted_count ) ;
fprintf ( outf , " %6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s \n " ,
dashes , dashes , dashes , dashes , dashes , dashes ) ;
if ( error_cum )
sprintf ( error_str , " %d " , error_cum ) ;
else
error_str [ 0 ] = ' \0 ' ;
2007-07-11 13:04:23 +04:00
fprintf ( outf , " %6.6s %11.6f %11.11s %9d %9.9s %s \n " ,
" 100.00 " , tv_float ( & tv_cum ) , " " ,
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
call_cum , error_str , " total " ) ;
}
void
call_summary ( FILE * outf )
{
2011-06-22 16:32:43 +04:00
int i , old_pers = current_personality ;
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
2011-06-22 16:32:43 +04:00
for ( i = 0 ; i < SUPPORTED_PERSONALITIES ; + + i ) {
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
if ( ! countv [ i ] )
continue ;
if ( current_personality ! = i )
set_personality ( i ) ;
if ( i )
fprintf ( outf ,
" System call usage summary for %u bit mode: \n " ,
personality_wordsize [ current_personality ] * 8 ) ;
call_summary_pers ( outf ) ;
}
if ( old_pers ! = current_personality )
set_personality ( old_pers ) ;
}