~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/tools/xreply/xreply.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
 LD_PRELOAD library that gives statistic on number of roundtrips in an application.
 
4
 
 
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.
 
11
 
 
12
*/
 
13
 
 
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>
 
23
 
 
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.
 
27
*/
 
28
__attribute((weak)) long ___xreply_reply_count = 0;
 
29
__attribute((weak)) int ___xreply_reply_enabled = 1;
 
30
 
 
31
#define MAX_BACKTRACES 1024
 
32
 
 
33
extern long ___xreply_reply_count;
 
34
extern int ___xreply_reply_enabled;
 
35
 
 
36
typedef Status(*xreply_ptr_t)(Display*, xReply*, int, Bool);
 
37
 
 
38
static xreply_ptr_t xreply_ptr = NULL;
 
39
static int xreply_backtrace_set = 0;
 
40
static int xreply_backtrace_type = 0;
 
41
 
 
42
struct xreply_struct {
 
43
    char* key;
 
44
    char* text;
 
45
    int count;
 
46
};
 
47
static struct xreply_struct backtraces[ MAX_BACKTRACES ];
 
48
static int backtraces_size = 0;
 
49
 
 
50
static int xreply_compare(const void* left, const void* right)
 
51
{
 
52
    int left_count = ((struct xreply_struct*)left)->count;
 
53
    int right_count = ((struct xreply_struct*)right)->count;
 
54
    return right_count - left_count;
 
55
}
 
56
 
 
57
static void xreply_print(void)
 
58
{
 
59
    char tmp[ 1024 ];
 
60
    int fd;
 
61
    fd = open("/proc/self/cmdline", O_RDONLY);
 
62
    if(fd >= 0) {
 
63
        read(fd, tmp, 1024);
 
64
        tmp[ 1023 ] = '\0';
 
65
        close(fd);
 
66
    }
 
67
    fprintf(stderr, "XREPLY (%d : %s): %ld\n", getpid(), tmp, ___xreply_reply_count);
 
68
    if(xreply_backtrace_type < 0) {
 
69
        int i;
 
70
        qsort(backtraces, backtraces_size, sizeof(struct xreply_struct), xreply_compare);
 
71
        for(i = 0;
 
72
                i < backtraces_size;
 
73
                ++i)
 
74
            fprintf(stderr, "%d:%s\n\n", backtraces[ i ].count, backtraces[ i ].text);
 
75
    }
 
76
}
 
77
 
 
78
static void xreply_backtrace()
 
79
{
 
80
    void* trace[256];
 
81
    int n = backtrace(trace, 256);
 
82
    char** strings = backtrace_symbols(trace, n);
 
83
 
 
84
    if(xreply_backtrace_type > 0) {
 
85
        fprintf(stderr, "%ld [\n", ___xreply_reply_count);
 
86
        if(n > xreply_backtrace_type)
 
87
            n = xreply_backtrace_type;
 
88
        int i;
 
89
        for(i = 0;
 
90
                i < n;
 
91
                ++i)
 
92
            fprintf(stderr, "%d: %s\n", i, strings[ i ]);
 
93
        fprintf(stderr, "]\n");
 
94
    } else {
 
95
        char stack[ 256 * 20 ];
 
96
        int pos = 0;
 
97
        int i;
 
98
        stack[ 0 ] = '\0';
 
99
        if(n > -xreply_backtrace_type)
 
100
            n = -xreply_backtrace_type;
 
101
        for(i = 0;
 
102
                i < n;
 
103
                ++i) {
 
104
            const char* start = strrchr(strings[ i ], '[');
 
105
            if(start == NULL)
 
106
                assert(!"No [ in address.");
 
107
            long addr;
 
108
            if(sscanf(start + 1, "0x%lx", &addr) != 1)
 
109
                assert(!"Failed to parse address.");
 
110
            if(sizeof(void*) == 4) {
 
111
                sprintf(stack + pos, "0x%8lx", addr);
 
112
                pos += 10;
 
113
            } else if(sizeof(void*) == 8) {
 
114
                sprintf(stack + pos, "0x%16lx", addr);
 
115
                pos += 18;
 
116
            } else
 
117
                assert(!"Unknown sizeof( void* ).");
 
118
        }
 
119
        for(i = 0;
 
120
                i < backtraces_size;
 
121
                ++i)
 
122
            if(strcmp(backtraces[ i ].key, stack) == 0) {
 
123
                ++backtraces[ i ].count;
 
124
                break;
 
125
            }
 
126
        if(i == backtraces_size) {
 
127
            int stack_text_size = 10;
 
128
            char* stack_text;
 
129
            char* stack_text_pos;
 
130
            for(i = 0;
 
131
                    i < n;
 
132
                    ++i)
 
133
                stack_text_size += strlen(strings[ i ]) + 5;
 
134
            stack_text = stack_text_pos = malloc(stack_text_size);
 
135
            for(i = 0;
 
136
                    i < n;
 
137
                    ++i) {
 
138
                stack_text_pos = stpcpy(stack_text_pos, "\n");
 
139
                stack_text_pos = stpcpy(stack_text_pos, strings[ i ]);
 
140
            }
 
141
            backtraces[ backtraces_size ].key = strdup(stack);
 
142
            backtraces[ backtraces_size ].text = stack_text;
 
143
            backtraces[ backtraces_size ].count = 1;
 
144
            ++backtraces_size;
 
145
            if(backtraces_size >= MAX_BACKTRACES)
 
146
                assert(!"MAX_BACKTRACES reached.");
 
147
        }
 
148
    }
 
149
    free(strings);
 
150
}
 
151
 
 
152
Status
 
153
_XReply(dpy, rep, extra, discard)
 
154
register Display *dpy;
 
155
register xReply *rep;
 
156
int extra;      /* number of 32-bit words expected after the reply */
 
157
Bool discard;   /* should I discard data following "extra" words? */
 
158
{
 
159
    if(___xreply_reply_enabled)
 
160
        ++___xreply_reply_count;
 
161
    if(xreply_backtrace_set == 0) {
 
162
        if(getenv("XREPLY_BACKTRACE") != NULL) {
 
163
            // C<number> - compress backtraces, saved as negative value in xreply_backtrace_type
 
164
            if(getenv("XREPLY_BACKTRACE")[ 0 ] == 'C')
 
165
                xreply_backtrace_type = -atoi(getenv("XREPLY_BACKTRACE") + 1);
 
166
            else // <number> - print the backtrace every time
 
167
                xreply_backtrace_type = atoi(getenv("XREPLY_BACKTRACE"));
 
168
        } else
 
169
            xreply_backtrace_type = 0;
 
170
    }
 
171
    if(xreply_backtrace_type != 0)
 
172
        xreply_backtrace();
 
173
    if(xreply_ptr == NULL) {
 
174
        xreply_ptr = (xreply_ptr_t)dlsym(RTLD_NEXT, "_XReply");
 
175
        if(xreply_ptr == NULL)
 
176
            assert(!"dlsym() failed.");
 
177
        atexit(xreply_print);
 
178
    }
 
179
    return xreply_ptr(dpy, rep, extra, discard);
 
180
}