mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Port to 2.6 - remove non-working disk crap
This commit is contained in:
33
Makefile
33
Makefile
@ -1,12 +1,20 @@
|
||||
CFLAGS = `pkg-config --cflags gtk+-2.0 libglade-2.0` -Wall -g
|
||||
LIBS = `pkg-config --libs gtk+-2.0 libglade-2.0` -lbfd -liberty
|
||||
C_FILES = sysprof.c binfile.c stackstash.c watch.c process.c profile.c treeviewutils.c
|
||||
OBJS = $(addsuffix .o, $(basename $(C_FILES)))
|
||||
BINARY = sysprof
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := sysprof-module.o
|
||||
CFLAGS += $(MODCFLAGS) -DKERNEL26
|
||||
|
||||
else
|
||||
|
||||
CFLAGS := $(shell pkg-config --cflags gtk+-2.0 libglade-2.0) -Wall -g
|
||||
LIBS := $(shell pkg-config --libs gtk+-2.0 libglade-2.0) -lbfd -liberty
|
||||
C_FILES := sysprof.c binfile.c stackstash.c watch.c process.c profile.c treeviewutils.c
|
||||
OBJS := $(addsuffix .o, $(basename $(C_FILES)))
|
||||
BINARY := sysprof
|
||||
MODULE := sysprof-module
|
||||
INCLUDE := -isystem /lib/modules/`uname -r`/build/include
|
||||
MODCFLAGS := -O2 -DMODULE -D__KERNEL__ -Wall ${INCLUDE}
|
||||
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
MODULE := sysprof-module
|
||||
|
||||
all: $(BINARY) $(MODULE).o
|
||||
|
||||
@ -26,7 +34,20 @@ include depend.mk
|
||||
|
||||
.PHONY: depend all
|
||||
|
||||
ifeq ($(shell (uname -r | grep 2.6) > /dev/null ; echo -n $$?),0)
|
||||
|
||||
# if kernel 2.6
|
||||
$(MODULE).o: $(MODULE).c
|
||||
echo birnan $(MODCFLAGS)
|
||||
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
else
|
||||
|
||||
MODCFLAGS += KERNEL24
|
||||
|
||||
$(MODULE).o: $(MODULE).c
|
||||
gcc $(MODCFLAGS) $(MODULE).c -c -o$(MODULE).o
|
||||
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
7
README
7
README
@ -6,9 +6,8 @@ program "sysprof".
|
||||
|
||||
- There is no auto* stuff. Just type "make" and hope for the best.
|
||||
|
||||
- It does not work on Linux 2.6. Feel free to port it and send me the
|
||||
patch.
|
||||
|
||||
- You need gtk+ 2.4.0 or better, and you need libglade
|
||||
|
||||
S<EFBFBD>ren
|
||||
- Thanks to Kristian H<>gsberg, it now works on the 2.6 kernel.
|
||||
|
||||
S<EFBFBD>ren
|
||||
|
||||
585
sysprof-module.c
585
sysprof-module.c
@ -1,3 +1,5 @@
|
||||
/* -*- c-basic-offset: 8 -*- */
|
||||
|
||||
#include <linux/config.h>
|
||||
#ifdef CONFIG_SMP
|
||||
# define __SMP__
|
||||
@ -5,451 +7,238 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/kernel.h> /* Needed for KERN_ALERT */
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
#include <linux/tqueue.h>
|
||||
#ifdef KERNEL24
|
||||
# include <linux/tqueue.h>
|
||||
#endif
|
||||
#include <linux/sched.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/poll.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
#include "sysprof-module.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Soeren Sandmann (sandmann@daimi.au.dk)");
|
||||
|
||||
#define SAMPLES_PER_SECOND 50 /* must divide HZ */
|
||||
|
||||
static const int cpu_profiler = 1; /* 0: page faults, 1: cpu */
|
||||
|
||||
static void on_timer_interrupt (void *);
|
||||
|
||||
static struct tq_struct timer_task =
|
||||
{
|
||||
{ NULL, NULL },
|
||||
0,
|
||||
on_timer_interrupt,
|
||||
NULL
|
||||
};
|
||||
|
||||
int exiting = 0;
|
||||
DECLARE_WAIT_QUEUE_HEAD (wait_for_exit);
|
||||
|
||||
#define SAMPLES_PER_SECOND (50)
|
||||
#define INTERVAL (HZ / SAMPLES_PER_SECOND)
|
||||
#define N_TRACES 256
|
||||
|
||||
static SysprofStackTrace stack_traces[N_TRACES];
|
||||
static SysprofStackTrace * head = &stack_traces[0];
|
||||
static SysprofStackTrace * tail = &stack_traces[0];
|
||||
static SysprofStackTrace * head = &stack_traces[0];
|
||||
static SysprofStackTrace * tail = &stack_traces[0];
|
||||
DECLARE_WAIT_QUEUE_HEAD (wait_for_trace);
|
||||
DECLARE_WAIT_QUEUE_HEAD (wait_for_exit);
|
||||
|
||||
static void
|
||||
generate_stack_trace (struct task_struct *task,
|
||||
SysprofStackTrace *trace)
|
||||
typedef void (* TimeoutFunc)(unsigned long data);
|
||||
static void on_timer(unsigned long);
|
||||
|
||||
/*
|
||||
* Wrappers to cover up kernel differences in timer handling
|
||||
*/
|
||||
#ifdef KERNEL24
|
||||
static struct tq_struct timer_task =
|
||||
{
|
||||
#define START_OF_STACK 0xBFFFFFFF
|
||||
|
||||
typedef struct StackFrame StackFrame;
|
||||
struct StackFrame {
|
||||
StackFrame *next;
|
||||
void *return_address;
|
||||
};
|
||||
|
||||
struct pt_regs *regs = (struct pt_regs *)(
|
||||
(long)current + THREAD_SIZE - sizeof (struct pt_regs));
|
||||
|
||||
StackFrame *frame;
|
||||
int i;
|
||||
|
||||
memset (trace, 0, sizeof (SysprofStackTrace));
|
||||
|
||||
trace->pid = current->pid;
|
||||
trace->truncated = 0;
|
||||
|
||||
trace->addresses[0] = (void *)regs->eip;
|
||||
i = 1;
|
||||
|
||||
frame = (StackFrame *)regs->ebp;
|
||||
|
||||
while (frame && i < SYSPROF_MAX_ADDRESSES - 1 &&
|
||||
(long)frame < (long)START_OF_STACK &&
|
||||
(long)frame >= regs->esp)
|
||||
{
|
||||
void *next = NULL;
|
||||
|
||||
if (verify_area(VERIFY_READ, frame, sizeof(StackFrame)) == 0)
|
||||
{
|
||||
void *return_address;
|
||||
|
||||
__get_user (return_address, &(frame->return_address));
|
||||
__get_user (next, &(frame->next));
|
||||
trace->addresses[i++] = return_address;
|
||||
|
||||
if ((long)next <= (long)frame)
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
frame = next;
|
||||
}
|
||||
|
||||
trace->n_addresses = i;
|
||||
if (i == SYSPROF_MAX_ADDRESSES)
|
||||
trace->truncated = 1;
|
||||
else
|
||||
trace->truncated = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
disk_access (struct vm_area_struct *area,
|
||||
unsigned long address)
|
||||
{
|
||||
struct file *file = area->vm_file;
|
||||
struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
struct page *page, **hash;
|
||||
unsigned long size, pgoff, endoff;
|
||||
int disk_access = 1;
|
||||
|
||||
pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
|
||||
endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
|
||||
|
||||
/*
|
||||
* An external ptracer can access pages that normally aren't
|
||||
* accessible..
|
||||
*/
|
||||
size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
||||
if ((pgoff >= size) && (area->vm_mm == current->mm))
|
||||
return 0;
|
||||
|
||||
/* The "size" of the file, as far as mmap is concerned, isn't bigger than the mapping */
|
||||
if (size > endoff)
|
||||
size = endoff;
|
||||
|
||||
/*
|
||||
* Do we have something in the page cache already?
|
||||
*/
|
||||
hash = page_hash(mapping, pgoff);
|
||||
|
||||
page = __find_get_page(mapping, pgoff, hash);
|
||||
if (page)
|
||||
/*
|
||||
* Ok, found a page in the page cache, now we need to check
|
||||
* that it's up-to-date.
|
||||
*/
|
||||
if (Page_Uptodate(page))
|
||||
disk_access = 0;
|
||||
|
||||
return disk_access;
|
||||
}
|
||||
|
||||
struct page *
|
||||
hijacked_nopage (struct vm_area_struct * area,
|
||||
unsigned long address,
|
||||
int unused)
|
||||
{
|
||||
struct page *result;
|
||||
int disk;
|
||||
|
||||
disk = disk_access (area, address);
|
||||
|
||||
printk (KERN_ALERT "disk access: %d\n", disk);
|
||||
|
||||
result = filemap_nopage (area, address, unused);
|
||||
|
||||
if (current && disk)
|
||||
{
|
||||
generate_stack_trace (current, head);
|
||||
|
||||
#if 0
|
||||
memset (head, 0, sizeof (SysprofStackTrace));
|
||||
|
||||
head->pid = current->pid;
|
||||
head->addresses[0] = (void *)address;
|
||||
head->truncated = 0;
|
||||
head->n_addresses = 1;
|
||||
#endif
|
||||
|
||||
memmove (&(head->addresses[1]), &(head->addresses[0]),
|
||||
head->n_addresses * 4);
|
||||
head->n_addresses++;
|
||||
head->addresses[0] = address;
|
||||
|
||||
if (area->vm_file)
|
||||
{
|
||||
char *line = d_path (area->vm_file->f_dentry,
|
||||
area->vm_file->f_vfsmnt,
|
||||
head->filename, PAGE_SIZE);
|
||||
|
||||
strncpy (head->filename, line, sizeof (head->filename) - 1);
|
||||
#if 0
|
||||
|
||||
if (line == head->filename)
|
||||
printk (KERN_ALERT "got name\n");
|
||||
else if (line == NULL)
|
||||
printk (KERN_ALERT "noasdf\n");
|
||||
else
|
||||
printk (KERN_ALERT "%s\n", line);
|
||||
#endif
|
||||
head->map_start = area->vm_start;
|
||||
}
|
||||
|
||||
if (head++ == &stack_traces[N_TRACES - 1])
|
||||
head = &stack_traces[0];
|
||||
|
||||
wake_up (&wait_for_trace);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
hijack_nopage (struct vm_area_struct *vma)
|
||||
{
|
||||
if (vma->vm_ops && vma->vm_ops->nopage == filemap_nopage)
|
||||
vma->vm_ops->nopage = hijacked_nopage;
|
||||
}
|
||||
|
||||
static void
|
||||
hijack_nopages (struct task_struct *task)
|
||||
{
|
||||
struct mm_struct *mm = task->mm;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
if (!mm)
|
||||
return;
|
||||
|
||||
for (vma = mm->mmap; vma != NULL; vma = vma->vm_next)
|
||||
hijack_nopage (vma);
|
||||
}
|
||||
|
||||
static void
|
||||
clean_hijacked_nopages (void)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
||||
for_each_process (task)
|
||||
{
|
||||
struct mm_struct *mm = task->mm;
|
||||
|
||||
if (mm)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
for (vma = mm->mmap; vma != NULL; vma = vma->vm_next)
|
||||
{
|
||||
if (vma->vm_ops && vma->vm_ops->nopage == hijacked_nopage)
|
||||
vma->vm_ops->nopage = filemap_nopage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct mmap_arg_struct {
|
||||
unsigned long addr;
|
||||
unsigned long len;
|
||||
unsigned long prot;
|
||||
unsigned long flags;
|
||||
unsigned long fd;
|
||||
unsigned long offset;
|
||||
{ NULL, NULL },
|
||||
0,
|
||||
on_timer,
|
||||
NULL
|
||||
};
|
||||
|
||||
typedef asmlinkage int (* old_mmap_func) (struct mmap_arg_struct *arg);
|
||||
typedef asmlinkage long (* mmap2_func) (
|
||||
unsigned long addr, unsigned long len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long fd, unsigned long pgoff);
|
||||
#else
|
||||
|
||||
static mmap2_func orig_mmap2;
|
||||
static old_mmap_func orig_mmap;
|
||||
static struct timer_list timer;
|
||||
|
||||
static void
|
||||
after_mmap (long res, unsigned long len)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long start;
|
||||
|
||||
if (res == -1 || !current || current->pid == 0)
|
||||
return;
|
||||
|
||||
start = res;
|
||||
|
||||
vma = find_vma (current->mm, start);
|
||||
|
||||
if (vma && vma->vm_end >= start + len)
|
||||
hijack_nopage (vma);
|
||||
#if 0
|
||||
else if (vma)
|
||||
{
|
||||
printk (KERN_ALERT "nope: vm_start: %x, vm_end: %x\n"
|
||||
"start: %p, len: %x, start + len: %x\n",
|
||||
vma->vm_start, vma->vm_end, start, len, start + len);
|
||||
}
|
||||
else
|
||||
printk (KERN_ALERT "no vma\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static long
|
||||
new_mmap2 (unsigned long addr, unsigned long len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long fd, unsigned long pgoff)
|
||||
{
|
||||
int res = orig_mmap2 (addr, len, prot, flags, fd, pgoff);
|
||||
|
||||
after_mmap (res, len);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
new_mmap (struct mmap_arg_struct *arg)
|
||||
{
|
||||
int res = orig_mmap (arg);
|
||||
|
||||
after_mmap (res, arg->len);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void **sys_call_table = (void **)0xc0347df0;
|
||||
|
||||
static void
|
||||
hijack_mmaps (void)
|
||||
init_timeout (void)
|
||||
{
|
||||
orig_mmap2 = sys_call_table[__NR_mmap2];
|
||||
sys_call_table[__NR_mmap2] = new_mmap2;
|
||||
|
||||
orig_mmap = sys_call_table[__NR_mmap];
|
||||
sys_call_table[__NR_mmap] = new_mmap;
|
||||
}
|
||||
|
||||
static void
|
||||
restore_mmaps (void)
|
||||
{
|
||||
sys_call_table[__NR_mmap2] = orig_mmap2;
|
||||
sys_call_table[__NR_mmap] = orig_mmap;
|
||||
}
|
||||
|
||||
static void
|
||||
on_timer_interrupt (void *data)
|
||||
{
|
||||
static int n_ticks = 0;
|
||||
|
||||
if (exiting)
|
||||
{
|
||||
#if 0
|
||||
if (!cpu_profiler)
|
||||
{
|
||||
restore_mmaps();
|
||||
|
||||
clean_hijacked_nopages ();
|
||||
}
|
||||
#ifdef KERNEL24
|
||||
/* no setup needed */
|
||||
#else
|
||||
init_timer(&timer);
|
||||
timer.function = on_timer;
|
||||
#endif
|
||||
wake_up (&wait_for_exit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
++n_ticks;
|
||||
|
||||
if (current && current->pid != 0 &&
|
||||
(n_ticks % (HZ / SAMPLES_PER_SECOND)) == 0)
|
||||
{
|
||||
if (cpu_profiler)
|
||||
{
|
||||
generate_stack_trace (current, head);
|
||||
|
||||
if (head++ == &stack_traces[N_TRACES - 1])
|
||||
head = &stack_traces[0];
|
||||
|
||||
wake_up (&wait_for_trace);
|
||||
static void
|
||||
remove_timeout(void)
|
||||
{
|
||||
#ifdef KERNEL24
|
||||
exiting = 1;
|
||||
sleep_on (&wait_for_exit);
|
||||
#else
|
||||
del_timer (&timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
add_timeout(unsigned int interval,
|
||||
TimeoutFunc f)
|
||||
{
|
||||
#ifdef KERNEL24
|
||||
queue_task(&timer_task, &tq_timer);
|
||||
#else
|
||||
mod_timer(&timer, jiffies + INTERVAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The portable part of the driver starts here
|
||||
*/
|
||||
|
||||
static void
|
||||
generate_stack_trace(struct pt_regs *regs,
|
||||
SysprofStackTrace *trace)
|
||||
{
|
||||
#define START_OF_STACK 0xBFFFFFFF
|
||||
|
||||
typedef struct StackFrame StackFrame;
|
||||
struct StackFrame {
|
||||
StackFrame *next;
|
||||
void *return_address;
|
||||
};
|
||||
|
||||
StackFrame *frame;
|
||||
int i;
|
||||
|
||||
memset(trace, 0, sizeof (SysprofStackTrace));
|
||||
|
||||
trace->pid = current->pid;
|
||||
trace->truncated = 0;
|
||||
|
||||
trace->addresses[0] = (void *)regs->eip;
|
||||
i = 1;
|
||||
frame = (StackFrame *)regs->ebp;
|
||||
|
||||
while (frame && i < SYSPROF_MAX_ADDRESSES &&
|
||||
(long)frame < (long)START_OF_STACK &&
|
||||
(long)frame >= regs->esp) {
|
||||
void *next = NULL;
|
||||
|
||||
if (verify_area(VERIFY_READ, frame, sizeof(StackFrame)) == 0) {
|
||||
void *return_address;
|
||||
|
||||
__get_user (return_address, &(frame->return_address));
|
||||
__get_user (next, &(frame->next));
|
||||
trace->addresses[i++] = return_address;
|
||||
|
||||
if ((long)next <= (long)frame)
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
frame = next;
|
||||
}
|
||||
|
||||
trace->n_addresses = i;
|
||||
if (i == SYSPROF_MAX_ADDRESSES)
|
||||
trace->truncated = 1;
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
hijack_nopages (current);
|
||||
#endif
|
||||
trace->truncated = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
on_timer(unsigned long dong)
|
||||
{
|
||||
static int n_ticks = 0;
|
||||
|
||||
#ifdef KERNEL24
|
||||
if (exiting) {
|
||||
wake_up (&wait_for_exit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
queue_task (&timer_task, &tq_timer);
|
||||
#endif
|
||||
|
||||
++n_ticks;
|
||||
|
||||
if (
|
||||
#ifdef KERNEL24
|
||||
current && current->pid != 0 &&
|
||||
(n_ticks % (HZ / SAMPLES_PER_SECOND)) == 0
|
||||
#else
|
||||
current && current->pid != 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
||||
struct pt_regs *regs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) current->thread_info)) - 1;
|
||||
#if 0
|
||||
struct pt_regs *regs = (struct pt_regs *)(
|
||||
(long)current + THREAD_SIZE - sizeof (struct pt_regs));
|
||||
#endif
|
||||
|
||||
generate_stack_trace (regs, head);
|
||||
|
||||
if (head++ == &stack_traces[N_TRACES - 1])
|
||||
head = &stack_traces[0];
|
||||
|
||||
wake_up (&wait_for_trace);
|
||||
}
|
||||
|
||||
add_timeout (INTERVAL, on_timer);
|
||||
}
|
||||
|
||||
static int
|
||||
procfile_read (char *buffer,
|
||||
char **buffer_location,
|
||||
off_t offset,
|
||||
int buffer_length,
|
||||
int *eof,
|
||||
void *data)
|
||||
procfile_read(char *buffer,
|
||||
char **buffer_location,
|
||||
off_t offset,
|
||||
int buffer_len,
|
||||
int *eof,
|
||||
void *data)
|
||||
{
|
||||
#if 0
|
||||
if (offset > 0)
|
||||
return 0;
|
||||
#endif
|
||||
wait_event_interruptible(wait_for_trace, head != tail);
|
||||
|
||||
wait_event_interruptible (wait_for_trace, head != tail);
|
||||
*buffer_location = (char *)tail;
|
||||
if (tail++ == &stack_traces[N_TRACES - 1])
|
||||
tail = &stack_traces[0];
|
||||
return sizeof (SysprofStackTrace);
|
||||
if (buffer_len < sizeof (SysprofStackTrace))
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy (buffer, (char *)tail, sizeof (SysprofStackTrace));
|
||||
if (tail++ == &stack_traces[N_TRACES - 1])
|
||||
tail = &stack_traces[0];
|
||||
*buffer_location = buffer;
|
||||
|
||||
return sizeof (SysprofStackTrace);
|
||||
}
|
||||
|
||||
struct proc_dir_entry *trace_proc_file;
|
||||
|
||||
static unsigned int
|
||||
procfile_poll (struct file *filp, poll_table *poll_table)
|
||||
procfile_poll(struct file *filp, poll_table *poll_table)
|
||||
{
|
||||
if (head != tail)
|
||||
{
|
||||
return POLLIN;
|
||||
}
|
||||
poll_wait (filp, &wait_for_trace, poll_table);
|
||||
if (head != tail)
|
||||
{
|
||||
return POLLIN;
|
||||
}
|
||||
return 0;
|
||||
poll_wait(filp, &wait_for_trace, poll_table);
|
||||
if (head != tail) {
|
||||
return POLLIN | POLLRDNORM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
init_module (void)
|
||||
init_module(void)
|
||||
{
|
||||
struct task_struct *task;
|
||||
trace_proc_file =
|
||||
create_proc_entry ("sysprof-trace", S_IFREG | S_IRUGO, &proc_root);
|
||||
|
||||
if (!trace_proc_file)
|
||||
return 1;
|
||||
|
||||
trace_proc_file->read_proc = procfile_read;
|
||||
trace_proc_file->proc_fops->poll = procfile_poll;
|
||||
trace_proc_file->size = sizeof (SysprofStackTrace);
|
||||
|
||||
#if 0
|
||||
if (!cpu_profiler)
|
||||
{
|
||||
hijack_mmaps ();
|
||||
trace_proc_file =
|
||||
create_proc_entry ("sysprof-trace", S_IFREG | S_IRUGO, &proc_root);
|
||||
|
||||
for_each_process (task)
|
||||
{
|
||||
hijack_nopages (task);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
queue_task(&timer_task, &tq_timer);
|
||||
|
||||
printk (KERN_ALERT "starting sysprof module\n");
|
||||
|
||||
return 0;
|
||||
if (!trace_proc_file)
|
||||
return 1;
|
||||
|
||||
trace_proc_file->read_proc = procfile_read;
|
||||
trace_proc_file->proc_fops->poll = procfile_poll;
|
||||
trace_proc_file->size = sizeof (SysprofStackTrace);
|
||||
|
||||
init_timeout();
|
||||
|
||||
add_timeout(INTERVAL, on_timer);
|
||||
|
||||
printk(KERN_ALERT "starting sysprof module\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_module(void)
|
||||
{
|
||||
exiting = 1;
|
||||
sleep_on (&wait_for_exit);
|
||||
remove_proc_entry ("sysprof-trace", &proc_root);
|
||||
|
||||
printk (KERN_ALERT "stopping sysprof module\n");
|
||||
remove_timeout();
|
||||
|
||||
remove_proc_entry("sysprof-trace", &proc_root);
|
||||
|
||||
printk(KERN_ALERT "stopping sysprof module\n");
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
typedef struct SysprofStackTrace SysprofStackTrace;
|
||||
|
||||
#define SYSPROF_MAX_ADDRESSES 1024
|
||||
#define SYSPROF_MAX_ADDRESSES 512
|
||||
|
||||
struct SysprofStackTrace
|
||||
{
|
||||
@ -13,9 +13,6 @@ struct SysprofStackTrace
|
||||
* with -fomit-frame-pointer or is otherwise weird
|
||||
*/
|
||||
void *addresses[SYSPROF_MAX_ADDRESSES];
|
||||
|
||||
char filename[8192];
|
||||
int map_start;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
11
sysprof.c
11
sysprof.c
@ -109,7 +109,7 @@ on_read (gpointer data)
|
||||
|
||||
rd = read (app->input_fd, &trace, sizeof (trace));
|
||||
|
||||
if (app->profiling && !app->generating_profile)
|
||||
if (rd > 0 && app->profiling && !app->generating_profile)
|
||||
{
|
||||
Process *process = process_get_from_pid (trace.pid);
|
||||
int i;
|
||||
@ -122,7 +122,7 @@ on_read (gpointer data)
|
||||
process_ensure_map (process, trace.pid,
|
||||
(gulong)trace.addresses[i]);
|
||||
g_assert (!app->generating_profile);
|
||||
|
||||
|
||||
stack_stash_add_trace (
|
||||
app->stash, process,
|
||||
(gulong *)trace.addresses, trace.n_addresses, 1);
|
||||
@ -693,11 +693,14 @@ main (int argc, char **argv)
|
||||
if (app->input_fd < 0)
|
||||
{
|
||||
disaster ("Can't open /proc/sysprof-trace. You need to insert\n"
|
||||
"the sysprof kernel module. Type\n"
|
||||
"the sysprof kernel module. As root type\n"
|
||||
"\n"
|
||||
" insmod sysprof-module.o\n"
|
||||
"\n"
|
||||
"as root\n");
|
||||
"or if you are using a 2.6 kernel:\n"
|
||||
"\n"
|
||||
" insmod sysprof-module.ko\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
fd_add_watch (app->input_fd, app);
|
||||
|
||||
Reference in New Issue
Block a user