summaryrefslogtreecommitdiffstats
path: root/include/net/profile.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /include/net/profile.h
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (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.h311
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