gator: ARM DS-5.4 Streamline gator driver
authorPawel Moll <pawel.moll@arm.com>
Mon, 14 Mar 2011 15:22:44 +0000 (15:22 +0000)
committerPawel Moll <pawel.moll@arm.com>
Mon, 14 Mar 2011 15:22:44 +0000 (15:22 +0000)
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
16 files changed:
Makefile
README_Streamline.txt
gator.h
gator_annotate.c
gator_backtrace.c
gator_cookies.c
gator_events.c
gator_events_armv6.c
gator_events_armv7.c
gator_events_block.c
gator_events_irq.c
gator_events_meminfo.c
gator_events_net.c [new file with mode: 0644]
gator_events_sched.c
gator_main.c
gator_trace_sched.c

index 8e679a7e017e75ef1ba11b8df20107a35be8a943..0583ae31459705741d1f5c2ee2e656eb93deb812 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ gator-objs :=   gator_main.o \
                gator_events_armv7.o \
                gator_events_irq.o \
                gator_events_sched.o \
+               gator_events_net.o \
                gator_events_block.o \
                gator_events_meminfo.o
 
@@ -20,6 +21,6 @@ all:
        $(error)
 
 clean:
-       rm -f *.o .*.cmd */*.o */.*.cmd modules.order Module.symvers gator.ko gator.mod.c
+       rm -f *.o modules.order Module.symvers gator.ko gator.mod.c
 
 endif
index 4c52b7d2c5138e67ea7084dacbbc66c4ec447139..4688474f1739fce9f35ce87d469154a6081e0265 100644 (file)
@@ -76,42 +76,6 @@ vi rungator.sh
        /path/to/gatord &
 update-rc.d rungator.sh defaults
 
-*** Driver Sources ***
-
-Gator Sources
-       backtrace.c
-       cpu_buffer.c
-       cpu_fifo.c
-       cpu_fifo.h
-       gator_annotate.c
-       gator_events_irq.c
-       gator_init.c
-       gator_interrupt.c
-       gator_pmnc_armv7.c
-       gator_pmnc_none.c
-       gator_schedtrace.c
-       gator_setup.c
-       gator_timer.c
-       gator_traceprobe.h
-
-Oprofile Sources  // function names updated to avoid Oprofile collisions
-       buffer_sync.c
-       buffer_sync.h
-       cpu_buffer.h
-       event_buffer.c
-       event_buffer.h
-       oprof.h
-       oprofile.h
-       oprofile_files.c
-       oprofile_stats.c
-       oprofile_stats.h
-       timer_int.c
-
-Modified Oprofile Sources
-       buffer_sync.c   // modify sample contract to allow bad 'mm' or cookie
-       oprofilefs.c    // gatorfs and magic number
-       oprof.c         // updated module name and author
-
 *** GPL License ***
 
 For license information, please see the file LICENSE.
diff --git a/gator.h b/gator.h
index 87ca10770a1b90e821f8d04ccdf0c30452da9ce0..f0c95bf3e11fc9e6956a210550c85a92fb76f424 100644 (file)
--- a/gator.h
+++ b/gator.h
@@ -6,6 +6,13 @@
  * published by the Free Software Foundation.
  */
 
+#ifndef GATOR_H_
+#define GATOR_H_
+
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
 /******************************************************************************
  * Filesystem
  ******************************************************************************/
@@ -21,6 +28,27 @@ int gatorfs_create_ulong(struct super_block *sb, struct dentry *root,
 int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
        char const *name, unsigned long *val);
 
+/******************************************************************************
+ * Tracepoints
+ ******************************************************************************/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+#      error Kernels prior to 2.6.32 not supported
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+#      define GATOR_DEFINE_PROBE(probe_name, proto) \
+               static void probe_##probe_name(PARAMS(proto))
+#      define GATOR_REGISTER_TRACE(probe_name) \
+               register_trace_##probe_name(probe_##probe_name)
+#      define GATOR_UNREGISTER_TRACE(probe_name) \
+               unregister_trace_##probe_name(probe_##probe_name)
+#else
+#      define GATOR_DEFINE_PROBE(probe_name, proto) \
+               static void probe_##probe_name(void *data, PARAMS(proto))
+#      define GATOR_REGISTER_TRACE(probe_name) \
+               register_trace_##probe_name(probe_##probe_name, NULL)
+#      define GATOR_UNREGISTER_TRACE(probe_name) \
+               unregister_trace_##probe_name(probe_##probe_name, NULL)
+#endif
+
 /******************************************************************************
  * Events
  ******************************************************************************/
@@ -29,6 +57,8 @@ struct __gator_interface {
        int  (*init)(int *key);
        int  (*start)(void);
        void (*stop)(void);
+       void (*online)(void);
+       void (*offline)(void);
        int  (*read)(int **buffer);
        struct __gator_interface *next;
 };
@@ -36,3 +66,7 @@ struct __gator_interface {
 typedef struct __gator_interface gator_interface;
 
 int gator_event_install(int (*event_install)(gator_interface *));
+
+extern unsigned long gator_net_traffic;
+
+#endif // GATOR_H_
index 18441576c183967bd0cbbfd58ec05543c9782d04..56656f0149902902c8c2297a4b463b76753b2ff9 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
index c4ddf41a05692e43fca6f52acc81af5927bca44b..628a18f37b62537eb501c0b1c35b9f2e703beaae 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
index d267a572096f2bbef0fe494643a37a8c9422012a..4e39667096ebc6a6223d3bbcf51465192a411d5e 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,8 +11,6 @@
 #define MAX_COLLISIONS         2
 
 static DEFINE_PER_CPU(uint32_t, cookie_next_key);
-static DEFINE_PER_CPU(uint32_t, cookie_prev_text);
-static DEFINE_PER_CPU(uint32_t, cookie_prev_value);
 static DEFINE_PER_CPU(uint64_t *, cookie_keys);
 static DEFINE_PER_CPU(uint32_t *, cookie_values);
 
@@ -105,10 +103,6 @@ static inline uint32_t get_cookie(int cpu, int tgid, struct vm_area_struct *vma)
        }
 
        text = (char*)path->dentry->d_name.name;
