diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/sputrace.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sputrace.c | 272 |
1 files changed, 0 insertions, 272 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c deleted file mode 100644 index d0b1f3f4d9c8..000000000000 --- a/arch/powerpc/platforms/cell/spufs/sputrace.c +++ /dev/null | |||
@@ -1,272 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 IBM Deutschland Entwicklung GmbH | ||
3 | * Released under GPL v2. | ||
4 | * | ||
5 | * Partially based on net/ipv4/tcp_probe.c. | ||
6 | * | ||
7 | * Simple tracing facility for spu contexts. | ||
8 | */ | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/marker.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | #include <linux/wait.h> | ||
15 | #include <asm/atomic.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include "spufs.h" | ||
18 | |||
19 | struct spu_probe { | ||
20 | const char *name; | ||
21 | const char *format; | ||
22 | marker_probe_func *probe_func; | ||
23 | }; | ||
24 | |||
25 | struct sputrace { | ||
26 | ktime_t tstamp; | ||
27 | int owner_tid; /* owner */ | ||
28 | int curr_tid; | ||
29 | const char *name; | ||
30 | int number; | ||
31 | }; | ||
32 | |||
33 | static int bufsize __read_mostly = 16384; | ||
34 | MODULE_PARM_DESC(bufsize, "Log buffer size (number of records)"); | ||
35 | module_param(bufsize, int, 0); | ||
36 | |||
37 | |||
38 | static DEFINE_SPINLOCK(sputrace_lock); | ||
39 | static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait); | ||
40 | static ktime_t sputrace_start; | ||
41 | static unsigned long sputrace_head, sputrace_tail; | ||
42 | static struct sputrace *sputrace_log; | ||
43 | static int sputrace_logging; | ||
44 | |||
45 | static int sputrace_used(void) | ||
46 | { | ||
47 | return (sputrace_head - sputrace_tail) % bufsize; | ||
48 | } | ||
49 | |||
50 | static inline int sputrace_avail(void) | ||
51 | { | ||
52 | return bufsize - sputrace_used(); | ||
53 | } | ||
54 | |||
55 | static int sputrace_sprint(char *tbuf, int n) | ||
56 | { | ||
57 | const struct sputrace *t = sputrace_log + sputrace_tail % bufsize; | ||
58 | struct timespec tv = | ||
59 | ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start)); | ||
60 | |||
61 | return snprintf(tbuf, n, | ||
62 | "[%lu.%09lu] %d: %s (ctxthread = %d, spu = %d)\n", | ||
63 | (unsigned long) tv.tv_sec, | ||
64 | (unsigned long) tv.tv_nsec, | ||
65 | t->curr_tid, | ||
66 | t->name, | ||
67 | t->owner_tid, | ||
68 | t->number); | ||
69 | } | ||
70 | |||
71 | static ssize_t sputrace_read(struct file *file, char __user *buf, | ||
72 | size_t len, loff_t *ppos) | ||
73 | { | ||
74 | int error = 0, cnt = 0; | ||
75 | |||
76 | if (!buf || len < 0) | ||
77 | return -EINVAL; | ||
78 | |||
79 | while (cnt < len) { | ||
80 | char tbuf[128]; | ||
81 | int width; | ||
82 | |||
83 | /* If we have data ready to return, don't block waiting | ||
84 | * for more */ | ||
85 | if (cnt > 0 && sputrace_used() == 0) | ||
86 | break; | ||
87 | |||
88 | error = wait_event_interruptible(sputrace_wait, | ||
89 | sputrace_used() > 0); | ||
90 | if (error) | ||
91 | break; | ||
92 | |||
93 | spin_lock(&sputrace_lock); | ||
94 | if (sputrace_head == sputrace_tail) { | ||
95 | spin_unlock(&sputrace_lock); | ||
96 | continue; | ||
97 | } | ||
98 | |||
99 | width = sputrace_sprint(tbuf, sizeof(tbuf)); | ||
100 | if (width < len) | ||
101 | sputrace_tail = (sputrace_tail + 1) % bufsize; | ||
102 | spin_unlock(&sputrace_lock); | ||
103 | |||
104 | if (width >= len) | ||
105 | break; | ||
106 | |||
107 | error = copy_to_user(buf + cnt, tbuf, width); | ||
108 | if (error) | ||
109 | break; | ||
110 | cnt += width; | ||
111 | } | ||
112 | |||
113 | return cnt == 0 ? error : cnt; | ||
114 | } | ||
115 | |||
116 | static int sputrace_open(struct inode *inode, struct file *file) | ||
117 | { | ||
118 | int rc; | ||
119 | |||
120 | spin_lock(&sputrace_lock); | ||
121 | if (sputrace_logging) { | ||
122 | rc = -EBUSY; | ||
123 | goto out; | ||
124 | } | ||
125 | |||
126 | sputrace_logging = 1; | ||
127 | sputrace_head = sputrace_tail = 0; | ||
128 | sputrace_start = ktime_get(); | ||
129 | rc = 0; | ||
130 | |||
131 | out: | ||
132 | spin_unlock(&sputrace_lock); | ||
133 | return rc; | ||
134 | } | ||
135 | |||
136 | static int sputrace_release(struct inode *inode, struct file *file) | ||
137 | { | ||
138 | spin_lock(&sputrace_lock); | ||
139 | sputrace_logging = 0; | ||
140 | spin_unlock(&sputrace_lock); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static const struct file_operations sputrace_fops = { | ||
145 | .owner = THIS_MODULE, | ||
146 | .open = sputrace_open, | ||
147 | .read = sputrace_read, | ||
148 | .release = sputrace_release, | ||
149 | }; | ||
150 | |||
151 | static void sputrace_log_item(const char *name, struct spu_context *ctx, | ||
152 | struct spu *spu) | ||
153 | { | ||
154 | spin_lock(&sputrace_lock); | ||
155 | |||
156 | if (!sputrace_logging) { | ||
157 | spin_unlock(&sputrace_lock); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | if (sputrace_avail() > 1) { | ||
162 | struct sputrace *t = sputrace_log + sputrace_head; | ||
163 | |||
164 | t->tstamp = ktime_get(); | ||
165 | t->owner_tid = ctx->tid; | ||
166 | t->name = name; | ||
167 | t->curr_tid = current->pid; | ||
168 | t->number = spu ? spu->number : -1; | ||
169 | |||
170 | sputrace_head = (sputrace_head + 1) % bufsize; | ||
171 | } else { | ||
172 | printk(KERN_WARNING | ||
173 | "sputrace: lost samples due to full buffer.\n"); | ||
174 | } | ||
175 | spin_unlock(&sputrace_lock); | ||
176 | |||
177 | wake_up(&sputrace_wait); | ||
178 | } | ||
179 | |||
180 | static void spu_context_event(void *probe_private, void *call_data, | ||
181 | const char *format, va_list *args) | ||
182 | { | ||
183 | struct spu_probe *p = probe_private; | ||
184 | struct spu_context *ctx; | ||
185 | struct spu *spu; | ||
186 | |||
187 | ctx = va_arg(*args, struct spu_context *); | ||
188 | spu = va_arg(*args, struct spu *); | ||
189 | |||
190 | sputrace_log_item(p->name, ctx, spu); | ||
191 | } | ||
192 | |||
193 | static void spu_context_nospu_event(void *probe_private, void *call_data, | ||
194 | const char *format, va_list *args) | ||
195 | { | ||
196 | struct spu_probe *p = probe_private; | ||
197 | struct spu_context *ctx; | ||
198 | |||
199 | ctx = va_arg(*args, struct spu_context *); | ||
200 | |||
201 | sputrace_log_item(p->name, ctx, NULL); | ||
202 | } | ||
203 | |||
204 | struct spu_probe spu_probes[] = { | ||
205 | { "spu_bind_context__enter", "ctx %p spu %p", spu_context_event }, | ||
206 | { "spu_unbind_context__enter", "ctx %p spu %p", spu_context_event }, | ||
207 | { "spu_get_idle__enter", "ctx %p", spu_context_nospu_event }, | ||
208 | { "spu_get_idle__found", "ctx %p spu %p", spu_context_event }, | ||
209 | { "spu_get_idle__not_found", "ctx %p", spu_context_nospu_event }, | ||
210 | { "spu_find_victim__enter", "ctx %p", spu_context_nospu_event }, | ||
211 | { "spusched_tick__preempt", "ctx %p spu %p", spu_context_event }, | ||
212 | { "spusched_tick__newslice", "ctx %p", spu_context_nospu_event }, | ||
213 | { "spu_yield__enter", "ctx %p", spu_context_nospu_event }, | ||
214 | { "spu_deactivate__enter", "ctx %p", spu_context_nospu_event }, | ||
215 | { "__spu_deactivate__unload", "ctx %p spu %p", spu_context_event }, | ||
216 | { "spufs_ps_fault__enter", "ctx %p", spu_context_nospu_event }, | ||
217 | { "spufs_ps_fault__sleep", "ctx %p", spu_context_nospu_event }, | ||
218 | { "spufs_ps_fault__wake", "ctx %p spu %p", spu_context_event }, | ||
219 | { "spufs_ps_fault__insert", "ctx %p spu %p", spu_context_event }, | ||
220 | { "spu_acquire_saved__enter", "ctx %p", spu_context_nospu_event }, | ||
221 | { "destroy_spu_context__enter", "ctx %p", spu_context_nospu_event }, | ||
222 | { "spufs_stop_callback__enter", "ctx %p spu %p", spu_context_event }, | ||
223 | }; | ||
224 | |||
225 | static int __init sputrace_init(void) | ||
226 | { | ||
227 | struct proc_dir_entry *entry; | ||
228 | int i, error = -ENOMEM; | ||
229 | |||
230 | sputrace_log = kcalloc(bufsize, sizeof(struct sputrace), GFP_KERNEL); | ||
231 | if (!sputrace_log) | ||
232 | goto out; | ||
233 | |||
234 | entry = proc_create("sputrace", S_IRUSR, NULL, &sputrace_fops); | ||
235 | if (!entry) | ||
236 | goto out_free_log; | ||
237 | |||
238 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) { | ||
239 | struct spu_probe *p = &spu_probes[i]; | ||
240 | |||
241 | error = marker_probe_register(p->name, p->format, | ||
242 | p->probe_func, p); | ||
243 | if (error) | ||
244 | printk(KERN_INFO "Unable to register probe %s\n", | ||
245 | p->name); | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | |||
250 | out_free_log: | ||
251 | kfree(sputrace_log); | ||
252 | out: | ||
253 | return -ENOMEM; | ||
254 | } | ||
255 | |||
256 | static void __exit sputrace_exit(void) | ||
257 | { | ||
258 | int i; | ||
259 | |||
260 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) | ||
261 | marker_probe_unregister(spu_probes[i].name, | ||
262 | spu_probes[i].probe_func, &spu_probes[i]); | ||
263 | |||
264 | remove_proc_entry("sputrace", NULL); | ||
265 | kfree(sputrace_log); | ||
266 | marker_synchronize_unregister(); | ||
267 | } | ||
268 | |||
269 | module_init(sputrace_init); | ||
270 | module_exit(sputrace_exit); | ||
271 | |||
272 | MODULE_LICENSE("GPL"); | ||