aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/trace.c
diff options
context:
space:
mode:
authorJeremy Erickson <jerickso@cs.unc.edu>2012-08-30 21:01:47 -0400
committerJeremy Erickson <jerickso@cs.unc.edu>2012-08-30 21:01:47 -0400
commitb1e1fea67bca3796d5f9133a92c300ec4fa93a4f (patch)
tree5cc1336e1fe1d6f93b1067e73e43381dd20db690 /litmus/trace.c
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
Bjoern's Dissertation Code with Priority Donationwip-splitting-omlp-jerickso
Diffstat (limited to 'litmus/trace.c')
-rw-r--r--litmus/trace.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/litmus/trace.c b/litmus/trace.c
new file mode 100644
index 000000000000..39200c8ff74e
--- /dev/null
+++ b/litmus/trace.c
@@ -0,0 +1,213 @@
1#include <linux/sched.h>
2#include <linux/module.h>
3#include <linux/uaccess.h>
4
5#include <litmus/ftdev.h>
6#include <litmus/litmus.h>
7#include <litmus/trace.h>
8
9/******************************************************************************/
10/* Allocation */
11/******************************************************************************/
12
13static struct ftdev overhead_dev;
14
15#define trace_ts_buf overhead_dev.minor[0].buf
16
17static unsigned int ts_seq_no = 0;
18
19static inline void __save_timestamp_cpu(unsigned long event,
20 uint8_t type, uint8_t cpu)
21{
22 unsigned int seq_no;
23 struct timestamp *ts;
24 seq_no = fetch_and_inc((int *) &ts_seq_no);
25 if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) {
26 ts->event = event;
27 ts->timestamp = ft_timestamp();
28 ts->seq_no = seq_no;
29 ts->cpu = cpu;
30 ts->task_type = type;
31 ft_buffer_finish_write(trace_ts_buf, ts);
32 }
33}
34
35static void __add_timestamp_user(struct timestamp *pre_recorded)
36{
37 unsigned int seq_no;
38 struct timestamp *ts;
39 seq_no = fetch_and_inc((int *) &ts_seq_no);
40
41 if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) {
42 *ts = *pre_recorded;
43 ts->seq_no = seq_no;
44 ft_buffer_finish_write(trace_ts_buf, ts);
45 }
46}
47
48static inline void __save_timestamp(unsigned long event,
49 uint8_t type)
50{
51 __save_timestamp_cpu(event, type, raw_smp_processor_id());
52}
53
54/* hack: fake timestamp to user-reported time, and record parts of the PID */
55feather_callback void save_timestamp_time(unsigned long event, unsigned long ptr)
56{
57 uint64_t* time = (uint64_t*) ptr;
58 unsigned int seq_no;
59 struct timestamp *ts;
60 seq_no = fetch_and_inc((int *) &ts_seq_no);
61 if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) {
62 ts->event = event;
63 ts->timestamp = *time;
64 ts->seq_no = seq_no;
65 /* type takes lowest byte of PID */
66 ts->task_type = (uint8_t) current->pid;
67 /* cpu takes second-lowest byte of PID*/
68 ts->cpu = (uint8_t) (current->pid >> 8);
69
70 ft_buffer_finish_write(trace_ts_buf, ts);
71 }
72}
73
74feather_callback void save_timestamp_pid(unsigned long event)
75{
76 /* Abuse existing fields to partially export PID. */
77 __save_timestamp_cpu(event,
78 /* type takes lowest byte of PID */
79 (uint8_t) current->pid,
80 /* cpu takes second-lowest byte of PID*/
81 (uint8_t) (current->pid >> 8));
82}
83
84feather_callback void save_timestamp(unsigned long event)
85{
86 __save_timestamp(event, TSK_UNKNOWN);
87}
88
89feather_callback void save_timestamp_def(unsigned long event,
90 unsigned long type)
91{
92 __save_timestamp(event, (uint8_t) type);
93}
94
95feather_callback void save_timestamp_task(unsigned long event,
96 unsigned long t_ptr)
97{
98 int rt = is_realtime((struct task_struct *) t_ptr);
99 __save_timestamp(event, rt ? TSK_RT : TSK_BE);
100}
101
102feather_callback void save_timestamp_cpu(unsigned long event,
103 unsigned long cpu)
104{
105 __save_timestamp_cpu(event, TSK_UNKNOWN, cpu);
106}
107
108feather_callback void save_task_latency(unsigned long event,
109 unsigned long when_ptr)
110{
111 lt_t now = litmus_clock();
112 lt_t *when = (lt_t*) when_ptr;
113 unsigned int seq_no;
114 int cpu = raw_smp_processor_id();
115 struct timestamp *ts;
116
117 seq_no = fetch_and_inc((int *) &ts_seq_no);
118 if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) {
119 ts->event = event;
120 ts->timestamp = now - *when;
121 ts->seq_no = seq_no;
122 ts->cpu = cpu;
123 ts->task_type = TSK_RT;
124 ft_buffer_finish_write(trace_ts_buf, ts);
125 }
126}
127
128/******************************************************************************/
129/* DEVICE FILE DRIVER */
130/******************************************************************************/
131
132/*
133 * should be 8M; it is the max we can ask to buddy system allocator (MAX_ORDER)
134 * and we might not get as much
135 */
136#define NO_TIMESTAMPS (2 << 16)
137
138static int alloc_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
139{
140 unsigned int count = NO_TIMESTAMPS;
141 while (count && !trace_ts_buf) {
142 printk("time stamp buffer: trying to allocate %u time stamps.\n", count);
143 ftdev->minor[idx].buf = alloc_ft_buffer(count, sizeof(struct timestamp));
144 count /= 2;
145 }
146 return ftdev->minor[idx].buf ? 0 : -ENOMEM;
147}
148
149static void free_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
150{
151 free_ft_buffer(ftdev->minor[idx].buf);
152 ftdev->minor[idx].buf = NULL;
153}
154
155static ssize_t write_timestamp_from_user(struct ft_buffer* buf, size_t len,
156 const char __user *from)
157{
158 ssize_t consumed = 0;
159 struct timestamp ts;
160
161 /* don't give us partial timestamps */
162 if (len % sizeof(ts))
163 return -EINVAL;
164
165 while (len >= sizeof(ts)) {
166 if (copy_from_user(&ts, from, sizeof(ts))) {
167 consumed = -EFAULT;
168 goto out;
169 }
170 len -= sizeof(ts);
171 from += sizeof(ts);
172 consumed += sizeof(ts);
173
174 __add_timestamp_user(&ts);
175 }
176
177out:
178 return consumed;
179}
180
181static int __init init_ft_overhead_trace(void)
182{
183 int err;
184
185 printk("Initializing Feather-Trace overhead tracing device.\n");
186 err = ftdev_init(&overhead_dev, THIS_MODULE, 1, "ft_trace");
187 if (err)
188 goto err_out;
189
190 overhead_dev.alloc = alloc_timestamp_buffer;
191 overhead_dev.free = free_timestamp_buffer;
192 overhead_dev.write = write_timestamp_from_user;
193
194 err = register_ftdev(&overhead_dev);
195 if (err)
196 goto err_dealloc;
197
198 return 0;
199
200err_dealloc:
201 ftdev_exit(&overhead_dev);
202err_out:
203 printk(KERN_WARNING "Could not register ft_trace module.\n");
204 return err;
205}
206
207static void __exit exit_ft_overhead_trace(void)
208{
209 ftdev_exit(&overhead_dev);
210}
211
212module_init(init_ft_overhead_trace);
213module_exit(exit_ft_overhead_trace);