1 #include <linux/config.h> /* for CONFIG_NET_PROFILE */
2 #ifndef _NET_PROFILE_H_
3 #define _NET_PROFILE_H_ 1
5 #ifdef CONFIG_NET_PROFILE
7 #include <linux/types.h>
8 #include <linux/time.h>
9 #include <linux/kernel.h>
10 #include <asm/system.h>
16 struct net_profile_slot
19 struct net_profile_slot *next;
20 struct timeval entered;
21 struct timeval accumulator;
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);
34 static inline void net_profile_stamp(struct timeval *pstamp)
36 rdtsc(pstamp->tv_usec, pstamp->tv_sec);
39 static inline void net_profile_accumulate(struct timeval *entered,
40 struct timeval *leaved,
43 __asm__ __volatile__ ("subl %2,%0\n\t"
47 "subl " SYMBOL_NAME_STR(net_profile_adjust) "+4,%0\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));
55 static inline void net_profile_sub(struct timeval *sub,
58 __asm__ __volatile__ ("subl %2,%0\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));
65 static inline void net_profile_add(struct timeval *add,
68 __asm__ __volatile__ ("addl %2,%0\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));
76 #elif defined (__alpha__)
78 extern __u32 alpha_lo;
81 /* On alpha cycle counter has only 32 bits :-( :-( */
83 static inline void net_profile_stamp(struct timeval *pstamp)
86 __asm__ __volatile__ ("rpcc %0" : "r="(result));
87 if (result <= alpha_lo)
90 pstamp->tv_sec = alpha_hi;
91 pstamp->tv_usec = alpha_lo;
94 static inline void net_profile_accumulate(struct timeval *entered,
95 struct timeval *leaved,
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;
102 if (usecs >= 0x100000000L) {
103 usecs -= 0x100000000L;
105 } else if (usecs < -0x100000000L) {
106 usecs += 0x200000000L;
108 } else if (usecs < 0) {
109 usecs += 0x100000000L;
113 acc->tv_usec = usecs;
116 static inline void net_profile_sub(struct timeval *entered,
117 struct timeval *leaved)
119 time_t usecs = leaved->tv_usec - entered->tv_usec;
120 time_t secs = leaved->tv_sec - entered->tv_sec;
123 usecs += 0x100000000L;
126 leaved->tv_sec = secs;
127 leaved->tv_usec = usecs;
130 static inline void net_profile_add(struct timeval *entered, struct timeval *leaved)
132 time_t usecs = leaved->tv_usec + entered->tv_usec;
133 time_t secs = leaved->tv_sec + entered->tv_sec;
135 if (usecs >= 0x100000000L) {
136 usecs -= 0x100000000L;
139 leaved->tv_sec = secs;
140 leaved->tv_usec = usecs;
146 static inline void net_profile_stamp(struct timeval *pstamp)
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 :-) :-)
154 do_gettimeofday(pstamp);
157 static inline void net_profile_accumulate(struct timeval *entered,
158 struct timeval *leaved,
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;
165 if (usecs >= 1000000) {
168 } else if (usecs < -1000000) {
171 } else if (usecs < 0) {
176 acc->tv_usec = usecs;
179 static inline void net_profile_sub(struct timeval *entered,
180 struct timeval *leaved)
182 time_t usecs = leaved->tv_usec - entered->tv_usec;
183 time_t secs = leaved->tv_sec - entered->tv_sec;
189 leaved->tv_sec = secs;
190 leaved->tv_usec = usecs;
193 static inline void net_profile_add(struct timeval *entered, struct timeval *leaved)
195 time_t usecs = leaved->tv_usec + entered->tv_usec;
196 time_t secs = leaved->tv_sec + entered->tv_sec;
198 if (usecs >= 1000000) {
202 leaved->tv_sec = secs;
203 leaved->tv_usec = usecs;
210 static inline void net_profile_enter(struct net_profile_slot *s)
216 if (s->active++ == 0) {
217 net_profile_stamp(&s->entered);
218 atomic_inc(&net_profile_active);
220 restore_flags(flags);
223 static inline void net_profile_leave_irq(struct net_profile_slot *s)
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);
241 restore_flags(flags);
244 static inline void net_profile_leave(struct net_profile_slot *s)
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);
260 restore_flags(flags);
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)
268 #define NET_PROFILE_SKB_CLEAR(skb) ({ \
269 skb->pstamp.tv_usec = 0; \
272 #define NET_PROFILE_SKB_INIT(skb) ({ \
273 net_profile_stamp(&skb->pstamp); \
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++; \
284 #define NET_PROFILE_DECL(slot) \
285 extern struct net_profile_slot net_prof_##slot;
287 #define NET_PROFILE_DEFINE(slot) \
288 struct net_profile_slot net_prof_##slot = { #slot, };
290 #define NET_PROFILE_REGISTER(slot) net_profile_register(&net_prof_##slot)
291 #define NET_PROFILE_UNREGISTER(slot) net_profile_unregister(&net_prof_##slot)
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 *);
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)