/* 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" /* 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" /* @todo since we don't have aggregation maps yet, try regular maps */ #define VALUE_TYPE INT64 #define KEY1_TYPE STRING #define KEY2_TYPE INT64 #include "map-gen.c" #include "map.c" #include "stat.c" #include "stack.c" MODULE_DESCRIPTION("SystemTap probe: os_timer"); MODULE_AUTHOR("Charles Spirakis "); Stat timing; MAP cur_addr; /* A generic asynchorous probe entry point */ void inst_async(struct pt_regs *regs) { u64 start; u64 end; unsigned long ip; rdtscll(start); ip = REG_IP(regs); /* Create a map of interrupted addresses seen */ /* really want a map of image name / address */ _stp_map_add_sii(cur_addr, current->comm, ip, 1); /* Need _stp_stack() and _stp_ustack()? */ /* _stp_image() and aggregation maps */ rdtscll(end); _stp_stat_add(timing, end - start); } 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 probe_start(void) { timing = _stp_stat_init(HIST_LINEAR, 0, 5000, 250); cur_addr = _stp_map_new_sii(1000); /* 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); return 0; } void probe_exit (void) { /* unregister the os_timer */ del_timer_sync(&timer); /* print out any colledted data, etc */ _stp_printf ("os timer done.\n"); _stp_printf ("WARNING: Currently using task_pt_regs() to get the pt_regs struct\n"); _stp_printf ("during the timer interrupt, but there seems to be issues with that...\n\n"); _stp_stat_print (timing, "timing (cpu cycles): # calls:%C avg:%A min:%m max:%M\n%H", 0); _stp_print("Process\tIp\tCount\n"); _stp_map_print (cur_addr, "%1s\t%2P\t%d"); _stp_map_del(cur_addr); _stp_print_flush(); }