1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* 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 <charles.spirakis@intel.com>");
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();
}
|