aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2008-09-17 13:29:37 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2008-09-17 13:29:37 -0400
commit364619e98672692ad1f58d96ffab531a304868e5 (patch)
tree8d076778d883efbcc7a32f562f5e822dad92ca5d
parentcc5954a935380af2cf0bec81386f10eb4b425a25 (diff)
Feather-Trace: use ftdev for overhead tracing
Much cleaner code now.
-rw-r--r--include/litmus/trace.h4
-rw-r--r--litmus/trace.c290
2 files changed, 22 insertions, 272 deletions
diff --git a/include/litmus/trace.h b/include/litmus/trace.h
index 2c8e1419de..b8157e88d8 100644
--- a/include/litmus/trace.h
+++ b/include/litmus/trace.h
@@ -23,10 +23,6 @@ struct timestamp {
23 uint8_t task_type; 23 uint8_t task_type;
24}; 24};
25 25
26
27/* buffer holding time stamps - will be provided by driver */
28extern struct ft_buffer* trace_ts_buf;
29
30/* tracing callbacks */ 26/* tracing callbacks */
31feather_callback void save_timestamp(unsigned long event); 27feather_callback void save_timestamp(unsigned long event);
32feather_callback void save_timestamp_def(unsigned long event, unsigned long type); 28feather_callback void save_timestamp_def(unsigned long event, unsigned long type);
diff --git a/litmus/trace.c b/litmus/trace.c
index dadb09d863..6162bb3716 100644
--- a/litmus/trace.c
+++ b/litmus/trace.c
@@ -5,6 +5,8 @@
5#include <asm/uaccess.h> 5#include <asm/uaccess.h>
6#include <linux/module.h> 6#include <linux/module.h>
7 7
8#include <litmus/ftdev.h>
9
8#include <litmus/litmus.h> 10#include <litmus/litmus.h>
9#include <litmus/trace.h> 11#include <litmus/trace.h>
10 12
@@ -12,7 +14,9 @@
12/* Allocation */ 14/* Allocation */
13/******************************************************************************/ 15/******************************************************************************/
14 16
15struct ft_buffer* trace_ts_buf = NULL; 17static struct ftdev overhead_dev;
18
19#define trace_ts_buf overhead_dev.minor[0].buf
16 20
17static unsigned int ts_seq_no = 0; 21static unsigned int ts_seq_no = 0;
18 22
@@ -47,289 +51,39 @@ feather_callback void save_timestamp_task(unsigned long event, unsigned long t_p
47 __save_timestamp(event, rt ? TSK_RT : TSK_BE); 51 __save_timestamp(event, rt ? TSK_RT : TSK_BE);
48} 52}
49 53
50static struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size)
51{
52 struct ft_buffer* buf;
53 size_t total = (size + 1) * count;
54 char* mem;
55 int order = 0, pages = 1;
56
57 buf = kmalloc(sizeof(struct ft_buffer), GFP_KERNEL);
58 if (!buf)
59 return NULL;
60
61 total = (total / PAGE_SIZE) + (total % PAGE_SIZE != 0);
62 while (pages < total) {
63 order++;
64 pages *= 2;
65 }
66
67 mem = (char*) __get_free_pages(GFP_KERNEL, order);
68 if (!mem) {
69 kfree(buf);
70 return NULL;
71 }
72
73 if (!init_ft_buffer(buf, count, size,
74 mem + (count * size), /* markers at the end */
75 mem)) { /* buffer objects */
76 free_pages((unsigned long) mem, order);
77 kfree(buf);
78 return NULL;
79 }
80 return buf;
81}
82
83static void free_ft_buffer(struct ft_buffer* buf)
84{
85 int order = 0, pages = 1;
86 size_t total;
87
88 if (buf) {
89 total = (buf->slot_size + 1) * buf->slot_count;
90 total = (total / PAGE_SIZE) + (total % PAGE_SIZE != 0);
91 while (pages < total) {
92 order++;
93 pages *= 2;
94 }
95 free_pages((unsigned long) buf->buffer_mem, order);
96 kfree(buf);
97 }
98}
99
100
101/******************************************************************************/ 54/******************************************************************************/
102/* DEVICE FILE DRIVER */ 55/* DEVICE FILE DRIVER */
103/******************************************************************************/ 56/******************************************************************************/
104 57
105#define NO_TIMESTAMPS (2 << 19) /* that should be 8 megs of ram, we may not get 58#define NO_TIMESTAMPS (2 << 19) /* that should be 8 megs of ram, we may not get
106 * as much */ 59 * as much */
60#define FT_TRACE_MAJOR 252
107 61
108static DECLARE_MUTEX(feather_lock); 62static int alloc_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
109static int use_count = 0;
110
111/* used for draining the FT buffers */
112static int enabled_events = 0;
113
114static int trace_release(struct inode *in, struct file *filp)
115{
116 int err = -EINVAL;
117
118 if (down_interruptible(&feather_lock)) {
119 err = -ERESTARTSYS;
120 goto out;
121 }
122
123 printk(KERN_ALERT "%s/%d disconnects from feather trace device. "
124 "use_count=%d\n",
125 current->comm, current->pid, use_count);
126
127 if (use_count == 1) {
128 /* disable events */
129 ft_disable_all_events();
130 enabled_events = 0;
131
132 /* wait for any pending events to complete */
133 set_current_state(TASK_UNINTERRUPTIBLE);
134 schedule_timeout(HZ);
135
136 printk(KERN_ALERT "Failed trace writes: %u\n",
137 trace_ts_buf->failed_writes);
138
139 free_ft_buffer(trace_ts_buf);
140 trace_ts_buf = NULL;
141 }
142
143 /* dummy entry to make linker happy */
144 ft_event0(666, save_timestamp);
145
146 use_count--;
147 up(&feather_lock);
148out:
149 return err;
150}
151
152static ssize_t trace_read(struct file *filp, char __user *to, size_t len,
153 loff_t *f_pos)
154{
155 /* we ignore f_pos, this is strictly sequential */
156 ssize_t error = 0;
157 struct timestamp ts;
158
159 if (down_interruptible(&feather_lock)) {
160 error = -ERESTARTSYS;
161 goto out;
162 }
163
164
165 while (len >= sizeof(struct timestamp)) {
166 if (ft_buffer_read(trace_ts_buf, &ts)) {
167 /* FIXME: avoid double copy */
168 if (copy_to_user(to, &ts, sizeof(struct timestamp))) {
169 error = -EFAULT;
170 break;
171 } else {
172 len -= sizeof(struct timestamp);
173 to += sizeof(struct timestamp);
174 error += sizeof(struct timestamp);
175 }
176 } else if (enabled_events) {
177 /* only wait if there are any events enabled */
178 set_current_state(TASK_INTERRUPTIBLE);
179 schedule_timeout(50);
180 if (signal_pending(current)) {
181 error = -ERESTARTSYS;
182 break;
183 }
184 } else
185 /* nothing left to get, return to user space */
186 break;
187 }
188 up(&feather_lock);
189out:
190 return error;
191}
192
193#define ENABLE_CMD 0
194#define DISABLE_CMD 1
195
196typedef uint32_t cmd_t;
197
198static ssize_t trace_write(struct file *filp, const char __user *from,
199 size_t len, loff_t *f_pos)
200{
201 ssize_t error = -EINVAL;
202 cmd_t cmd;
203 cmd_t id;
204
205 if (len % sizeof(cmd_t) || len < 2 * sizeof(cmd_t))
206 goto out;
207
208 if (copy_from_user(&cmd, from, sizeof(cmd_t))) {
209 error = -EFAULT;
210 goto out;
211 }
212 len -= sizeof(cmd_t);
213 from += sizeof(cmd_t);
214
215 if (cmd != ENABLE_CMD && cmd != DISABLE_CMD)
216 goto out;
217
218 if (down_interruptible(&feather_lock)) {
219 error = -ERESTARTSYS;
220 goto out;
221 }
222
223 error = sizeof(cmd_t);
224 while (len) {
225 if (copy_from_user(&id, from, sizeof(cmd_t))) {
226 error = -EFAULT;
227 goto out;
228 }
229 len -= sizeof(cmd_t);
230 from += sizeof(cmd_t);
231 if (cmd) {
232 printk(KERN_INFO
233 "Disabling feather-trace event %d.\n", (int) id);
234 ft_disable_event(id);
235 enabled_events--;
236 } else {
237 printk(KERN_INFO
238 "Enabling feather-trace event %d.\n", (int) id);
239 ft_enable_event(id);
240 enabled_events++;
241 }
242 error += sizeof(cmd_t);
243 }
244
245 up(&feather_lock);
246 out:
247 return error;
248}
249
250static int trace_open(struct inode *in, struct file *filp)
251{ 63{
252 int err = 0; 64 unsigned int count = NO_TIMESTAMPS;
253 unsigned int count = NO_TIMESTAMPS;
254
255 if (down_interruptible(&feather_lock)) {
256 err = -ERESTARTSYS;
257 goto out;
258 }
259
260 while (count && !trace_ts_buf) { 65 while (count && !trace_ts_buf) {
261 printk("trace: trying to allocate %u time stamps.\n", count); 66 printk("time stamp buffer: trying to allocate %u time stamps.\n", count);
262 trace_ts_buf = alloc_ft_buffer(count, sizeof(struct timestamp)); 67 ftdev->minor[idx].buf = alloc_ft_buffer(count, sizeof(struct timestamp));
263 count /= 2; 68 count /= 2;
264 } 69 }
265 if (!trace_ts_buf) 70 return ftdev->minor[idx].buf ? 0 : -ENOMEM;
266 err = -ENOMEM;
267 else
268 use_count++;
269
270 up(&feather_lock);
271out:
272 return err;
273} 71}
274 72
275/******************************************************************************/ 73static void free_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
276/* Device Registration */
277/******************************************************************************/
278
279#define FT_TRACE_MAJOR 252
280
281struct file_operations ft_trace_fops = {
282 .owner = THIS_MODULE,
283 .open = trace_open,
284 .release = trace_release,
285 .write = trace_write,
286 .read = trace_read,
287};
288
289
290static int __init register_buffer_dev(const char* name,
291 struct file_operations* fops,
292 int major, int count)
293{ 74{
294 dev_t trace_dev; 75 free_ft_buffer(ftdev->minor[idx].buf);
295 struct cdev *cdev; 76 ftdev->minor[idx].buf = NULL;
296 int error = 0;
297
298 trace_dev = MKDEV(major, 0);
299 error = register_chrdev_region(trace_dev, count, name);
300 if (error)
301 {
302 printk(KERN_WARNING "trace: "
303 "Could not register major/minor number %d\n", major);
304 return error;
305 }
306 cdev = cdev_alloc();
307 if (!cdev) {
308 printk(KERN_WARNING "trace: "
309 "Could not get a cdev for %s.\n", name);
310 return -ENOMEM;
311 }
312 cdev->owner = THIS_MODULE;
313 cdev->ops = fops;
314 error = cdev_add(cdev, trace_dev, count);
315 if (error) {
316 printk(KERN_WARNING "trace: "
317 "add_cdev failed for %s.\n", name);
318 return -ENOMEM;
319 }
320 return error;
321
322} 77}
323 78
324static int __init init_sched_trace(void) 79static int __init init_ft_overhead_trace(void)
325{ 80{
326 int error = 0; 81 printk("Initializing Feather-Trace overhead tracing device.\n");
327 82 ftdev_init(&overhead_dev);
328 printk("Initializing Feather-Trace device\n"); 83 overhead_dev.minor_cnt = 1; /* only one buffer */
329 84 overhead_dev.alloc = alloc_timestamp_buffer;
330 error = register_buffer_dev("ft_trace", &ft_trace_fops, 85 overhead_dev.free = free_timestamp_buffer;
331 FT_TRACE_MAJOR, 1); 86 return register_ftdev(&overhead_dev, "ft_trace", FT_TRACE_MAJOR);
332 return error;
333} 87}
334 88
335module_init(init_sched_trace); 89module_init(init_ft_overhead_trace);