From 023ce066151d32da6a16c48c9d339ca7a69d0180 Mon Sep 17 00:00:00 2001 From: Soeren Sandmann Date: Sat, 16 Apr 2005 23:57:00 +0000 Subject: [PATCH] Read a whole page at a time. Sat Apr 16 19:51:48 2005 Soeren Sandmann * sysprof-module.c (read_user_space): Read a whole page at a time. --- ChangeLog | 4 +++ sysprof-module.c | 72 +++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87e3c987..e9447119 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sat Apr 16 19:51:48 2005 Soeren Sandmann + + * sysprof-module.c (read_user_space): Read a whole page at a time. + Sat Apr 16 14:15:55 2005 Soeren Sandmann * TODO: Update diff --git a/sysprof-module.c b/sysprof-module.c index f7c4dc39..abcc08a8 100644 --- a/sysprof-module.c +++ b/sysprof-module.c @@ -61,21 +61,10 @@ typedef struct userspace_reader userspace_reader; struct userspace_reader { struct task_struct *task; - unsigned long user_page; - unsigned long kernel_page; - struct page *page; + unsigned long cache_address; + unsigned long *cache; }; -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 */ @@ -149,19 +138,48 @@ x_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int 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 read_user_space (userspace_reader *reader, unsigned long address, 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 done_userspace_reader (userspace_reader *reader) { - if (reader->user_page) - kunmap (reader->page); + kfree (reader->cache); } typedef struct StackFrame StackFrame; @@ -214,15 +232,19 @@ generate_stack_trace(struct task_struct *task, addr = regs->ebp; - init_userspace_reader (&reader, task); - while (i < SYSPROF_MAX_ADDRESSES && read_frame (&reader, addr, &frame) && - addr < START_OF_STACK && addr >= regs->esp) { + if (init_userspace_reader (&reader, task)) + { + 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; - addr = frame.next; + done_userspace_reader (&reader); } - done_userspace_reader (&reader); - + trace->n_addresses = i; if (i == SYSPROF_MAX_ADDRESSES) trace->truncated = 1; @@ -230,8 +252,6 @@ generate_stack_trace(struct task_struct *task, trace->truncated = 0; } -struct work_struct work; - DECLARE_WAIT_QUEUE_HEAD (wait_to_be_scanned); static void @@ -250,6 +270,8 @@ do_generate (void *data) mod_timer(&timer, jiffies + INTERVAL); } +struct work_struct work; + static void on_timer(unsigned long dong) {