add more spacing
[personal-kdebase.git] / workspace / kwin / tools / xreply / xreply.c
blob9b6700b4b73ccaddaa875ad80c304f8c558f7818
1 /*
3 LD_PRELOAD library that gives statistic on number of roundtrips in an application.
5 $XREPLY_BACKTRACE defines whether and how backtraces will be printed for every
6 roundtrip. If not set, only total number of roundtrips is printed after the process
7 exits. If set to a number, backtrace for every roundtrip will be printed, and the
8 backtraces will be as deep as the given number. If set to C<number> (e.g. C10),
9 the backtraces will be "compressed" - every backtrace will be printed only once
10 after the process exits, together with number of times it occurred.
14 #define _GNU_SOURCE
15 #include <dlfcn.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <execinfo.h>
21 #include <assert.h>
22 #include <X11/Xlibint.h>
24 /* Since these symbols are weak, the apps can provide their own, and therefore
25 e.g. temporarily suspend counting of roundtrips. At least theoretically,
26 I haven't really tried it.
28 __attribute((weak)) long ___xreply_reply_count = 0;
29 __attribute((weak)) int ___xreply_reply_enabled = 1;
31 #define MAX_BACKTRACES 1024
33 extern long ___xreply_reply_count;
34 extern int ___xreply_reply_enabled;
36 typedef Status (*xreply_ptr_t)(Display*,xReply*,int,Bool);
38 static xreply_ptr_t xreply_ptr = NULL;
39 static int xreply_backtrace_set = 0;
40 static int xreply_backtrace_type = 0;
42 struct xreply_struct
44 char* key;
45 char* text;
46 int count;
48 static struct xreply_struct backtraces[ MAX_BACKTRACES ];
49 static int backtraces_size = 0;
51 static int xreply_compare( const void* left, const void* right )
53 int left_count = ((struct xreply_struct*)left)->count;
54 int right_count = ((struct xreply_struct*)right)->count;
55 return right_count - left_count;
58 static void xreply_print(void)
60 char tmp[ 1024 ];
61 int fd;
62 fd = open( "/proc/self/cmdline", O_RDONLY );
63 if( fd >= 0 )
65 read( fd, tmp, 1024 );
66 tmp[ 1023 ] = '\0';
67 close( fd );
69 fprintf( stderr, "XREPLY (%d : %s): %ld\n", getpid(), tmp, ___xreply_reply_count );
70 if( xreply_backtrace_type < 0 )
72 int i;
73 qsort( backtraces, backtraces_size, sizeof( struct xreply_struct ), xreply_compare );
74 for( i = 0;
75 i < backtraces_size;
76 ++i )
77 fprintf( stderr, "%d:%s\n\n", backtraces[ i ].count, backtraces[ i ].text );
81 static void xreply_backtrace()
83 void* trace[256];
84 int n = backtrace(trace, 256);
85 char** strings = backtrace_symbols (trace, n);
87 if( xreply_backtrace_type > 0 )
89 fprintf( stderr, "%ld [\n", ___xreply_reply_count );
90 if( n > xreply_backtrace_type )
91 n = xreply_backtrace_type;
92 int i;
93 for( i = 0;
94 i < n;
95 ++i )
96 fprintf( stderr, "%d: %s\n", i, strings[ i ] );
97 fprintf( stderr, "]\n" );
99 else
101 char stack[ 256 * 20 ];
102 int pos = 0;
103 int i;
104 stack[ 0 ] = '\0';
105 if( n > -xreply_backtrace_type )
106 n = -xreply_backtrace_type;
107 for( i = 0;
108 i < n;
109 ++i )
111 const char* start = strrchr( strings[ i ], '[' );
112 if( start == NULL )
113 assert( !"No [ in address." );
114 long addr;
115 if( sscanf( start + 1, "0x%lx", &addr ) != 1 )
116 assert( !"Failed to parse address." );
117 if( sizeof( void* ) == 4 )
119 sprintf( stack + pos, "0x%8lx", addr );
120 pos += 10;
122 else if( sizeof( void* ) == 8 )
124 sprintf( stack + pos, "0x%16lx", addr );
125 pos += 18;
127 else
128 assert( !"Unknown sizeof( void* )." );
130 for( i = 0;
131 i < backtraces_size;
132 ++i )
133 if( strcmp( backtraces[ i ].key, stack ) == 0 )
135 ++backtraces[ i ].count;
136 break;
138 if( i == backtraces_size )
140 int stack_text_size = 10;
141 char* stack_text;
142 char* stack_text_pos;
143 for( i = 0;
144 i < n;
145 ++i )
146 stack_text_size += strlen( strings[ i ] ) + 5;
147 stack_text = stack_text_pos = malloc( stack_text_size );
148 for( i = 0;
149 i < n;
150 ++i )
152 stack_text_pos = stpcpy( stack_text_pos, "\n" );
153 stack_text_pos = stpcpy( stack_text_pos, strings[ i ] );
155 backtraces[ backtraces_size ].key = strdup( stack );
156 backtraces[ backtraces_size ].text = stack_text;
157 backtraces[ backtraces_size ].count = 1;
158 ++backtraces_size;
159 if( backtraces_size >= MAX_BACKTRACES )
160 assert( !"MAX_BACKTRACES reached." );
163 free (strings);
166 Status
167 _XReply (dpy, rep, extra, discard)
168 register Display *dpy;
169 register xReply *rep;
170 int extra; /* number of 32-bit words expected after the reply */
171 Bool discard; /* should I discard data following "extra" words? */
173 if( ___xreply_reply_enabled )
174 ++___xreply_reply_count;
175 if( xreply_backtrace_set == 0 )
177 if( getenv( "XREPLY_BACKTRACE" ) != NULL )
178 { // C<number> - compress backtraces, saved as negative value in xreply_backtrace_type
179 if( getenv( "XREPLY_BACKTRACE" )[ 0 ] == 'C' )
180 xreply_backtrace_type = -atoi( getenv( "XREPLY_BACKTRACE" ) + 1 );
181 else // <number> - print the backtrace every time
182 xreply_backtrace_type = atoi( getenv( "XREPLY_BACKTRACE" ));
184 else
185 xreply_backtrace_type = 0;
187 if( xreply_backtrace_type != 0 )
188 xreply_backtrace();
189 if( xreply_ptr == NULL )
191 xreply_ptr = (xreply_ptr_t)dlsym( RTLD_NEXT, "_XReply" );
192 if( xreply_ptr == NULL )
193 assert( !"dlsym() failed." );
194 atexit( xreply_print );
196 return xreply_ptr( dpy, rep, extra, discard );