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 <[email protected]>
Signed-off-by: Maynard Johnson <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
Acked-by: Acked-by: Robert Richter <[email protected]>
Signed-off-by: Benjamin Herrenschmidt <[email protected]>
This commit is contained in:
Carl Love 2008-10-14 23:37:01 +00:00 • committed by Benjamin Herrenschmidt
commit a5598ca0d4
7 changed files with 279 additions and 36 deletions

View file

@ -628,3 +628,27 @@ void sync_buffer(int cpu)
mutex_unlock(&buffer_mutex);
}
/* The function can be used to add a buffer worth of data directly to
* the kernel buffer. The buffer is assumed to be a circular buffer.
* Take the entries from index start and end at index end, wrapping
* at max_entries.
*/
void oprofile_put_buff(unsigned long *buf, unsigned int start,
unsigned int stop, unsigned int max)
{
int i;
i = start;
mutex_lock(&buffer_mutex);
while (i != stop) {
add_event_entry(buf[i++]);
if (i >= max)
i = 0;
}
mutex_unlock(&buffer_mutex);
}

View file

@ -38,13 +38,26 @@ static int work_enabled;
void free_cpu_buffers(void)
{
int i;
for_each_online_cpu(i) {
vfree(per_cpu(cpu_buffer, i).buffer);
per_cpu(cpu_buffer, i).buffer = NULL;
}
}
unsigned long oprofile_get_cpu_buffer_size(void)
{
return fs_cpu_buffer_size;
}
void oprofile_cpu_buffer_inc_smpl_lost(void)
{
struct oprofile_cpu_buffer *cpu_buf
= &__get_cpu_var(cpu_buffer);
cpu_buf->sample_lost_overflow++;
}
int alloc_cpu_buffers(void)
{
int i;

View file

@ -17,6 +17,13 @@ int alloc_event_buffer(void);
void free_event_buffer(void);
/**
* Add data to the event buffer.
* The data passed is free-form, but typically consists of
* file offsets, dcookies, context information, and ESCAPE codes.
*/
void add_event_entry(unsigned long data);
/* wake up the process sleeping on the event file */
void wake_up_buffer_waiter(void);