cleanup
[linux-2.4.21-pre4.git] / include / net1 / profile.h
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                               "0" (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                               "0" (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                               "0" (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