Read a whole page at a time.

Sat Apr 16 19:51:48 2005  Soeren Sandmann  <sandmann@redhat.com>

	* sysprof-module.c (read_user_space): Read a whole page at a time.
This commit is contained in:
Soeren Sandmann
2005-04-16 23:57:00 +00:00
committed by Søren Sandmann Pedersen
parent 2b0ca11c6c
commit 023ce06615
2 changed files with 51 additions and 25 deletions

View File

@ -1,3 +1,7 @@
Sat Apr 16 19:51:48 2005 Soeren Sandmann <sandmann@redhat.com>
* sysprof-module.c (read_user_space): Read a whole page at a time.
Sat Apr 16 14:15:55 2005 Soeren Sandmann <sandmann@redhat.com> Sat Apr 16 14:15:55 2005 Soeren Sandmann <sandmann@redhat.com>
* TODO: Update * TODO: Update

View File

@ -61,21 +61,10 @@ typedef struct userspace_reader userspace_reader;
struct userspace_reader struct userspace_reader
{ {
struct task_struct *task; struct task_struct *task;
unsigned long user_page; unsigned long cache_address;
unsigned long kernel_page; unsigned long *cache;
struct page *page;
}; };
static void
init_userspace_reader (userspace_reader *reader,
struct task_struct *task)
{
reader->task = task;
reader->user_page = 0;
reader->kernel_page = 0;
reader->page = NULL;
}
/* This function was mostly cutted and pasted from ptrace.c /* This function was mostly cutted and pasted from ptrace.c
*/ */
@ -149,19 +138,48 @@ x_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int
return buf - old_buf; return buf - old_buf;
} }
static int
init_userspace_reader (userspace_reader *reader,
struct task_struct *task)
{
reader->task = task;
reader->cache = kmalloc (PAGE_SIZE, GFP_KERNEL);
if (!reader->cache)
return 0;
reader->cache_address = 0x0;
return 1;
}
static int static int
read_user_space (userspace_reader *reader, read_user_space (userspace_reader *reader,
unsigned long address, unsigned long address,
unsigned long *result) unsigned long *result)
{ {
return x_access_process_vm(reader->task, address, result, 4, 0); unsigned long cache_address = reader->cache_address;
int index, r;
if (!cache_address || cache_address != (address & PAGE_MASK)) {
cache_address = address & PAGE_MASK;
r = x_access_process_vm (reader->task, cache_address,
reader->cache, PAGE_SIZE, 0);
if (r != PAGE_SIZE)
return 0;
reader->cache_address = cache_address;
}
index = (address - cache_address) / sizeof (unsigned long);
*result = reader->cache[index];
return 1;
} }
static void static void
done_userspace_reader (userspace_reader *reader) done_userspace_reader (userspace_reader *reader)
{ {
if (reader->user_page) kfree (reader->cache);
kunmap (reader->page);
} }
typedef struct StackFrame StackFrame; typedef struct StackFrame StackFrame;
@ -214,15 +232,19 @@ generate_stack_trace(struct task_struct *task,
addr = regs->ebp; addr = regs->ebp;
init_userspace_reader (&reader, task); if (init_userspace_reader (&reader, task))
while (i < SYSPROF_MAX_ADDRESSES && read_frame (&reader, addr, &frame) && {
addr < START_OF_STACK && addr >= regs->esp) { while (i < SYSPROF_MAX_ADDRESSES &&
read_frame (&reader, addr, &frame) &&
addr < START_OF_STACK && addr >= regs->esp)
{
trace->addresses[i++] = (void *)frame.return_address;
addr = frame.next;
}
trace->addresses[i++] = (void *)frame.return_address; done_userspace_reader (&reader);
addr = frame.next;
} }
done_userspace_reader (&reader);
trace->n_addresses = i; trace->n_addresses = i;
if (i == SYSPROF_MAX_ADDRESSES) if (i == SYSPROF_MAX_ADDRESSES)
trace->truncated = 1; trace->truncated = 1;
@ -230,8 +252,6 @@ generate_stack_trace(struct task_struct *task,
trace->truncated = 0; trace->truncated = 0;
} }
struct work_struct work;
DECLARE_WAIT_QUEUE_HEAD (wait_to_be_scanned); DECLARE_WAIT_QUEUE_HEAD (wait_to_be_scanned);
static void static void
@ -250,6 +270,8 @@ do_generate (void *data)
mod_timer(&timer, jiffies + INTERVAL); mod_timer(&timer, jiffies + INTERVAL);
} }
struct work_struct work;
static void static void
on_timer(unsigned long dong) on_timer(unsigned long dong)
{ {