diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-07-23 23:40:10 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-11-24 15:21:06 -0500 |
commit | e079932a0a1aab6adbc42fedefc6caa2d9a8af2b (patch) | |
tree | b40d3cb42068da1b14db3d3e9836fbc372056a33 | |
parent | 12982f31a233250c7a62b17fb4bd13594cb78777 (diff) |
Feather-trace: let userspace add overhead events
This is useful for measuring locking-related overheads
that are partially recorded in userspace.
-rw-r--r-- | litmus/trace.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/litmus/trace.c b/litmus/trace.c index f0eb2c706488..5d77806da647 100644 --- a/litmus/trace.c +++ b/litmus/trace.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/sched.h> | 1 | #include <linux/sched.h> |
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/uaccess.h> | ||
3 | 4 | ||
4 | #include <litmus/ftdev.h> | 5 | #include <litmus/ftdev.h> |
5 | #include <litmus/litmus.h> | 6 | #include <litmus/litmus.h> |
@@ -31,6 +32,18 @@ static inline void __save_timestamp_cpu(unsigned long event, | |||
31 | } | 32 | } |
32 | } | 33 | } |
33 | 34 | ||
35 | static 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 | if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) { | ||
41 | *ts = *pre_recorded; | ||
42 | ts->seq_no = seq_no; | ||
43 | ft_buffer_finish_write(trace_ts_buf, ts); | ||
44 | } | ||
45 | } | ||
46 | |||
34 | static inline void __save_timestamp(unsigned long event, | 47 | static inline void __save_timestamp(unsigned long event, |
35 | uint8_t type) | 48 | uint8_t type) |
36 | { | 49 | { |
@@ -108,6 +121,32 @@ static void free_timestamp_buffer(struct ftdev* ftdev, unsigned int idx) | |||
108 | ftdev->minor[idx].buf = NULL; | 121 | ftdev->minor[idx].buf = NULL; |
109 | } | 122 | } |
110 | 123 | ||
124 | static ssize_t write_timestamp_from_user(struct ft_buffer* buf, size_t len, | ||
125 | const char __user *from) | ||
126 | { | ||
127 | ssize_t consumed = 0; | ||
128 | struct timestamp ts; | ||
129 | |||
130 | /* don't give us partial timestamps */ | ||
131 | if (len % sizeof(ts)) | ||
132 | return -EINVAL; | ||
133 | |||
134 | while (len >= sizeof(ts)) { | ||
135 | if (copy_from_user(&ts, from, sizeof(ts))) { | ||
136 | consumed = -EFAULT; | ||
137 | goto out; | ||
138 | } | ||
139 | len -= sizeof(ts); | ||
140 | from += sizeof(ts); | ||
141 | consumed += sizeof(ts); | ||
142 | |||
143 | __add_timestamp_user(&ts); | ||
144 | } | ||
145 | |||
146 | out: | ||
147 | return consumed; | ||
148 | } | ||
149 | |||
111 | static int __init init_ft_overhead_trace(void) | 150 | static int __init init_ft_overhead_trace(void) |
112 | { | 151 | { |
113 | int err; | 152 | int err; |
@@ -119,6 +158,7 @@ static int __init init_ft_overhead_trace(void) | |||
119 | 158 | ||
120 | overhead_dev.alloc = alloc_timestamp_buffer; | 159 | overhead_dev.alloc = alloc_timestamp_buffer; |
121 | overhead_dev.free = free_timestamp_buffer; | 160 | overhead_dev.free = free_timestamp_buffer; |
161 | overhead_dev.write = write_timestamp_from_user; | ||
122 | 162 | ||
123 | err = register_ftdev(&overhead_dev); | 163 | err = register_ftdev(&overhead_dev); |
124 | if (err) | 164 | if (err) |