aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2008-10-14 19:37:01 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-21 00:17:48 -0400
commita5598ca0d49821912a5053c05f07fd650671eb6d (patch)
treefcfa402eeb45f76fbb03886708e5042fe5f1babb /drivers
parentbb5e6491cae4c5d6ddfa3e173e22efb35f595949 (diff)
powerpc/oprofile: Fix mutex locking for cell spu-oprofile
The issue is the SPU code is not holding the kernel mutex lock while adding samples to the kernel buffer. This patch creates per SPU buffers to hold the data. Data is added to the buffers from in interrupt context. The data is periodically pushed to the kernel buffer via a new Oprofile function oprofile_put_buff(). The oprofile_put_buff() function is called via a work queue enabling the funtion to acquire the mutex lock. The existing user controls for adjusting the per CPU buffer size is used to control the size of the per SPU buffers. Similarly, overflows of the SPU buffers are reported by incrementing the per CPU buffer stats. This eliminates the need to have architecture specific controls for the per SPU buffers which is not acceptable to the OProfile user tool maintainer. The export of the oprofile add_event_entry() is removed as it is no longer needed given this patch. Note, this patch has not addressed the issue of indexing arrays by the spu number. This still needs to be fixed as the spu numbering is not guarenteed to be 0 to max_num_spus-1. Signed-off-by: Carl Love <carll@us.ibm.com> Signed-off-by: Maynard Johnson <maynardj@us.ibm.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Acked-by: Robert Richter <robert.richter@amd.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/oprofile/buffer_sync.c24
-rw-r--r--drivers/oprofile/cpu_buffer.c15
-rw-r--r--drivers/oprofile/event_buffer.h7
3 files changed, 45 insertions, 1 deletions
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index ed982273fb8b..37681700b61a 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -628,3 +628,27 @@ void sync_buffer(int cpu)
628 628
629 mutex_unlock(&buffer_mutex); 629 mutex_unlock(&buffer_mutex);
630} 630}
631
632/* The function can be used to add a buffer worth of data directly to
633 * the kernel buffer. The buffer is assumed to be a circular buffer.
634 * Take the entries from index start and end at index end, wrapping
635 * at max_entries.
636 */
637void oprofile_put_buff(unsigned long *buf, unsigned int start,
638 unsigned int stop, unsigned int max)
639{
640 int i;
641
642 i = start;
643
644 mutex_lock(&buffer_mutex);
645 while (i != stop) {
646 add_event_entry(buf[i++]);
647
648 if (i >= max)
649 i = 0;
650 }
651
652 mutex_unlock(&buffer_mutex);
653}
654
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index e1bd5a937f6c..7ba39fe20a8a 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -38,13 +38,26 @@ static int work_enabled;
38void free_cpu_buffers(void) 38void free_cpu_buffers(void)
39{ 39{
40 int i; 40 int i;
41 41
42 for_each_online_cpu(i) { 42 for_each_online_cpu(i) {
43 vfree(per_cpu(cpu_buffer, i).buffer); 43 vfree(per_cpu(cpu_buffer, i).buffer);
44 per_cpu(cpu_buffer, i).buffer = NULL; 44 per_cpu(cpu_buffer, i).buffer = NULL;
45 } 45 }
46} 46}
47 47
48unsigned long oprofile_get_cpu_buffer_size(void)
49{
50 return fs_cpu_buffer_size;
51}
52
53void oprofile_cpu_buffer_inc_smpl_lost(void)
54{
55 struct oprofile_cpu_buffer *cpu_buf
56 = &__get_cpu_var(cpu_buffer);
57
58 cpu_buf->sample_lost_overflow++;
59}
60
48int alloc_cpu_buffers(void) 61int alloc_cpu_buffers(void)
49{ 62{
50 int i; 63 int i;
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 5076ed1ebd8f..84bf324c5771 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -17,6 +17,13 @@ int alloc_event_buffer(void);
17 17
18void free_event_buffer(void); 18void free_event_buffer(void);
19 19
20/**
21 * Add data to the event buffer.
22 * The data passed is free-form, but typically consists of
23 * file offsets, dcookies, context information, and ESCAPE codes.
24 */
25void add_event_entry(unsigned long data);
26
20/* wake up the process sleeping on the event file */ 27/* wake up the process sleeping on the event file */
21void wake_up_buffer_waiter(void); 28void wake_up_buffer_waiter(void);
22 29