diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /include/net/profile.h | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'include/net/profile.h')
-rw-r--r-- | include/net/profile.h | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/include/net/profile.h b/include/net/profile.h new file mode 100644 index 000000000..82fad0a37 --- /dev/null +++ b/include/net/profile.h @@ -0,0 +1,311 @@ +#include <linux/config.h> /* for CONFIG_NET_PROFILE */ +#ifndef _NET_PROFILE_H_ +#define _NET_PROFILE_H_ 1 + +#ifdef CONFIG_NET_PROFILE + +#include <linux/types.h> +#include <linux/time.h> +#include <linux/kernel.h> +#include <asm/system.h> + +struct net_profile_slot +{ + char id[16]; + struct net_profile_slot *next; + struct timeval entered; + struct timeval accumulator; + struct timeval irq; + int hits; + int active; + int underflow; +}; + +extern atomic_t net_profile_active; +extern struct timeval net_profile_adjust; +extern void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved); + +#if CPU == 586 || CPU == 686 + + +extern __inline__ void net_profile_stamp(struct timeval *pstamp) +{ + __asm__ __volatile__ (".byte 0x0f,0x31" + :"=a" (pstamp->tv_usec), + "=d" (pstamp->tv_sec)); +} + +extern __inline__ void net_profile_accumulate(struct timeval *entered, + struct timeval *leaved, + struct timeval *acc) +{ + __asm__ __volatile__ ("subl %2,%0\n\t" + "sbbl %3,%1\n\t" + "addl %4,%0\n\t" + "adcl %5,%1\n\t" + "subl " SYMBOL_NAME_STR(net_profile_adjust) "+4,%0\n\t" + "sbbl $0,%1\n\t" + : "=r" (acc->tv_usec), "=r" (acc->tv_sec) + : "g" (entered->tv_usec), "g" (entered->tv_sec), + "g" (leaved->tv_usec), "g" (leaved->tv_sec), + "0" (acc->tv_usec), "1" (acc->tv_sec)); +} + +extern __inline__ void net_profile_sub(struct timeval *sub, + struct timeval *acc) +{ + __asm__ __volatile__ ("subl %2,%0\n\t" + "sbbl %3,%1\n\t" + : "=r" (acc->tv_usec), "=r" (acc->tv_sec) + : "g" (sub->tv_usec), "g" (sub->tv_sec), + "0" (acc->tv_usec), "1" (acc->tv_sec)); +} + +extern __inline__ void net_profile_add(struct timeval *add, + struct timeval *acc) +{ + __asm__ __volatile__ ("addl %2,%0\n\t" + "adcl %3,%1\n\t" + : "=r" (acc->tv_usec), "=r" (acc->tv_sec) + : "g" (add->tv_usec), "g" (add->tv_sec), + "0" (acc->tv_usec), "1" (acc->tv_sec)); +} + + +#elif defined (__alpha__) + +extern __u32 alpha_lo; +extern long alpha_hi; + +/* On alpha cycle counter has only 32 bits :-( :-( */ + +extern __inline__ void net_profile_stamp(struct timeval *pstamp) +{ + __u32 result; + __asm__ __volatile__ ("rpcc %0" : "r="(result)); + if (result <= alpha_lo) + alpha_hi++; + alpha_lo = result; + pstamp->tv_sec = alpha_hi; + pstamp->tv_usec = alpha_lo; +} + +extern __inline__ void net_profile_accumulate(struct timeval *entered, + struct timeval *leaved, + struct timeval *acc) +{ + time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec + - net_profile_adjust.tv_usec; + time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec; + + if (usecs >= 0x100000000L) { + usecs -= 0x100000000L; + secs++; + } else if (usecs < -0x100000000L) { + usecs += 0x200000000L; + secs -= 2; + } else if (usecs < 0) { + usecs += 0x100000000L; + secs--; + } + acc->tv_sec = secs; + acc->tv_usec = usecs; +} + +extern __inline__ void net_profile_sub(struct timeval *entered, + struct timeval *leaved) +{ + time_t usecs = leaved->tv_usec - entered->tv_usec; + time_t secs = leaved->tv_sec - entered->tv_sec; + + if (usecs < 0) { + usecs += 0x100000000L; + secs--; + } + leaved->tv_sec = secs; + leaved->tv_usec = usecs; +} + +extern __inline__ void net_profile_add(struct timeval *entered, struct timeval *leaved) +{ + time_t usecs = leaved->tv_usec + entered->tv_usec; + time_t secs = leaved->tv_sec + entered->tv_sec; + + if (usecs >= 0x100000000L) { + usecs -= 0x100000000L; + secs++; + } + leaved->tv_sec = secs; + leaved->tv_usec = usecs; +} + + +#else + +extern __inline__ void net_profile_stamp(struct timeval *pstamp) +{ + /* Not "fast" counterpart! On architectures without + cpu clock "fast" routine is absolutely useless in this + situation. do_gettimeofday still says something on slow-slow-slow + boxes, though it eats more cpu time than the sobject of + investigation :-) :-) + */ + do_gettimeofday(pstamp); +} + +extern __inline__ void net_profile_accumulate(struct timeval *entered, + struct timeval *leaved, + struct timeval *acc) +{ + time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec + - net_profile_adjust.tv_usec; + time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec; + + if (usecs >= 1000000) { + usecs -= 1000000; + secs++; + } else if (usecs < -1000000) { + usecs += 2000000; + secs -= 2; + } else if (usecs < 0) { + usecs += 1000000; + secs--; + } + acc->tv_sec = secs; + acc->tv_usec = usecs; +} + +extern __inline__ void net_profile_sub(struct timeval *entered, + struct timeval *leaved) +{ + time_t usecs = leaved->tv_usec - entered->tv_usec; + time_t secs = leaved->tv_sec - entered->tv_sec; + + if (usecs < 0) { + usecs += 1000000; + secs--; + } + leaved->tv_sec = secs; + leaved->tv_usec = usecs; +} + +extern __inline__ void net_profile_add(struct timeval *entered, struct timeval *leaved) +{ + time_t usecs = leaved->tv_usec + entered->tv_usec; + time_t secs = leaved->tv_sec + entered->tv_sec; + + if (usecs >= 1000000) { + usecs -= 1000000; + secs++; + } + leaved->tv_sec = secs; + leaved->tv_usec = usecs; +} + + + +#endif + +extern __inline__ void net_profile_enter(struct net_profile_slot *s) +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (s->active++ == 0) { + net_profile_stamp(&s->entered); + atomic_inc(&net_profile_active); + } + restore_flags(flags); +} + +extern __inline__ void net_profile_leave_irq(struct net_profile_slot *s) +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (--s->active <= 0) { + if (s->active == 0) { + struct timeval curr_pstamp; + net_profile_stamp(&curr_pstamp); + net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator); + if (!atomic_dec_and_test(&net_profile_active)) + net_profile_irq_adjust(&s->entered, &curr_pstamp); + } else { + s->underflow++; + } + } + s->hits++; + restore_flags(flags); +} + +extern __inline__ void net_profile_leave(struct net_profile_slot *s) +{ + unsigned long flags; + save_flags(flags); + cli(); + if (--s->active <= 0) { + if (s->active == 0) { + struct timeval curr_pstamp; + net_profile_stamp(&curr_pstamp); + net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator); + atomic_dec(&net_profile_active); + } else { + s->underflow++; + } + } + s->hits++; + restore_flags(flags); +} + + +#define NET_PROFILE_ENTER(slot) net_profile_enter(&net_prof_##slot) +#define NET_PROFILE_LEAVE(slot) net_profile_leave(&net_prof_##slot) +#define NET_PROFILE_LEAVE_IRQ(slot) net_profile_leave_irq(&net_prof_##slot) + +#define NET_PROFILE_SKB_CLEAR(skb) ({ \ + skb->pstamp.tv_usec = 0; \ +}) + +#define NET_PROFILE_SKB_INIT(skb) ({ \ + net_profile_stamp(&skb->pstamp); \ +}) + +#define NET_PROFILE_SKB_PASSED(skb, slot) ({ \ + if (skb->pstamp.tv_usec) { \ + struct timeval cur_pstamp = skb->pstamp; \ + net_profile_stamp(&skb->pstamp); \ + net_profile_accumulate(&cur_pstamp, &skb->pstamp, &net_prof_##slot.accumulator); \ + net_prof_##slot.hits++; \ + }}) + +#define NET_PROFILE_DECL(slot) \ + extern struct net_profile_slot net_prof_##slot; + +#define NET_PROFILE_DEFINE(slot) \ + struct net_profile_slot net_prof_##slot = { #slot, }; + +#define NET_PROFILE_REGISTER(slot) net_profile_register(&net_prof_##slot) +#define NET_PROFILE_UNREGISTER(slot) net_profile_unregister(&net_prof_##slot) + +extern int net_profile_init(void); +extern int net_profile_register(struct net_profile_slot *); +extern int net_profile_unregister(struct net_profile_slot *); + +#else + +#define NET_PROFILE_ENTER(slot) do { /* nothing */ } while(0) +#define NET_PROFILE_LEAVE(slot) do { /* nothing */ } while(0) +#define NET_PROFILE_LEAVE_IRQ(slot) do { /* nothing */ } while(0) +#define NET_PROFILE_SKB_CLEAR(skb) do { /* nothing */ } while(0) +#define NET_PROFILE_SKB_INIT(skb) do { /* nothing */ } while(0) +#define NET_PROFILE_SKB_PASSED(skb, slot) do { /* nothing */ } while(0) +#define NET_PROFILE_DECL(slot) +#define NET_PROFILE_DEFINE(slot) +#define NET_PROFILE_REGISTER(slot) do { /* nothing */ } while(0) +#define NET_PROFILE_UNREGISTER(slot) do { /* nothing */ } while(0) + +#endif + +#endif |