diff options
-rw-r--r-- | drivers/oprofile/cpu_buffer.c | 43 | ||||
-rw-r--r-- | drivers/oprofile/cpu_buffer.h | 9 |
2 files changed, 37 insertions, 15 deletions
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index ac79f6676033..934ff159e70e 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
@@ -1,11 +1,12 @@ | |||
1 | /** | 1 | /** |
2 | * @file cpu_buffer.c | 2 | * @file cpu_buffer.c |
3 | * | 3 | * |
4 | * @remark Copyright 2002 OProfile authors | 4 | * @remark Copyright 2002-2009 OProfile authors |
5 | * @remark Read the file COPYING | 5 | * @remark Read the file COPYING |
6 | * | 6 | * |
7 | * @author John Levon <levon@movementarian.org> | 7 | * @author John Levon <levon@movementarian.org> |
8 | * @author Barry Kasindorf <barry.kasindorf@amd.com> | 8 | * @author Barry Kasindorf <barry.kasindorf@amd.com> |
9 | * @author Robert Richter <robert.richter@amd.com> | ||
9 | * | 10 | * |
10 | * Each CPU has a local buffer that stores PC value/event | 11 | * Each CPU has a local buffer that stores PC value/event |
11 | * pairs. We also log context switches when we notice them. | 12 | * pairs. We also log context switches when we notice them. |
@@ -143,20 +144,36 @@ void end_cpu_work(void) | |||
143 | flush_scheduled_work(); | 144 | flush_scheduled_work(); |
144 | } | 145 | } |
145 | 146 | ||
146 | int op_cpu_buffer_write_entry(struct op_entry *entry) | 147 | /* |
148 | * This function prepares the cpu buffer to write a sample. | ||
149 | * | ||
150 | * Struct op_entry is used during operations on the ring buffer while | ||
151 | * struct op_sample contains the data that is stored in the ring | ||
152 | * buffer. Struct entry can be uninitialized. The function reserves a | ||
153 | * data array that is specified by size. Use | ||
154 | * op_cpu_buffer_write_commit() after preparing the sample. In case of | ||
155 | * errors a null pointer is returned, otherwise the pointer to the | ||
156 | * sample. | ||
157 | * | ||
158 | */ | ||
159 | struct op_sample | ||
160 | *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) | ||
147 | { | 161 | { |
148 | entry->event = ring_buffer_lock_reserve(op_ring_buffer_write, | 162 | entry->event = ring_buffer_lock_reserve |
149 | sizeof(struct op_sample), | 163 | (op_ring_buffer_write, sizeof(struct op_sample) + |
150 | &entry->irq_flags); | 164 | size * sizeof(entry->sample->data[0]), &entry->irq_flags); |
151 | if (entry->event) | 165 | if (entry->event) |
152 | entry->sample = ring_buffer_event_data(entry->event); | 166 | entry->sample = ring_buffer_event_data(entry->event); |
153 | else | 167 | else |
154 | entry->sample = NULL; | 168 | entry->sample = NULL; |
155 | 169 | ||
156 | if (!entry->sample) | 170 | if (!entry->sample) |
157 | return -ENOMEM; | 171 | return NULL; |
158 | 172 | ||
159 | return 0; | 173 | entry->size = size; |
174 | entry->data = entry->sample->data; | ||
175 | |||
176 | return entry->sample; | ||
160 | } | 177 | } |
161 | 178 | ||
162 | int op_cpu_buffer_write_commit(struct op_entry *entry) | 179 | int op_cpu_buffer_write_commit(struct op_entry *entry) |
@@ -192,14 +209,14 @@ op_add_sample(struct oprofile_cpu_buffer *cpu_buf, | |||
192 | unsigned long pc, unsigned long event) | 209 | unsigned long pc, unsigned long event) |
193 | { | 210 | { |
194 | struct op_entry entry; | 211 | struct op_entry entry; |
195 | int ret; | 212 | struct op_sample *sample; |
196 | 213 | ||
197 | ret = op_cpu_buffer_write_entry(&entry); | 214 | sample = op_cpu_buffer_write_reserve(&entry, 0); |
198 | if (ret) | 215 | if (!sample) |
199 | return ret; | 216 | return -ENOMEM; |
200 | 217 | ||
201 | entry.sample->eip = pc; | 218 | sample->eip = pc; |
202 | entry.sample->event = event; | 219 | sample->event = event; |
203 | 220 | ||
204 | return op_cpu_buffer_write_commit(&entry); | 221 | return op_cpu_buffer_write_commit(&entry); |
205 | } | 222 | } |
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 65b763ad72da..2d4bfdeb7fba 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h | |||
@@ -1,10 +1,11 @@ | |||
1 | /** | 1 | /** |
2 | * @file cpu_buffer.h | 2 | * @file cpu_buffer.h |
3 | * | 3 | * |
4 | * @remark Copyright 2002 OProfile authors | 4 | * @remark Copyright 2002-2009 OProfile authors |
5 | * @remark Read the file COPYING | 5 | * @remark Read the file COPYING |
6 | * | 6 | * |
7 | * @author John Levon <levon@movementarian.org> | 7 | * @author John Levon <levon@movementarian.org> |
8 | * @author Robert Richter <robert.richter@amd.com> | ||
8 | */ | 9 | */ |
9 | 10 | ||
10 | #ifndef OPROFILE_CPU_BUFFER_H | 11 | #ifndef OPROFILE_CPU_BUFFER_H |
@@ -31,12 +32,15 @@ void end_cpu_work(void); | |||
31 | struct op_sample { | 32 | struct op_sample { |
32 | unsigned long eip; | 33 | unsigned long eip; |
33 | unsigned long event; | 34 | unsigned long event; |
35 | unsigned long data[0]; | ||
34 | }; | 36 | }; |
35 | 37 | ||
36 | struct op_entry { | 38 | struct op_entry { |
37 | struct ring_buffer_event *event; | 39 | struct ring_buffer_event *event; |
38 | struct op_sample *sample; | 40 | struct op_sample *sample; |
39 | unsigned long irq_flags; | 41 | unsigned long irq_flags; |
42 | unsigned long size; | ||
43 | unsigned long *data; | ||
40 | }; | 44 | }; |
41 | 45 | ||
42 | struct oprofile_cpu_buffer { | 46 | struct oprofile_cpu_buffer { |
@@ -68,7 +72,8 @@ static inline void op_cpu_buffer_reset(int cpu) | |||
68 | cpu_buf->last_task = NULL; | 72 | cpu_buf->last_task = NULL; |
69 | } | 73 | } |
70 | 74 | ||
71 | int op_cpu_buffer_write_entry(struct op_entry *entry); | 75 | struct op_sample |
76 | *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size); | ||
72 | int op_cpu_buffer_write_commit(struct op_entry *entry); | 77 | int op_cpu_buffer_write_commit(struct op_entry *entry); |
73 | struct op_sample *op_cpu_buffer_read_entry(int cpu); | 78 | struct op_sample *op_cpu_buffer_read_entry(int cpu); |
74 | unsigned long op_cpu_buffer_entries(int cpu); | 79 | unsigned long op_cpu_buffer_entries(int cpu); |