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 ac79f667603..934ff159e70 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 65b763ad72d..2d4bfdeb7fb 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); |
