oprofile: modify op_cpu_buffer_read_entry()
Robert Richter [Tue, 30 Dec 2008 03:10:46 +0000 (04:10 +0100)]
This implements the support of samples with attached data.

Signed-off-by: Robert Richter <robert.richter@amd.com>

drivers/oprofile/buffer_sync.c
drivers/oprofile/cpu_buffer.c
drivers/oprofile/cpu_buffer.h

index 21fd249..908202a 100644 (file)
@@ -329,9 +329,10 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm)
        int i, count;
        unsigned long cookie = 0;
        off_t offset;
+       struct op_entry entry;
        struct op_sample *sample;
 
-       sample = op_cpu_buffer_read_entry(cpu);
+       sample = op_cpu_buffer_read_entry(&entry, cpu);
        if (!sample)
                return;
        pc = sample->eip;
@@ -370,7 +371,7 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm)
                count = IBS_OP_CODE_SIZE;       /*IBS OP is 5 int64s*/
 
        for (i = 0; i < count; i++) {
-               sample = op_cpu_buffer_read_entry(cpu);
+               sample = op_cpu_buffer_read_entry(&entry, cpu);
                if (!sample)
                        return;
                add_event_entry(sample->eip);
@@ -528,6 +529,8 @@ void sync_buffer(int cpu)
        sync_buffer_state state = sb_buffer_start;
        unsigned int i;
        unsigned long available;
+       struct op_entry entry;
+       struct op_sample *sample;
 
        mutex_lock(&buffer_mutex);
 
@@ -537,19 +540,19 @@ void sync_buffer(int cpu)
        available = op_cpu_buffer_entries(cpu);
 
        for (i = 0; i < available; ++i) {
-               struct op_sample *s = op_cpu_buffer_read_entry(cpu);
-               if (!s)
+               sample = op_cpu_buffer_read_entry(&entry, cpu);
+               if (!sample)
                        break;
 
-               if (is_code(s->eip)) {
-                       switch (s->event) {
+               if (is_code(sample->eip)) {
+                       switch (sample->event) {
                        case 0:
                        case CPU_IS_KERNEL:
                                /* kernel/userspace switch */
-                               in_kernel = s->event;
+                               in_kernel = sample->event;
                                if (state == sb_buffer_start)
                                        state = sb_sample_start;
-                               add_kernel_ctx_switch(s->event);
+                               add_kernel_ctx_switch(sample->event);
                                break;
                        case CPU_TRACE_BEGIN:
                                state = sb_bt_start;
@@ -566,7 +569,7 @@ void sync_buffer(int cpu)
                        default:
                                /* userspace context switch */
                                oldmm = mm;
-                               new = (struct task_struct *)s->event;
+                               new = (struct task_struct *)sample->event;
                                release_mm(oldmm);
                                mm = take_tasks_mm(new);
                                if (mm != oldmm)
@@ -581,7 +584,7 @@ void sync_buffer(int cpu)
                        /* ignore sample */
                        continue;
 
-               if (add_sample(mm, s, in_kernel))
+               if (add_sample(mm, sample, in_kernel))
                        continue;
 
                /* ignore backtraces if failed to add a sample */
index 934ff15..400f7fc 100644 (file)
@@ -182,20 +182,28 @@ int op_cpu_buffer_write_commit(struct op_entry *entry)
                                         entry->irq_flags);
 }
 
-struct op_sample *op_cpu_buffer_read_entry(int cpu)
+struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)
 {
        struct ring_buffer_event *e;
        e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
        if (e)
-               return ring_buffer_event_data(e);
+               goto event;
        if (ring_buffer_swap_cpu(op_ring_buffer_read,
                                 op_ring_buffer_write,
                                 cpu))
                return NULL;
        e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
        if (e)
-               return ring_buffer_event_data(e);
+               goto event;
        return NULL;
+
+event:
+       entry->event = e;
+       entry->sample = ring_buffer_event_data(e);
+       entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample))
+               / sizeof(entry->sample->data[0]);
+       entry->data = entry->sample->data;
+       return entry->sample;
 }
 
 unsigned long op_cpu_buffer_entries(int cpu)
index 2d4bfde..d7c0545 100644 (file)
@@ -75,7 +75,7 @@ static inline void op_cpu_buffer_reset(int cpu)
 struct op_sample
 *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size);
 int op_cpu_buffer_write_commit(struct op_entry *entry);
-struct op_sample *op_cpu_buffer_read_entry(int cpu);
+struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu);
 unsigned long op_cpu_buffer_entries(int cpu);
 
 /* transient events for the CPU buffer -> event buffer */