1 #include <linux/config.h> /* for CONFIG_NET_PROFILE */
2 #ifndef _NET_PROFILE_H_
3 #define _NET_PROFILE_H_ 1
4
5 #ifdef CONFIG_NET_PROFILE
6
7 #include <linux/types.h>
8 #include <linux/time.h>
9 #include <linux/kernel.h>
10 #include <asm/system.h>
11
12 #ifdef CONFIG_X86_TSC
13 #include <asm/msr.h>
14 #endif
15
16 struct net_profile_slot
17 {
18 char id[16];
19 struct net_profile_slot *next;
20 struct timeval entered;
21 struct timeval accumulator;
22 struct timeval irq;
23 int hits;
24 int active;
25 int underflow;
26 };
27
28 extern atomic_t net_profile_active;
29 extern struct timeval net_profile_adjust;
30 extern void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved);
31
32 #ifdef CONFIG_X86_TSC
33
34 static inline void net_profile_stamp(struct timeval *pstamp)
35 {
36 rdtsc(pstamp->tv_usec, pstamp->tv_sec);
37 }
38
39 static inline void net_profile_accumulate(struct timeval *entered,
40 struct timeval *leaved,
41 struct timeval *acc)
42 {
43 __asm__ __volatile__ ("subl %2,%0\n\t"
44 "sbbl %3,%1\n\t"
45 "addl %4,%0\n\t"
46 "adcl %5,%1\n\t"
47 "subl " SYMBOL_NAME_STR(net_profile_adjust) "+4,%0\n\t"
48 "sbbl $0,%1\n\t"
49 : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
50 : "g" (entered->tv_usec), "g" (entered->tv_sec),
51 "g" (leaved->tv_usec), "g" (leaved->tv_sec),
52 "" (acc->tv_usec), "1" (acc->tv_sec));
53 }
54
55 static inline void net_profile_sub(struct timeval *sub,
56 struct timeval *acc)
57 {
58 __asm__ __volatile__ ("subl %2,%0\n\t"
59 "sbbl %3,%1\n\t"
60 : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
61 : "g" (sub->tv_usec), "g" (sub->tv_sec),
62 "" (acc->tv_usec), "1" (acc->tv_sec));
63 }
64
65 static inline void net_profile_add(struct timeval *add,
66 struct timeval *acc)
67 {
68 __asm__ __volatile__ ("addl %2,%0\n\t"
69 "adcl %3,%1\n\t"
70 : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
71 : "g" (add->tv_usec), "g" (add->tv_sec),
72 "" (acc->tv_usec), "1" (acc->tv_sec));
73 }
74
75
76 #elif defined (__alpha__)
77
78 extern __u32 alpha_lo;
79 extern long alpha_hi;
80
81 /* On alpha cycle counter has only 32 bits :-( :-( */
82
83 static inline void net_profile_stamp(struct timeval *pstamp)
84 {
85 __u32 result;
86 __asm__ __volatile__ ("rpcc %0" : "r="(result));
87 if (result <= alpha_lo)
88 alpha_hi++;
89 alpha_lo = result;
90 pstamp->tv_sec = alpha_hi;
91 pstamp->tv_usec = alpha_lo;
92 }
93
94 static inline void net_profile_accumulate(struct timeval *entered,
95 struct timeval *leaved,
96 struct timeval *acc)
97 {
98 time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec
99 - net_profile_adjust.tv_usec;
100 time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec;
101
102 if (usecs >= 0x100000000L) {
103 usecs -= 0x100000000L;
104 secs++;
105 } else if (usecs < -0x100000000L) {
106 usecs += 0x200000000L;
107 secs -= 2;
108 } else if (usecs < 0) {
109 usecs += 0x100000000L;
110 secs--;
111 }
112 acc->tv_sec = secs;
113 acc->tv_usec = usecs;
114 }
115
116 static inline void net_profile_sub(struct timeval *entered,
117 struct timeval *leaved)
118 {
119 time_t usecs = leaved->tv_usec - entered->tv_usec;
120 time_t secs = leaved->tv_sec - entered->tv_sec;
121
122 if (usecs < 0) {
123 usecs += 0x100000000L;
124 secs--;
125 }
126 leaved->tv_sec = secs;
127 leaved->tv_usec = usecs;
128 }
129
130 static inline void net_profile_add(struct timeval *entered, struct timeval *leaved)
131 {
132 time_t usecs = leaved->tv_usec + entered->tv_usec;
133 time_t secs = leaved->tv_sec + entered->tv_sec;
134
135 if (usecs >= 0x100000000L) {
136 usecs -= 0x100000000L;
137 secs++;
138 }
139 leaved->tv_sec = secs;
140 leaved->tv_usec = usecs;
141 }
142
143
144 #else
145
146 static inline void net_profile_stamp(struct timeval *pstamp)
147 {
148 /* Not "fast" counterpart! On architectures without
149 cpu clock "fast" routine is absolutely useless in this
150 situation. do_gettimeofday still says something on slow-slow-slow
151 boxes, though it eats more cpu time than the subject of
152 investigation :-) :-)
153 */
154 do_gettimeofday(pstamp);
155 }
156
157 static inline void net_profile_accumulate(struct timeval *entered,
158 struct timeval *leaved,
159 struct timeval *acc)
160 {
161 time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec
162 - net_profile_adjust.tv_usec;
163 time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec;
164
165 if (usecs >= 1000000) {
166 usecs -= 1000000;
167 secs++;
168 } else if (usecs < -1000000) {
169 usecs += 2000000;
170 secs -= 2;
171 } else if (usecs < 0) {
172 usecs += 1000000;
173 secs--;
174 }
175 acc->tv_sec = secs;
176 acc->tv_usec = usecs;
177 }
178
179 static inline void net_profile_sub(struct timeval *entered,
180 struct timeval *leaved)
181 {
182 time_t usecs = leaved->tv_usec - entered->tv_usec;
183 time_t secs = leaved->tv_sec - entered->tv_sec;
184
185 if (usecs < 0) {
186 usecs += 1000000;
187 secs--;
188 }
189 leaved->tv_sec = secs;
190 leaved->tv_usec = usecs;
191 }
192
193 static inline void net_profile_add(struct timeval *entered, struct timeval *leaved)
194 {
195 time_t usecs = leaved->tv_usec + entered->tv_usec;
196 time_t secs = leaved->tv_sec + entered->tv_sec;
197
198 if (usecs >= 1000000) {
199 usecs -= 1000000;
200 secs++;
201 }
202 leaved->tv_sec = secs;
203 leaved->tv_usec = usecs;
204 }
205
206
207
208 #endif
209
210 static inline void net_profile_enter(struct net_profile_slot *s)
211 {
212 unsigned long flags;
213
214 save_flags(flags);
215 cli();
216 if (s->active++ == 0) {
217 net_profile_stamp(&s->entered);
218 atomic_inc(&net_profile_active);
219 }
220 restore_flags(flags);
221 }
222
223 static inline void net_profile_leave_irq(struct net_profile_slot *s)
224 {
225 unsigned long flags;
226
227 save_flags(flags);
228 cli();
229 if (--s->active <= 0) {
230 if (s->active == 0) {
231 struct timeval curr_pstamp;
232 net_profile_stamp(&curr_pstamp);
233 net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator);
234 if (!atomic_dec_and_test(&net_profile_active))
235 net_profile_irq_adjust(&s->entered, &curr_pstamp);
236 } else {
237 s->underflow++;
238 }
239 }
240 s->hits++;
241 restore_flags(flags);
242 }
243
244 static inline void net_profile_leave(struct net_profile_slot *s)
245 {
246 unsigned long flags;
247 save_flags(flags);
248 cli();
249 if (--s->active <= 0) {
250 if (s->active == 0) {
251 struct timeval curr_pstamp;
252 net_profile_stamp(&curr_pstamp);
253 net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator);
254 atomic_dec(&net_profile_active);
255 } else {
256 s->underflow++;
257 }
258 }
259 s->hits++;
260 restore_flags(flags);
261 }
262
263
264 #define NET_PROFILE_ENTER(slot) net_profile_enter(&net_prof_##slot)
265 #define NET_PROFILE_LEAVE(slot) net_profile_leave(&net_prof_##slot)
266 #define NET_PROFILE_LEAVE_IRQ(slot) net_profile_leave_irq(&net_prof_##slot)
267
268 #define NET_PROFILE_SKB_CLEAR(skb) ({ \
269 skb->pstamp.tv_usec = 0; \
270 })
271
272 #define NET_PROFILE_SKB_INIT(skb) ({ \
273 net_profile_stamp(&skb->pstamp); \
274 })
275
276 #define NET_PROFILE_SKB_PASSED(skb, slot) ({ \
277 if (skb->pstamp.tv_usec) { \
278 struct timeval cur_pstamp = skb->pstamp; \
279 net_profile_stamp(&skb->pstamp); \
280 net_profile_accumulate(&cur_pstamp, &skb->pstamp, &net_prof_##slot.accumulator); \
281 net_prof_##slot.hits++; \
282 }})
283
284 #define NET_PROFILE_DECL(slot) \
285 extern struct net_profile_slot net_prof_##slot;
286
287 #define NET_PROFILE_DEFINE(slot) \
288 struct net_profile_slot net_prof_##slot = { #slot, };
289
290 #define NET_PROFILE_REGISTER(slot) net_profile_register(&net_prof_##slot)
291 #define NET_PROFILE_UNREGISTER(slot) net_profile_unregister(&net_prof_##slot)
292
293 extern int net_profile_init(void);
294 extern int net_profile_register(struct net_profile_slot *);
295 extern int net_profile_unregister(struct net_profile_slot *);
296
297 #else
298
299 #define NET_PROFILE_ENTER(slot) do { /* nothing */ } while(0)
300 #define NET_PROFILE_LEAVE(slot) do { /* nothing */ } while(0)
301 #define NET_PROFILE_LEAVE_IRQ(slot) do { /* nothing */ } while(0)
302 #define NET_PROFILE_SKB_CLEAR(skb) do { /* nothing */ } while(0)
303 #define NET_PROFILE_SKB_INIT(skb) do { /* nothing */ } while(0)
304 #define NET_PROFILE_SKB_PASSED(skb, slot) do { /* nothing */ } while(0)
305 #define NET_PROFILE_DECL(slot)
306 #define NET_PROFILE_DEFINE(slot)
307 #define NET_PROFILE_REGISTER(slot) do { /* nothing */ } while(0)
308 #define NET_PROFILE_UNREGISTER(slot) do { /* nothing */ } while(0)
309
310 #endif
311
312 #endif
313
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.