diff options
-rwxr-xr-x | runtime/probes/os_timer/build | 2 | ||||
-rw-r--r-- | runtime/probes/os_timer/os_timer.c | 138 | ||||
-rwxr-xr-x | runtime/probes/os_timer/stp | 42 | ||||
-rw-r--r-- | runtime/probes/os_timer/targets | 1 |
4 files changed, 183 insertions, 0 deletions
diff --git a/runtime/probes/os_timer/build b/runtime/probes/os_timer/build new file mode 100755 index 00000000..f3e83244 --- /dev/null +++ b/runtime/probes/os_timer/build @@ -0,0 +1,2 @@ +#!/bin/bash +../build_probe $* diff --git a/runtime/probes/os_timer/os_timer.c b/runtime/probes/os_timer/os_timer.c new file mode 100644 index 00000000..f40b4168 --- /dev/null +++ b/runtime/probes/os_timer/os_timer.c @@ -0,0 +1,138 @@ +/* Use the os timer as a poor-man's time based profiler for a UP system */ + +/* Demonstrates the beginnings of a generic framework for */ +/* asynchronous probes using the runtime */ + +/* @todo NOTE: the statement: regs = task_pt_regs(current); */ +/* isn't working in the way I would expect. The timer callback */ +/* happens, but I don't get a reasonable value in regs->eip */ +/* Can this routine be called during the timer callback? */ + +/* os includes */ +#include "linux/timer.h" + +/* define this if you don't want to use relayfs. Normally */ +/* you want relayfs, unless you need a realtime stream of data */ + +/* #define STP_NETLINK_ONLY */ + +/* How many strings to allocate. see strings.c. Default is 0. */ +#define STP_NUM_STRINGS 1 + +/* maximum size for a string. default is 2048 */ +#define STP_STRING_SIZE 2048 + +/* size of strings saved in maps */ +#define MAP_STRING_LENGTH 256 + +/* width of histograms. Default 50 */ +#define HIST_WIDTH 50 + +/* always include this. Put all non-map defines above it. */ +#include "runtime.h" + +/* since we don't have aggregation maps yet, try regular maps */ +#define NEED_INT64_VALS + +#define KEY1_TYPE INT64 +#include "map-keys.c" + +#include "map.c" + +#include "stat.c" +#include "stack.c" + +MODULE_DESCRIPTION("SystemTap probe: os_timer"); +MODULE_AUTHOR("Charles Spirakis <charles.spirakis@intel.com>"); + +Stat addr; +MAP cur_addr; + +/* A generic asynchorous probe entry point */ +void inst_async(struct pt_regs *regs) +{ + unsigned long ip = regs->eip; + + /* can we generate a histogram of ip addresses seen? */ + _stp_stat_add(addr, 1); + + /* Create a map of interrupted addresses seen */ + /* really want a map of image name / address */ + _stp_map_key_int64(cur_addr, ip); + _stp_map_add_int64(cur_addr, 1); + + /* Need _stp_stack() and _stp_ustack()? */ + /* _stp_image() and aggregation maps */ +} + +static struct timer_list timer; + +/* Helper function to convert from os timer callback into */ +/* generic asynchronous entry point form */ +static void os_timer_callback(unsigned long val) +{ + struct pt_regs *regs; + + /* setup the next timeout now so it doesn't drift */ + /* due to processing the async probe code */ + mod_timer(&timer, jiffies + val); + + /* determine pt_regs from the kernel stack */ + /* @todo This doesn't seem to get a reasonable pt_regs pointer */ + /* based on the value of regs->eip. However, KSTK_EIP() in */ + /* include/asm/processor.h implies regs->eip is valid... */ + regs = task_pt_regs(current); + + /* Call the asynchronous probe with a ptregs struct */ + inst_async(regs); +} + +/* called when the module loads. */ +int init_module(void) +{ + int ret; + + TRANSPORT_OPEN; + + addr = _stp_stat_init(HIST_LINEAR, 0, 1000, 100); + + cur_addr = _stp_map_new_int64(1000, INT64); + + /* register the os_timer */ + init_timer(&timer); + + timer.expires = jiffies + 50; + timer.function = os_timer_callback; + + /* data is usd for defining when the next timeout shoud occur */ + timer.data = 50; + + add_timer(&timer); + + ret = 0; + + return ret; +} + +static void probe_exit (void) +{ + /* unregister the os_timer */ + del_timer_sync(&timer); + + /* print out any colledted data, etc */ + _stp_printf ("os timer done. Currently an issue with tast_pt_regs() call so data below may not be valid\n"); + _stp_stat_print (addr, "addr: count:%C sum:%S avg:%A min:%m max:%M\n%H", 0); + + _stp_map_print (cur_addr, "Count: %d\tInterrupts: %1P"); + _stp_map_del(cur_addr); + + _stp_print_flush(); +} + +/* required */ +void cleanup_module(void) +{ + _stp_transport_close(); +} + +MODULE_LICENSE("GPL"); diff --git a/runtime/probes/os_timer/stp b/runtime/probes/os_timer/stp new file mode 100755 index 00000000..4baf70ff --- /dev/null +++ b/runtime/probes/os_timer/stp @@ -0,0 +1,42 @@ +#!/bin/bash +if [ -n "$1" ] +then + modulename=$1 +else + echo "Usage: stp modulename" + exit +fi + +RELAYFS=`lsmod | grep relayfs |awk '{print $1}'` +if [ "$RELAYFS" != "relayfs" ] +then + /sbin/insmod ../../relayfs/relayfs.ko +fi + +if [ ! -d "/mnt/relay" ] +then + mkdir /mnt/relay +fi + +MOUNT=`mount | grep relayfs |awk '{print $1}'` +if [ "$MOUNT" != "relayfs" ] +then + mount -t relayfs relayfs /mnt/relay +fi + +STP_CONTROL=`lsmod | grep stp_control |awk '{print $1}'` +if [ "$STP_CONTROL" != "stp_control" ] +then + /sbin/insmod ../../transport/stp-control.ko +fi + +#/sbin/insmod $modulename + +# print to screen only +#../../stpd/stpd -p $modulename + +# print to screen and log to files (file logging only if #define STP_NETLINK_ONLY commented out in module) +../../stpd/stpd $modulename + +# no screen, log to files (file logging only if #define STP_NETLINK_ONLY commented out in module) +#../../stpd/stpd -q $modulename diff --git a/runtime/probes/os_timer/targets b/runtime/probes/os_timer/targets new file mode 100644 index 00000000..879d3afc --- /dev/null +++ b/runtime/probes/os_timer/targets @@ -0,0 +1 @@ +os_timer |