diff options
Diffstat (limited to 'litmus/trace.c')
-rw-r--r-- | litmus/trace.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/litmus/trace.c b/litmus/trace.c new file mode 100644 index 000000000000..5735d28f5e30 --- /dev/null +++ b/litmus/trace.c | |||
@@ -0,0 +1,102 @@ | |||
1 | #include <linux/module.h> | ||
2 | |||
3 | #include <litmus/ftdev.h> | ||
4 | #include <litmus/litmus.h> | ||
5 | #include <litmus/trace.h> | ||
6 | |||
7 | /******************************************************************************/ | ||
8 | /* Allocation */ | ||
9 | /******************************************************************************/ | ||
10 | |||
11 | static struct ftdev overhead_dev; | ||
12 | |||
13 | #define trace_ts_buf overhead_dev.minor[0].buf | ||
14 | |||
15 | static unsigned int ts_seq_no = 0; | ||
16 | |||
17 | static inline void __save_timestamp_cpu(unsigned long event, | ||
18 | uint8_t type, uint8_t cpu) | ||
19 | { | ||
20 | unsigned int seq_no; | ||
21 | struct timestamp *ts; | ||
22 | seq_no = fetch_and_inc((int *) &ts_seq_no); | ||
23 | if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) { | ||
24 | ts->event = event; | ||
25 | ts->timestamp = ft_timestamp(); | ||
26 | ts->seq_no = seq_no; | ||
27 | ts->cpu = cpu; | ||
28 | ts->task_type = type; | ||
29 | ft_buffer_finish_write(trace_ts_buf, ts); | ||
30 | } | ||
31 | } | ||
32 | |||
33 | static inline void __save_timestamp(unsigned long event, | ||
34 | uint8_t type) | ||
35 | { | ||
36 | __save_timestamp_cpu(event, type, raw_smp_processor_id()); | ||
37 | } | ||
38 | |||
39 | feather_callback void save_timestamp(unsigned long event) | ||
40 | { | ||
41 | __save_timestamp(event, TSK_UNKNOWN); | ||
42 | } | ||
43 | |||
44 | feather_callback void save_timestamp_def(unsigned long event, | ||
45 | unsigned long type) | ||
46 | { | ||
47 | __save_timestamp(event, (uint8_t) type); | ||
48 | } | ||
49 | |||
50 | feather_callback void save_timestamp_task(unsigned long event, | ||
51 | unsigned long t_ptr) | ||
52 | { | ||
53 | int rt = is_realtime((struct task_struct *) t_ptr); | ||
54 | __save_timestamp(event, rt ? TSK_RT : TSK_BE); | ||
55 | } | ||
56 | |||
57 | feather_callback void save_timestamp_cpu(unsigned long event, | ||
58 | unsigned long cpu) | ||
59 | { | ||
60 | __save_timestamp_cpu(event, TSK_UNKNOWN, cpu); | ||
61 | } | ||
62 | |||
63 | /******************************************************************************/ | ||
64 | /* DEVICE FILE DRIVER */ | ||
65 | /******************************************************************************/ | ||
66 | |||
67 | /* | ||
68 | * should be 8M; it is the max we can ask to buddy system allocator (MAX_ORDER) | ||
69 | * and we might not get as much | ||
70 | */ | ||
71 | #define NO_TIMESTAMPS (2 << 11) | ||
72 | |||
73 | #define FT_TRACE_MAJOR 252 | ||
74 | |||
75 | static int alloc_timestamp_buffer(struct ftdev* ftdev, unsigned int idx) | ||
76 | { | ||
77 | unsigned int count = NO_TIMESTAMPS; | ||
78 | while (count && !trace_ts_buf) { | ||
79 | printk("time stamp buffer: trying to allocate %u time stamps.\n", count); | ||
80 | ftdev->minor[idx].buf = alloc_ft_buffer(count, sizeof(struct timestamp)); | ||
81 | count /= 2; | ||
82 | } | ||
83 | return ftdev->minor[idx].buf ? 0 : -ENOMEM; | ||
84 | } | ||
85 | |||
86 | static void free_timestamp_buffer(struct ftdev* ftdev, unsigned int idx) | ||
87 | { | ||
88 | free_ft_buffer(ftdev->minor[idx].buf); | ||
89 | ftdev->minor[idx].buf = NULL; | ||
90 | } | ||
91 | |||
92 | static int __init init_ft_overhead_trace(void) | ||
93 | { | ||
94 | printk("Initializing Feather-Trace overhead tracing device.\n"); | ||
95 | ftdev_init(&overhead_dev, THIS_MODULE); | ||
96 | overhead_dev.minor_cnt = 1; /* only one buffer */ | ||
97 | overhead_dev.alloc = alloc_timestamp_buffer; | ||
98 | overhead_dev.free = free_timestamp_buffer; | ||
99 | return register_ftdev(&overhead_dev, "ft_trace", FT_TRACE_MAJOR); | ||
100 | } | ||
101 | |||
102 | module_init(init_ft_overhead_trace); | ||