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