]> mj.ucw.cz Git - libucw.git/blob - lib/profile.h
Rewritten ff-binary.
[libucw.git] / lib / profile.h
1 /*
2  *      UCW Library -- Poor Man's Profiler
3  *
4  *      (c) 2001 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 /*
11  *  Usage:
12  *              #define PROFILE_xxx
13  *              #include "lib/profile.h"
14  *              prof_t cnt;
15  *              prof_init(&cnt);
16  *              ...
17  *              prof_start(&cnt);
18  *              ...
19  *              prof_stop(&cnt);
20  *              printf("%s\n", PROF_STR(cnt));
21  */
22
23 /* PROFILE_TOD: gettimeofday() profiler */
24
25 struct prof_tod {
26   u32 start_sec, start_usec;
27   s32 sec, usec;
28 };
29
30 void prof_tod_init(struct prof_tod *);
31 void prof_tod_switch(struct prof_tod *, struct prof_tod *);
32 int prof_tod_format(char *, struct prof_tod *);
33
34 /* PROFILE_TSC: i386 TSC profiler */
35
36 #ifdef CPU_I386
37
38 struct prof_tsc {
39   u64 start_tsc;
40   u64 ticks;
41 };
42
43 void prof_tsc_init(struct prof_tsc *);
44 int prof_tsc_format(char *, struct prof_tsc *);
45
46 #endif
47
48 /* PROFILE_KTSC: Linux kernel TSC profiler */
49
50 #ifdef CONFIG_LINUX
51
52 struct prof_ktsc {
53   u64 start_user, start_sys;
54   u64 ticks_user, ticks_sys;
55 };
56
57 void prof_ktsc_init(struct prof_ktsc *);
58 void prof_ktsc_switch(struct prof_ktsc *, struct prof_ktsc *);
59 int prof_ktsc_format(char *, struct prof_ktsc *);
60
61 #endif
62
63 /* Select the right profiler */
64
65 #if defined(PROFILE_TOD)
66
67 #define PROFILER
68 #define PROF_STR_SIZE 21
69 typedef struct prof_tod prof_t;
70 #define prof_init prof_tod_init
71 #define prof_switch prof_tod_switch
72 #define prof_format prof_tod_format
73
74 #elif defined(PROFILE_TSC)
75
76 #define PROFILER
77 #define PROFILER_INLINE
78 #define PROF_STR_SIZE 24
79
80 typedef struct prof_tsc prof_t;
81 #define prof_init prof_tsc_init
82 #define prof_format prof_tsc_format
83
84 #define rdtscll(val) __asm__ __volatile__("rdtsc" : "=A" (val))
85
86 static inline void prof_start(prof_t *c)
87 {
88   rdtscll(c->start_tsc);
89 }
90
91 static inline void prof_stop(prof_t *c)
92 {
93   u64 tsc;
94   rdtscll(tsc);
95   tsc -= c->start_tsc;
96   c->ticks += tsc;
97 }
98
99 static inline void prof_switch(prof_t *o, prof_t *n)
100 {
101   u64 tsc;
102   rdtscll(tsc);
103   n->start_tsc = tsc;
104   tsc -= o->start_tsc;
105   o->ticks += tsc;
106 }
107
108 #elif defined(PROFILE_KTSC)
109
110 #define PROFILER
111 #define PROF_STR_SIZE 50
112 typedef struct prof_ktsc prof_t;
113 #define prof_init prof_ktsc_init
114 #define prof_switch prof_ktsc_switch
115 #define prof_format prof_ktsc_format
116
117 #endif
118
119 #ifdef PROFILER
120
121 /* Stuff common for all profilers */
122 #ifndef PROFILER_INLINE
123 static inline void prof_start(prof_t *c) { prof_switch(NULL, c); }
124 static inline void prof_stop(prof_t *c) { prof_switch(c, NULL); }
125 #endif
126 #define PROF_STR(C) ({ static byte _x[PROF_STR_SIZE]; prof_format(_x, &(C)); _x; })
127
128 #else
129
130 /* Dummy profiler with no output */
131 typedef struct { } prof_t;
132 static inline void prof_init(prof_t *c UNUSED) { }
133 static inline void prof_start(prof_t *c UNUSED) { }
134 static inline void prof_stop(prof_t *c UNUSED) { }
135 static inline void prof_switch(prof_t *c UNUSED, prof_t *d UNUSED) { }
136 static inline void prof_format(char *b, prof_t *c UNUSED) { b[0]='?'; b[1]=0; }
137 #define PROF_STR_SIZE 2
138 #define PROF_STR(C) "?"
139
140 #endif