-       if (per_cpu     (cookie_prev_text, cpu) == (uint32_t)text) {
-               return per_cpu(cookie_prev_value, cpu);
-       }
-
        key = gator_chksum_crc32(text);
        key = (key << 32) | (uint32_t)text;
 
@@ -125,8 +119,6 @@ static inline uint32_t get_cookie(int cpu, int tgid, struct vm_area_struct *vma)
        gator_buffer_write_string(cpu, text);
 
 output:
-       per_cpu(cookie_prev_text, cpu) = (uint32_t)text;
-       per_cpu(cookie_prev_value, cpu) = cookie;
        return cookie;
 }
 
@@ -187,10 +179,8 @@ static void cookies_initialize(void)
        int cpu, size;
        int i, j;
 
-       for_each_possible_cpu(cpu) {
+       for_each_present_cpu(cpu) {
                per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
-               per_cpu(cookie_prev_text, cpu) = 0;
-               per_cpu(cookie_prev_value, cpu) = 0;
 
                size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t);
                per_cpu(cookie_keys, cpu) = (uint64_t*)kmalloc(size, GFP_KERNEL);
@@ -221,7 +211,7 @@ static void cookies_release(void)
 {
        int cpu;
 
-       for_each_possible_cpu(cpu) {
+       for_each_present_cpu(cpu) {
                kfree(per_cpu(cookie_keys, cpu));
                per_cpu(cookie_keys, cpu) = NULL;
 
index 1a5d0a0ed1c9ac48b29efc908a5de9d7d440a911..d8372577ae03256dedbab48efcaaf0e7a9896652 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -18,6 +18,7 @@ extern int gator_events_irq_install(gator_interface *gi);
 extern int gator_events_sched_install(gator_interface *gi);
 extern int gator_events_block_install(gator_interface *gi);
 extern int gator_events_meminfo_install(gator_interface *gi);
+extern int gator_events_net_install(gator_interface *gi);
 
 static int gator_events_install(void)
 {
@@ -33,5 +34,7 @@ static int gator_events_install(void)
                return -1;
        if (gator_event_install(gator_events_meminfo_install))
                return -1;
+       if (gator_event_install(gator_events_net_install))
+               return -1;
        return 0;
 }
index a916d836a44d0eff6da1363f4c0beaba7195393d..c571e44b23183eb34b944168db4e911de28d6dc3 100644 (file)
@@ -1,17 +1,11 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/fs.h>
-
 #include "gator.h"
 
 #if defined(__arm__)
@@ -119,15 +113,13 @@ static int gator_events_armv6_init(int *key)
        return 0;
 }
 
-static void __gator_events_armv6_start(void* unused)
+static void gator_events_armv6_online(void)
 {
        unsigned int cnt;
        u32 pmnc;
 
        if (armv6_pmnc_read() & PMCR_E) {
-               pr_err("gator: CPU%u PMNC still enabled when setup new event counter.\n", smp_processor_id());
-               pmnc_count = 0;
-               return;
+               armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E);
        }
 
        /* initialize PMNC, reset overflow, D bit, C bit and P bit. */
@@ -162,31 +154,24 @@ static void __gator_events_armv6_start(void* unused)
        armv6_pmnc_write(pmnc | PMCR_E);
 }
 
-static int gator_events_armv6_start(void)
-{
-       if (!pmnc_count)
-               return 0;
-       return on_each_cpu(__gator_events_armv6_start, NULL, 1);
-}
-
-static void __gator_events_armv6_stop(void* unused)
+static void gator_events_armv6_offline(void)
 {
        unsigned int cnt;
 
        armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E);
-
        for (cnt = PMN0; cnt <= CCNT; cnt++) {
                armv6_pmnc_reset_counter(cnt);
-               pmnc_enabled[cnt] = 0;
-               pmnc_event[cnt] = 0;
        }
 }
 
 static void gator_events_armv6_stop(void)
 {
-       if (!pmnc_count)
-               return;
-       on_each_cpu(__gator_events_armv6_stop, NULL, 1);
+       unsigned int cnt;
+
+       for (cnt = PMN0; cnt <= CCNT; cnt++) {
+               pmnc_enabled[cnt] = 0;
+               pmnc_event[cnt] = 0;
+       }
 }
 
 static int gator_events_armv6_read(int **buffer)
@@ -194,9 +179,6 @@ static int gator_events_armv6_read(int **buffer)
        int cnt, len = 0;
        int cpu = raw_smp_processor_id();
 
-       if (!pmnc_count)
-               return 0;
-
        for (cnt = PMN0; cnt <= CCNT; cnt++) {
                if (pmnc_enabled[cnt]) {
                        u32 value = 0;
@@ -242,8 +224,9 @@ int gator_events_armv6_install(gator_interface *gi) {
 
        gi->create_files = gator_events_armv6_create_files;
        gi->init = gator_events_armv6_init;
-       gi->start = gator_events_armv6_start;
        gi->stop = gator_events_armv6_stop;
+       gi->online = gator_events_armv6_online;
+       gi->offline = gator_events_armv6_offline;
        gi->read = gator_events_armv6_read;
 #endif
        return 0;
index ca37befd114cc56b3ee01605ae9fc1656b13b7df..5a3268fb0e994353628920bcca4582c1ccdcb041 100644 (file)
@@ -1,15 +1,10 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/fs.h>
 
 #include "gator.h"
 
@@ -284,14 +279,12 @@ static int gator_events_armv7_init(int *key)
        return 0;
 }
 
-static void __gator_events_armv7_start(void* unused)
+static void gator_events_armv7_online(void)
 {
        unsigned int cnt;
 
        if (armv7_pmnc_read() & PMNC_E) {
-               pr_err("gator: CPU%u PMNC still enabled when setup new event counter\n", raw_smp_processor_id());
-               pmnc_count = 0;
-               return;
+               armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
        }
 
        /* Initialize & Reset PMNC: C bit and P bit */
@@ -339,17 +332,14 @@ static void __gator_events_armv7_start(void* unused)
        armv7_pmnc_write(armv7_pmnc_read() | PMNC_E);
 }
 
-static int gator_events_armv7_start(void)
+static void gator_events_armv7_offline(void)
 {
-       if (!pmnc_count)
-               return 0;
-       return on_each_cpu(__gator_events_armv7_start, NULL, 1);
+       armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
 }
 
-static void __gator_events_armv7_stop(void* unused)
+static void gator_events_armv7_stop(void)
 {
        unsigned int cnt;
-       armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
 
        for (cnt = CCNT; cnt < CNTMAX; cnt++) {
                pmnc_enabled[cnt] = 0;
@@ -357,13 +347,6 @@ static void __gator_events_armv7_stop(void* unused)
        }
 }
 
-static void gator_events_armv7_stop(void)
-{
-       if (!pmnc_count)
-               return;
-       on_each_cpu(__gator_events_armv7_stop, NULL, 1);
-}
-
 static int gator_events_armv7_read(int **buffer)
 {
        int cnt, len = 0;
@@ -419,8 +402,9 @@ int gator_events_armv7_install(gator_interface *gi) {
 
        gi->create_files = gator_events_armv7_create_files;
        gi->init = gator_events_armv7_init;
-       gi->start = gator_events_armv7_start;
        gi->stop = gator_events_armv7_stop;
+       gi->online = gator_events_armv7_online;
+       gi->offline = gator_events_armv7_offline;
        gi->read = gator_events_armv7_read;
 #endif
        return 0;
index c2d1e7e931396862f7894837ee40f7a6a0218b4e..f32d8ef6520b5d000d43a191d4224836834c2807 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,14 +7,8 @@
  *
  */
 
-#include <linux/version.h>
-#include <linux/blkdev.h>
-#include <trace/events/block.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-
 #include "gator.h"
-#include "gator_trace.h"
+#include <trace/events/block.h>
 
 #define BLOCK_RQ_WR            0
 #define BLOCK_RQ_RD            1
@@ -102,7 +96,7 @@ static int gator_events_block_start(void)
 {
        int cpu;
 
-       for_each_possible_cpu(cpu) 
+       for_each_present_cpu(cpu) 
                per_cpu(new_data_avail, cpu) = true;
 
        // register tracepoints
index f34cc18084c928b4dacfe55fa555ec44e8a838ee..7bbbd4bde9a4cbd160009134b46af3475353e5dd 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,15 +7,8 @@
  *
  */
 
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/dcookies.h>
-#include <linux/version.h>
-#include <trace/events/irq.h>
-
 #include "gator.h"
-#include "gator_trace.h"
+#include <trace/events/irq.h>
 
 #define HARDIRQ                0
 #define SOFTIRQ                1
@@ -41,8 +34,11 @@ GATOR_DEFINE_PROBE(irq_handler_exit, TP_PROTO(int irq,
        local_irq_restore(flags);
 }
 
-GATOR_DEFINE_PROBE(softirq_exit, TP_PROTO(struct softirq_action *h,
-               struct softirq_action *vec))
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+GATOR_DEFINE_PROBE(softirq_exit, TP_PROTO(struct softirq_action *h, struct softirq_action *vec))
+#else
+GATOR_DEFINE_PROBE(softirq_exit, TP_PROTO(unsigned int vec_nr))
+#endif
 {
        unsigned long flags;
 
@@ -93,7 +89,7 @@ static int gator_events_irq_start(void)
 {
        int cpu, i;
 
-       for_each_possible_cpu(cpu) {
+       for_each_present_cpu(cpu) {
                for (i = 0; i < TOTALIRQ; i++)
                        per_cpu(irqPrev, cpu)[i] = 0;
        }
index 52345c80e864a547d40bac8dd8ebaccc92ec833d..1b576f89130afb34cad447eb6bf6c725df16be32 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,16 +7,10 @@
  *
  */
 
+#include "gator.h"
 #include <linux/workqueue.h>
-#include <linux/version.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
 #include <trace/events/kmem.h>
 
-#include "gator.h"
-#include "gator_trace.h"
-
 #define MEMINFO_MEMFREE                0
 #define MEMINFO_MEMUSED                1
 #define MEMINFO_BUFFERRAM      2
diff --git a/gator_events_net.c b/gator_events_net.c
new file mode 100644 (file)
index 0000000..3ca5911
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include "gator.h"
+#include <linux/netdevice.h>
+
+#define NETRX          0
+#define NETTX          1
+#define NETDRV         2
+#define TOTALNET       (NETDRV+1)
+
+static ulong netdrv_enabled;
+static ulong netrx_enabled;
+static ulong nettx_enabled;
+static ulong netdrv_key;
+static ulong netrx_key;
+static ulong nettx_key;
+static int rx_total, tx_total;
+static ulong netPrev[TOTALNET];
+static int netGet[TOTALNET * 2];
+
+static void get_network_stats(struct work_struct *wsptr) {
+       int rx = 0, tx = 0;
+       struct net_device *dev;
+
+       for_each_netdev(&init_net, dev) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+               const struct net_device_stats *stats = dev_get_stats(dev);
+#else
+               struct rtnl_link_stats64 temp;
+               const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);
+#endif
+               rx += stats->rx_bytes;
+               tx += stats->tx_bytes;
+       }
+       rx_total = rx;
+       tx_total = tx;
+}
+DECLARE_WORK(wq_get_stats, get_network_stats);
+
+static void calculate_delta(int *drv, int *rx, int *tx)
+{
+       int drv_calc, rx_calc, tx_calc;
+
+       drv_calc = gator_net_traffic - netPrev[NETDRV];
+       if (drv_calc > 0) {
+               netPrev[NETDRV] += drv_calc;
+               netPrev[NETTX] += drv_calc;
+               // remove tcp/ip header overhead
+               //  approximation based on empirical measurement
+               netPrev[NETRX] += drv_calc / 42;
+               netPrev[NETTX] += drv_calc / 18;
+       }
+
+       rx_calc = (int)(rx_total - netPrev[NETRX]);
+       if (rx_calc < 0)
+               rx_calc = 0;
+       netPrev[NETRX] += rx_calc;
+
+       tx_calc = (int)(tx_total - netPrev[NETTX]);
+       if (tx_calc < 0)
+               tx_calc = 0;
+       netPrev[NETTX] += tx_calc;
+
+       *drv = drv_calc;
+       *rx = rx_calc;
+       *tx = tx_calc;
+}
+
+static int gator_events_net_create_files(struct super_block *sb, struct dentry *root)
+{
+       struct dentry *dir;
+
+       dir = gatorfs_mkdir(sb, root, "Linux_net_drv");
+       if (!dir) {
+               return -1;
+       }
+       gatorfs_create_ulong(sb, dir, "enabled", &netdrv_enabled);
+       gatorfs_create_ro_ulong(sb, dir, "key", &netdrv_key);
+
+       dir = gatorfs_mkdir(sb, root, "Linux_net_rx");
+       if (!dir) {
+               return -1;
+       }
+       gatorfs_create_ulong(sb, dir, "enabled", &netrx_enabled);
+       gatorfs_create_ro_ulong(sb, dir, "key", &netrx_key);
+
+       dir = gatorfs_mkdir(sb, root, "Linux_net_tx");
+       if (!dir) {
+               return -1;
+       }
+       gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled);
+       gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key);
+
+       return 0;
+}
+
+static int gator_events_net_init(int *key)
+{
+       netdrv_key = *key;
+       *key = *key + 1;
+       netrx_key = *key;
+       *key = *key + 1;
+       nettx_key = *key;
+       *key = *key + 1;
+
+       netdrv_enabled = 0;
+       netrx_enabled = 0;
+       nettx_enabled = 0;
+
+       return 0;
+}
+
+static int gator_events_net_start(void)
+{
+       get_network_stats(NULL);
+       netPrev[NETDRV] = 0;
+       netPrev[NETRX] = rx_total;
+       netPrev[NETTX] = tx_total;
+       return 0;
+}
+
+static void gator_events_net_stop(void)
+{
+       netdrv_enabled = 0;
+       netrx_enabled = 0;
+       nettx_enabled = 0;
+}
+
+static int gator_events_net_read(int **buffer)
+{
+       int len, drv_delta, rx_delta, tx_delta;
+
+       if (raw_smp_processor_id() != 0)
+               return 0;
+
+       schedule_work(&wq_get_stats);
+       calculate_delta(&drv_delta, &rx_delta, &tx_delta);
+
+       len = 0;
+       if (netdrv_enabled) {
+               netGet[len++] = netdrv_key;
+               netGet[len++] = drv_delta;
+       }
+
+       if (netrx_enabled) {
+               netGet[len++] = netrx_key;
+               netGet[len++] = rx_delta;
+       }
+
+       if (nettx_enabled) {
+               netGet[len++] = nettx_key;
+               netGet[len++] = tx_delta;
+       }
+
+       if (buffer)
+               *buffer = netGet;
+
+       return len;
+}
+
+int gator_events_net_install(gator_interface *gi) {
+       gi->create_files = gator_events_net_create_files;
+       gi->init = gator_events_net_init;
+       gi->start = gator_events_net_start;
+       gi->stop = gator_events_net_stop;
+       gi->read = gator_events_net_read;
+       gator_net_traffic++;
+       return 0;
+}
index 57b710ab67c4dd390b3aca65895cf924110870ca..138b7e4a64ce3a20705b2b91a9886e6090b03b99 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,15 +7,8 @@
  *
  */
 
-#include <linux/version.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/dcookies.h>
-#include <trace/events/sched.h>
-
 #include "gator.h"
-#include "gator_trace.h"
+#include <trace/events/sched.h>
 
 #define SCHED_SWITCH   0
 #define SCHED_TOTAL            (SCHED_SWITCH+1)
index 6748448fd45b11c08a8d4e405c68b32db137fc01..60b09cb881364bb26ac1b0d0234d05a1ff2a6f3a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,20 +7,13 @@
  *
  */
 
-static unsigned long gator_protocol_version = 2;
+static unsigned long gator_protocol_version = 3;
 
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/fs.h>
+#include "gator.h"
+#include <linux/slab.h>
+#include <linux/cpu.h>
 #include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/dcookies.h>
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 
@@ -42,12 +35,11 @@ static unsigned long gator_protocol_version = 2;
 #error kernels prior to 2.6.32 are not supported
 #endif
 
-#include "gator.h"
-
 /******************************************************************************
  * DEFINES
  ******************************************************************************/
-#define BUFFER_SIZE_DEFAULT            131072
+#define BUFFER_SIZE_DEFAULT            262144
+#define SYNC_FREQ_DEFAULT              1000
 
 #define NO_COOKIE                              0UL
 #define INVALID_COOKIE                 ~0UL
@@ -61,6 +53,7 @@ static unsigned long gator_protocol_version = 2;
 #define PROTOCOL_SCHEDULER_TRACE       11
 #define PROTOCOL_COUNTERS                      13
 #define PROTOCOL_ANNOTATE                      15
+#define PROTOCOL_CPU_SYNC                      17
 
 #if defined(__arm__)
 #define PC_REG regs->ARM_pc
@@ -71,19 +64,30 @@ static unsigned long gator_protocol_version = 2;
 /******************************************************************************
  * PER CPU
  ******************************************************************************/
+static unsigned long gator_cpu_cores;
 static unsigned long gator_buffer_size;
 static unsigned long gator_backtrace_depth;
 
 static unsigned long gator_started;
 static unsigned long gator_buffer_opened;
 static unsigned long gator_timer_count;
-static unsigned long gator_dump;
+static unsigned long gator_sync_freq;
+static int gator_master_tick;
 static DEFINE_MUTEX(start_mutex);
 static DEFINE_MUTEX(gator_buffer_mutex);
+
+unsigned long gator_net_traffic;
+
+#define COMMIT_SIZE            128
+#define COMMIT_MASK            (COMMIT_SIZE-1)
+static DEFINE_SPINLOCK(gator_commit_lock);
+static int *gator_commit;
+static int gator_commit_read;
+static int gator_commit_write;
+
 static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
-/* atomic_t because wait_event checks it outside of gator_buffer_mutex */
-static DEFINE_PER_CPU(atomic_t, gator_buffer_ready);
-static DEFINE_PER_CPU(int, gator_tick);
+static DEFINE_PER_CPU(int, gator_cpu_sync);
+static DEFINE_PER_CPU(int, gator_cpu_tick);
 static DEFINE_PER_CPU(int, gator_first_time);
 
 /******************************************************************************
@@ -115,6 +119,32 @@ u32 gator_cpuid(void)
        return (val >> 4) & 0xfff;
 }
 #endif
+
+/******************************************************************************
+ * Commit interface
+ ******************************************************************************/
+static int buffer_commit_ready(void)
+{
+       return (gator_commit_read != gator_commit_write);
+}
+
+static void buffer_commit_read(int *cpu, int *readval, int *writeval)
+{
+       int read = gator_commit_read;
+       *cpu      = gator_commit[read+0];
+       *readval  = gator_commit[read+1];
+       *writeval = gator_commit[read+2];
+       gator_commit_read = (read + 4) & COMMIT_MASK;
+}
+
+static void buffer_commit_write(int cpu, int readval, int writeval) {
+       int write = gator_commit_write;
+       gator_commit[write+0] = cpu;
+       gator_commit[write+1] = readval;
+       gator_commit[write+2] = writeval;
+       gator_commit_write = (write + 4) & COMMIT_MASK;
+}
+
 /******************************************************************************
  * Buffer management
  ******************************************************************************/
@@ -123,7 +153,6 @@ static uint32_t use_buffer_mask;
 static DEFINE_PER_CPU(int, use_buffer_seq);
 static DEFINE_PER_CPU(int, use_buffer_read);
 static DEFINE_PER_CPU(int, use_buffer_write);
-static DEFINE_PER_CPU(int, use_buffer_commit);
 static DEFINE_PER_CPU(char *, use_buffer);
 
 static void gator_buffer_write_packed_int(int cpu, unsigned int x)
@@ -193,38 +222,46 @@ static void gator_buffer_header(int cpu)
        gator_buffer_write_packed_int(cpu, PROTOCOL_FRAME);
        gator_buffer_write_packed_int(cpu, cpu);
        gator_buffer_write_packed_int(cpu, per_cpu(use_buffer_seq, cpu));
+       per_cpu(use_buffer_seq, cpu)++;
 }
 
 static void gator_buffer_commit(int cpu)
 {
-       per_cpu(use_buffer_commit, cpu) = per_cpu(use_buffer_write, cpu);
-
-       per_cpu(use_buffer_seq, cpu)++;
+       buffer_commit_write(cpu, per_cpu(use_buffer_read, cpu), per_cpu(use_buffer_write, cpu));
+       per_cpu(use_buffer_read, cpu) = per_cpu(use_buffer_write, cpu);
        gator_buffer_header(cpu);
-
-       atomic_set(&per_cpu(gator_buffer_ready, cpu), 1);
        wake_up(&gator_buffer_wait);
 }
 
-static void gator_buffer_check(int cpu)
+static void gator_buffer_check(int cpu, int tick)
 {
-       int commit = 0;
-       int available = per_cpu(use_buffer_write, cpu) - per_cpu(use_buffer_read, cpu);
-       if (available < 0) {
-               available += use_buffer_size;
-       }
-
-       if (!cpu && gator_dump) {
-               gator_dump = 0;
-               commit = 1;
-       } else if (available >= ((use_buffer_size * 3) / 4)) {
-               commit = 1;
-       } else if (cpu && (per_cpu(use_buffer_seq, cpu) < per_cpu(use_buffer_seq, 0))) {
-               commit = 1;
-       }
-
-       if (commit) {
+       if (gator_sync_freq && !(tick % gator_sync_freq)) {
+               int c, sync;
+               spin_lock(&gator_commit_lock);
+               // synchronize, if all online cpus have the same tick waypoint
+               sync = per_cpu(gator_cpu_sync, cpu) = per_cpu(gator_cpu_tick, cpu);
+               for_each_online_cpu(c) {
+                       if (sync != per_cpu(gator_cpu_sync, c)) {
+                               sync = 0;
+                               break;
+                       }
+               }
+               if (sync) {
+                       gator_buffer_write_packed_int(cpu, PROTOCOL_CPU_SYNC);
+               }
+               // commit the buffer
                gator_buffer_commit(cpu);
+               spin_unlock(&gator_commit_lock);
+       } else {
+               int available = per_cpu(use_buffer_write, cpu) - per_cpu(use_buffer_read, cpu);
+               if (available < 0) {
+                       available += use_buffer_size;
+               }
+               if (available >= ((use_buffer_size * 3) / 4)) {
+                       spin_lock(&gator_commit_lock);
+                       gator_buffer_commit(cpu);
+                       spin_unlock(&gator_commit_lock);
+               }
        }
 }
 
@@ -305,11 +342,11 @@ static void gator_write_annotate(int cpu, int len, int *buffer)
  ******************************************************************************/
 static gator_interface *gi = NULL;
 
-static void gator_timer_interrupt(unsigned int ticks)
+static void gator_timer_interrupt(void)
 {
        struct pt_regs * const regs = get_irq_regs();
        int cpu = raw_smp_processor_id();
-       int *buffer, len;
+       int *buffer, len, tick;
        gator_interface *i;
 
        // check full backtrace has enough space, otherwise may
@@ -322,7 +359,6 @@ static void gator_timer_interrupt(unsigned int ticks)
                                i->read(NULL);
                        }
                }
-               per_cpu(gator_tick, cpu) += ticks;
                return;
        }
 
@@ -354,52 +390,95 @@ static void gator_timer_interrupt(unsigned int ticks)
        gator_add_sample(cpu, regs);
 
        // Timer Tick
-       gator_write_packet(cpu, PROTOCOL_END_TICK, 1, &per_cpu(gator_tick, cpu));
-       per_cpu(gator_tick, cpu) += ticks;
+       tick = per_cpu(gator_cpu_tick, cpu);
+       if (tick == gator_master_tick) {
+               tick++;
+               per_cpu(gator_cpu_tick, cpu) = gator_master_tick = tick;
+       } else {
+               per_cpu(gator_cpu_tick, cpu) = tick = gator_master_tick;
+       }
+       gator_write_packet(cpu, PROTOCOL_END_TICK, 1, &tick);
 
-       // Check and commit
-       gator_buffer_check(cpu);
+       // Check and commit; generally, commit is set to occur once per second
+       gator_buffer_check(cpu, tick);
 }
 
 /******************************************************************************
  * hrtimer
  ******************************************************************************/
 DEFINE_PER_CPU(struct hrtimer, percpu_hrtimer);
-extern void gator_timer_stop(void);
+DEFINE_PER_CPU(int, hrtimer_is_active);
 static int hrtimer_running;
 static ktime_t profiling_interval;
-static atomic_t num_active_timers;
 
 static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer)
 {
-       unsigned int ticks = (unsigned int)hrtimer_forward_now(hrtimer, profiling_interval);
-       gator_timer_interrupt(ticks);
+       hrtimer_forward_now(hrtimer, profiling_interval);
+       gator_timer_interrupt();
        return HRTIMER_RESTART;
 }
 
-int gator_timer_init(void)
+static int gator_timer_init(void)
 {
        return 0;
 }
 
-static void __gator_timer_start(void *unused)
+static void __gator_timer_offline(void *unused)
 {
        int cpu = smp_processor_id();
+       if (per_cpu(hrtimer_is_active, cpu)) {
+               gator_interface *i;
+               struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
+               hrtimer_cancel(hrtimer);
+               per_cpu(hrtimer_is_active, cpu) = 0;
+               gator_buffer_commit(cpu);
 
-       struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
-       hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hrtimer->function = gator_hrtimer_notify;
-       hrtimer_start(hrtimer, profiling_interval, HRTIMER_MODE_REL_PINNED);
-       atomic_inc(&num_active_timers);
+               // offline any events
+               for (i = gi; i != NULL; i = i->next) {
+                       if (i->offline) {
+                               i->offline();
+                       }
+               }
+       }
+}
 
-       per_cpu(gator_first_time, cpu) = 1;
-       per_cpu(gator_tick, cpu) = 0;
+static void gator_timer_offline(void)
+{
+       if (hrtimer_running) {
+               hrtimer_running = 0;
+
+               on_each_cpu(__gator_timer_offline, NULL, 1);
+
+               // output a final sync point
+               gator_buffer_write_packed_int(0, PROTOCOL_CPU_SYNC);
+               gator_buffer_commit(0);
+       }
 }
 
-int gator_timer_start(unsigned long setup)
+static void __gator_timer_online(void *unused)
 {
-       atomic_set(&num_active_timers, 0);
+       int cpu = smp_processor_id();
+       if (!per_cpu(hrtimer_is_active, cpu)) {
+               gator_interface *i;
+               struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
+               hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               hrtimer->function = gator_hrtimer_notify;
+               hrtimer_start(hrtimer, profiling_interval, HRTIMER_MODE_REL_PINNED);
+               per_cpu(gator_cpu_tick, cpu) = 0;
+               per_cpu(gator_first_time, cpu) = 1;
+               per_cpu(hrtimer_is_active, cpu) = 1;
+
+               // online any events
+               for (i = gi; i != NULL; i = i->next) {
+                       if (i->online) {
+                               i->online();
+                       }
+               }
+       }
+}
 
+int gator_timer_online(unsigned long setup)
+{
        if (!setup) {
                pr_err("gator: cannot start due to a system tick value of zero");
                return -1;
@@ -414,37 +493,12 @@ int gator_timer_start(unsigned long setup)
        profiling_interval = ns_to_ktime(1000000000UL / setup);
 
        // timer interrupt
-       on_each_cpu(__gator_timer_start, NULL, 1);
-
-       if (atomic_read(&num_active_timers) != num_present_cpus()) {
-               pr_err("gator: %d timer(s) started yet %d cpu(s) detected, please bring all cpus online manually and restart\n", atomic_read(&num_active_timers), nr_cpu_ids);
-               gator_timer_stop();
-               return -1;
-       }
+       gator_master_tick = 0;
+       on_each_cpu(__gator_timer_online, NULL, 1);
 
        return 0;
 }
 
-void __gator_timer_stop(void *unused)
-{
-       struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, smp_processor_id());
-       hrtimer_cancel(hrtimer);
-       atomic_dec(&num_active_timers);
-}
-
-void gator_timer_stop(void)
-{
-       if (hrtimer_running) {
-               int previously_running = atomic_read(&num_active_timers);
-               hrtimer_running = 0;
-               on_each_cpu(__gator_timer_stop, NULL, 1);
-               if (atomic_read(&num_active_timers) != 0) {
-                       pr_err("gator: %d timers stopped yet %d were running, it is advised to quit and restart gatord", previously_running - atomic_read(&num_active_timers), previously_running);
-                       atomic_set(&num_active_timers, 0);
-               }
-       }
-}
-
 static uint64_t gator_get_time(void)
 {
        struct timespec ts;
@@ -456,6 +510,42 @@ static uint64_t gator_get_time(void)
        return timestamp;
 }
 
+/******************************************************************************
+ * cpu online notifier
+ ******************************************************************************/
+static int __cpuinit gator_cpu_notify(struct notifier_block *self,
+                                                                                       unsigned long action, void *hcpu)
+{
+       long cpu = (long)hcpu;
+
+       switch (action) {
+               case CPU_ONLINE:
+               case CPU_ONLINE_FROZEN:
+                       smp_call_function_single(cpu, __gator_timer_online, NULL, 1);
+                       break;
+               case CPU_DOWN_PREPARE:
+               case CPU_DOWN_PREPARE_FROZEN:
+                       smp_call_function_single(cpu, __gator_timer_offline, NULL, 1);
+                       break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata gator_cpu_notifier = {
+       .notifier_call = gator_cpu_notify,
+};
+
+static int gator_notifier_start(void)
+{
+       return register_hotcpu_notifier(&gator_cpu_notifier);
+}
+
+static void gator_notifier_stop(void)
+{
+       unregister_hotcpu_notifier(&gator_cpu_notifier);
+}
+
 /******************************************************************************
  * Main
  ******************************************************************************/
@@ -470,6 +560,8 @@ int gator_event_install(int (*event_install)(gator_interface *))
        ni->init = NULL;
        ni->start = NULL;
        ni->stop = NULL;
+       ni->online = NULL;
+       ni->offline = NULL;
        ni->read = NULL;
        ni->next = NULL;
 
@@ -538,11 +630,15 @@ static int gator_start(void)
                goto annotate_failure;
        if (gator_trace_sched_start())
                goto sched_failure;
-       if (gator_timer_start(gator_timer_count))
+       if (gator_timer_online(gator_timer_count))
                goto timer_failure;
+       if (gator_notifier_start())
+               goto notifier_failure;
 
        return 0;
 
+notifier_failure:
+       gator_timer_offline();
 timer_failure:
        gator_trace_sched_stop();
 sched_failure:
@@ -560,17 +656,19 @@ static void gator_stop(void)
 {
        gator_interface *i;
 
-       // stop all interrupt callback reads before tearing down other interfaces
-       gator_timer_stop();
-       gator_annotate_stop();
-       gator_trace_sched_stop();
-
        // stop all events
        for (i = gi; i != NULL; i = i->next) {
                if (i->stop) {
                        i->stop();
                }
        }
+
+       gator_annotate_stop();
+       gator_trace_sched_stop();
+
+       // stop all interrupt callback reads before tearing down other interfaces
+       gator_timer_offline();
+       gator_notifier_stop();
 }
 
 static void gator_exit(void)
@@ -604,18 +702,28 @@ static int gator_op_setup(void)
                goto setup_error;
        }
 
-       for_each_possible_cpu(cpu) {
+       gator_net_traffic = 0;
+
+       gator_commit_read = gator_commit_write = 0;
+       gator_commit = vmalloc(COMMIT_SIZE * sizeof(int));
+       if (!gator_commit) {
+               err = -ENOMEM;
+               goto setup_error;
+       }
+
+       for_each_present_cpu(cpu) {
                per_cpu(use_buffer, cpu) = vmalloc(use_buffer_size);
                if (!per_cpu(use_buffer, cpu)) {
                        err = -ENOMEM;
                        goto setup_error;
                }
 
-               atomic_set(&per_cpu(gator_buffer_ready, cpu), 0);
+               per_cpu(gator_cpu_sync, cpu) = 0;
+               per_cpu(gator_cpu_tick, cpu) = 0;
+
                per_cpu(use_buffer_seq, cpu) = 0;
                per_cpu(use_buffer_read, cpu) = 0;
                per_cpu(use_buffer_write, cpu) = 0;
-               per_cpu(use_buffer_commit, cpu) = 0;
                gator_buffer_header(cpu);
        }
 
@@ -646,8 +754,6 @@ static int gator_op_start(void)
 /* echo 0>/dev/gator/enable */
 static void gator_op_stop(void)
 {
-       int cpu;
-
        mutex_lock(&start_mutex);
 
        if (gator_started) {
@@ -655,11 +761,6 @@ static void gator_op_stop(void)
 
                mutex_lock(&gator_buffer_mutex);
 
-               /* wake up the daemon to read what remains */
-               for_each_possible_cpu(cpu) {
-                       gator_buffer_commit(cpu);
-                       atomic_set(&per_cpu(gator_buffer_ready, cpu), 1);
-               }
                gator_started = 0;
                cookies_release();
                wake_up(&gator_buffer_wait);
@@ -676,14 +777,16 @@ static void gator_shutdown(void)
 
        mutex_lock(&start_mutex);
 
-       for_each_possible_cpu(cpu) {
+       vfree(gator_commit);
+       gator_commit = NULL;
+
+       for_each_present_cpu(cpu) {
                mutex_lock(&gator_buffer_mutex);
                vfree(per_cpu(use_buffer, cpu));
                per_cpu(use_buffer, cpu) = NULL;
                per_cpu(use_buffer_seq, cpu) = 0;
                per_cpu(use_buffer_read, cpu) = 0;
                per_cpu(use_buffer_write, cpu) = 0;
-               per_cpu(use_buffer_commit, cpu) = 0;
                mutex_unlock(&gator_buffer_mutex);
        }
 
@@ -748,15 +851,6 @@ static int event_buffer_open(struct inode *inode, struct file *file)
        if (test_and_set_bit_lock(0, &gator_buffer_opened))
                return -EBUSY;
 
-       /* Register as a user of dcookies
-        * to ensure they persist for the lifetime of
-        * the open event file
-        */
-       err = -EINVAL;
-       file->private_data = dcookie_register();
-       if (!file->private_data)
-               goto out;
-
        if ((err = gator_op_setup()))
                goto fail;
 
@@ -767,35 +861,18 @@ static int event_buffer_open(struct inode *inode, struct file *file)
        return 0;
 
 fail:
-       dcookie_unregister(file->private_data);
-out:
        __clear_bit_unlock(0, &gator_buffer_opened);
        return err;
 }
 
 static int event_buffer_release(struct inode *inode, struct file *file)
 {
-       int cpu;
        gator_op_stop();
        gator_shutdown();
-       dcookie_unregister(file->private_data);
-       for_each_possible_cpu(cpu) {
-               atomic_set(&per_cpu(gator_buffer_ready, cpu), 0);
-       }
        __clear_bit_unlock(0, &gator_buffer_opened);
        return 0;
 }
 
-static int event_buffer_ready(void)
-{
-       int cpu;
-       for_each_possible_cpu(cpu) {
-               if (atomic_read(&per_cpu(gator_buffer_ready, cpu)))
-                       return cpu;
-       }
-       return -1;
-}
-
 static ssize_t event_buffer_read(struct file *file, char __user *buf,
                                 size_t count, loff_t *offset)
 {
@@ -808,18 +885,17 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
        if (count != use_buffer_size || *offset)
                return -EINVAL;
 
-       wait_event_interruptible(gator_buffer_wait, event_buffer_ready() >= 0 || !gator_started);
-       cpu = event_buffer_ready();
+       // sleep until the condition is true or a signal is received
+       // the condition is checked each time gator_buffer_wait is woken up
+       wait_event_interruptible(gator_buffer_wait, buffer_commit_ready() || !gator_started);
 
        if (signal_pending(current))
                return -EINTR;
 
-       if (cpu < 0)
+       if (!buffer_commit_ready())
                return 0;
 
-       /* should not happen */
-       if (!atomic_read(&per_cpu(gator_buffer_ready, cpu)))
-               return -EAGAIN;
+       buffer_commit_read(&cpu, &read, &commit);
 
        mutex_lock(&gator_buffer_mutex);
 
@@ -832,8 +908,6 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
        }
 
        /* determine the size of two halves */
-       commit = per_cpu(use_buffer_commit, cpu);
-       read = per_cpu(use_buffer_read, cpu);
        length1 = commit - read;
        length2 = 0;
        buffer1 = &(per_cpu(use_buffer, cpu)[read]);
@@ -857,16 +931,15 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
                }
        }
 
-       /* update position */
        retval = length1 + length2;
-       per_cpu(use_buffer_read, cpu) = (read + retval) & use_buffer_mask;
-
-       atomic_set(&per_cpu(gator_buffer_ready, cpu), 0);
 
        /* kick just in case we've lost an SMP event */
        wake_up(&gator_buffer_wait);
 
 out:
+       // do not adjust network stats if in non-streaming buffer mode
+       if (gator_sync_freq)
+               gator_net_traffic += retval;
        mutex_unlock(&gator_buffer_mutex);
        return retval;
 }
@@ -922,17 +995,24 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
 {
        struct dentry *dir;
        gator_interface *i;
+       int cpu;
 
        /* reinitialize default values */
+       gator_cpu_cores = 0;
+       for_each_present_cpu(cpu) {
+               gator_cpu_cores++;
+       }
        gator_buffer_size =     BUFFER_SIZE_DEFAULT;
+       gator_sync_freq = SYNC_FREQ_DEFAULT;
 
        gatorfs_create_file(sb, root, "enable", &enable_fops);
        gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops);
        gatorfs_create_file(sb, root, "backtrace_depth", &depth_fops);
        gatorfs_create_file(sb, root, "cpu_type", &cpu_type_fops);
+       gatorfs_create_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
        gatorfs_create_ulong(sb, root, "buffer_size", &gator_buffer_size);
        gatorfs_create_ulong(sb, root, "tick", &gator_timer_count);
-       gatorfs_create_ulong(sb, root, "dump", &gator_dump);
+       gatorfs_create_ulong(sb, root, "sync_freq", &gator_sync_freq);
        gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version);
 
        // Annotate interface
@@ -975,6 +1055,7 @@ static void __exit gator_module_exit(void)
 #ifdef GATOR_DEBUG
        pr_err("gator_module_exit");
 #endif
+       tracepoint_synchronize_unregister();
        gatorfs_unregister();
        if (gator_initialized) {
                gator_initialized = 0;
index 1328d88076d230d4d262631f6ed12439363abc51..19d8d89cb4b4dea17d6e994144bfc28f8bef1db9 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,14 +7,8 @@
  *
  */
 
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/version.h>
-#include <linux/hardirq.h>
 #include <trace/events/sched.h>
-
-#include "gator_trace.h"
+#include "gator.h"
 
 #define SCHED_TIMER_EVENT              0
 #define SCHED_WAIT_TASK                        1
@@ -147,7 +141,7 @@ int gator_trace_sched_start(void)
 {
        int cpu;
 
-       for_each_possible_cpu(cpu) {
+       for_each_present_cpu(cpu) {
                per_cpu(theSchedSel, cpu) = 0;
                per_cpu(theSchedPos, cpu) = 0;
                per_cpu(theSchedErr, cpu) = 0;
@@ -217,7 +211,7 @@ void gator_trace_sched_stop(void)
        GATOR_UNREGISTER_TRACE(sched_process_fork);
        pr_debug("gator: unregistered tracepoints\n");
 
-       for_each_possible_cpu(cpu) {
+       for_each_present_cpu(cpu) {
                kfree(per_cpu(theSchedBuf, cpu)[0]);
                kfree(per_cpu(theSchedBuf, cpu)[1]);
                per_cpu(theSchedBuf, cpu)[0] = NULL;