mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
Updates
Sat Jun 18 22:45:04 2005 Søren Sandmann <sandmann@redhat.com> * TODO: Updates * configure.ac: Check for Linux 2.6.11 * process.c (get_pidname): Present pid=-1 as [kernel]. * module/sysprof-module.c: Use register_timer_hook() instead of a kernel timer. Set trace.pid to -1 if interrupt happens in kernel.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
fb7e1ddc47
commit
18abd9e1e6
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
Sat Jun 18 22:45:04 2005 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
|
* TODO: Updates
|
||||||
|
|
||||||
|
* configure.ac: Check for Linux 2.6.11
|
||||||
|
|
||||||
|
* process.c (get_pidname): Present pid=-1 as [kernel].
|
||||||
|
|
||||||
|
* module/sysprof-module.c: Use register_timer_hook() instead of
|
||||||
|
a kernel timer. Set trace.pid to -1 if interrupt happens in
|
||||||
|
kernel.
|
||||||
|
|
||||||
Sun Jun 12 20:30:37 2005 Soeren Sandmann <sandmann@redhat.com>
|
Sun Jun 12 20:30:37 2005 Soeren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
* sysprof.c (build_gui): Disable type-ahead search for all the
|
* sysprof.c (build_gui): Disable type-ahead search for all the
|
||||||
|
|||||||
2
README
2
README
@ -6,7 +6,7 @@ See http://www.daimi.au.dk/~sandmann/sysprof/ for more information
|
|||||||
|
|
||||||
- You need gtk+ 2.6.0 or better.
|
- You need gtk+ 2.6.0 or better.
|
||||||
|
|
||||||
- You need a 2.6 kernel. On SMP kernels the module produces unreliable data.
|
- You need at least Linux 2.6.11
|
||||||
|
|
||||||
- The module must be compiled with the same compiler that compiled the
|
- The module must be compiled with the same compiler that compiled the
|
||||||
kernel it is going to be used with. For most systems that is just
|
kernel it is going to be used with. For most systems that is just
|
||||||
|
|||||||
19
TODO
19
TODO
@ -19,6 +19,12 @@ Before 1.2:
|
|||||||
|
|
||||||
* See if the auto-expanding can be made more intelligent
|
* See if the auto-expanding can be made more intelligent
|
||||||
|
|
||||||
|
* Send entire stack to user space, then do stackwalking there
|
||||||
|
|
||||||
|
* If interrupt happens in kernel mode, send both
|
||||||
|
kernel stack and user space stack, have userspace stitch them
|
||||||
|
together.
|
||||||
|
|
||||||
* Correctness
|
* Correctness
|
||||||
- When the module is unloaded, kill all processes blocking in read
|
- When the module is unloaded, kill all processes blocking in read
|
||||||
- or block unloading until all processes have exited
|
- or block unloading until all processes have exited
|
||||||
@ -41,13 +47,17 @@ Before 1.2:
|
|||||||
UI: "generate screenshot" menu item pops up a window with
|
UI: "generate screenshot" menu item pops up a window with
|
||||||
a text area + a radio buttons "text/html". When you flick
|
a text area + a radio buttons "text/html". When you flick
|
||||||
them, the text area is automatically updated.
|
them, the text area is automatically updated.
|
||||||
|
|
||||||
- Fixing the oops in kernels < 2.6.11
|
- Fixing the oops in kernels < 2.6.11
|
||||||
|
|
||||||
|
- Probably just require 2.6.11 (necessary for timer interrupt
|
||||||
|
based anyway).
|
||||||
|
|
||||||
- Make the process waiting in poll() responsible for extracting
|
- Make the process waiting in poll() responsible for extracting
|
||||||
the backtrace. Give a copy of the entire stack rather than doing
|
the backtrace. Give a copy of the entire stack rather than doing
|
||||||
the walk inside the kernel. That would allow us to do more complex
|
the walk inside the kernel. That would allow us to do more complex
|
||||||
algorithms in userspace (though we'd lose the ability to do non-racy
|
algorithms in userspace. Though we'd lose the ability to do non-racy
|
||||||
file naming).
|
file naming. We could pass a list of the process mappings though.
|
||||||
|
|
||||||
New model:
|
New model:
|
||||||
- Two arrays,
|
- Two arrays,
|
||||||
@ -201,6 +211,9 @@ http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/ehframe.html
|
|||||||
|
|
||||||
Later:
|
Later:
|
||||||
|
|
||||||
|
- See if it is possible to group the X server activity under the process that
|
||||||
|
generated it.
|
||||||
|
|
||||||
- .desktop file
|
- .desktop file
|
||||||
[Is this worth it? You will often want to start it as root,
|
[Is this worth it? You will often want to start it as root,
|
||||||
and you will need to insert the module from the command line]
|
and you will need to insert the module from the command line]
|
||||||
@ -348,6 +361,8 @@ Later:
|
|||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
|
|
||||||
|
* Timer interrupt based
|
||||||
|
|
||||||
* Interface
|
* Interface
|
||||||
- Consider expanding a few more levels of a new descendants tree
|
- Consider expanding a few more levels of a new descendants tree
|
||||||
- Algorithm should be expand in proportion to the
|
- Algorithm should be expand in proportion to the
|
||||||
|
|||||||
16
configure.ac
16
configure.ac
@ -61,6 +61,7 @@ AC_CHECK_LIB(bfd, bfd_get_error, [DEP_LIBS="$DEP_LIBS -lbfd -liberty"],
|
|||||||
AC_MSG_ERROR([libbfd is required to compile sysprof]),
|
AC_MSG_ERROR([libbfd is required to compile sysprof]),
|
||||||
-liberty)
|
-liberty)
|
||||||
|
|
||||||
|
|
||||||
# emit files
|
# emit files
|
||||||
|
|
||||||
AC_SUBST(DEP_LIBS)
|
AC_SUBST(DEP_LIBS)
|
||||||
@ -69,4 +70,19 @@ AC_CONFIG_FILES([
|
|||||||
Makefile
|
Makefile
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# Kernel version
|
||||||
|
|
||||||
|
KMAJOR=`uname -r | cut -d"." -f 1`
|
||||||
|
KMINOR=`uname -r | cut -d"." -f 2`
|
||||||
|
KMICRO=`uname -r | cut -d"." -f 3 | cut -d"-" -f 1`
|
||||||
|
|
||||||
|
if [[ $KMICRO -lt 11 ]] ; then
|
||||||
|
if [[ $KMICRO -gt 8 ]]; then
|
||||||
|
echo
|
||||||
|
echo Linux \>= 2.6.11 is required
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@ -42,7 +42,7 @@
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Soeren Sandmann (sandmann@daimi.au.dk)");
|
MODULE_AUTHOR("Soeren Sandmann (sandmann@daimi.au.dk)");
|
||||||
|
|
||||||
#define SAMPLES_PER_SECOND (100)
|
#define SAMPLES_PER_SECOND (256)
|
||||||
#define INTERVAL (HZ / SAMPLES_PER_SECOND)
|
#define INTERVAL (HZ / SAMPLES_PER_SECOND)
|
||||||
#define N_TRACES 256
|
#define N_TRACES 256
|
||||||
|
|
||||||
@ -52,8 +52,12 @@ static SysprofStackTrace * tail = &stack_traces[0];
|
|||||||
DECLARE_WAIT_QUEUE_HEAD (wait_for_trace);
|
DECLARE_WAIT_QUEUE_HEAD (wait_for_trace);
|
||||||
DECLARE_WAIT_QUEUE_HEAD (wait_for_exit);
|
DECLARE_WAIT_QUEUE_HEAD (wait_for_exit);
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void on_timer(unsigned long);
|
static void on_timer(unsigned long);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
static struct timer_list timer;
|
static struct timer_list timer;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct userspace_reader userspace_reader;
|
typedef struct userspace_reader userspace_reader;
|
||||||
struct userspace_reader
|
struct userspace_reader
|
||||||
@ -63,6 +67,7 @@ struct userspace_reader
|
|||||||
unsigned long *cache;
|
unsigned long *cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* This function was mostly cutted and pasted from ptrace.c
|
/* This function was mostly cutted and pasted from ptrace.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -93,7 +98,9 @@ put_mm (struct mm_struct *mm)
|
|||||||
mmput(mm);
|
mmput(mm);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int
|
static int
|
||||||
x_access_process_vm (struct task_struct *tsk,
|
x_access_process_vm (struct task_struct *tsk,
|
||||||
unsigned long addr,
|
unsigned long addr,
|
||||||
@ -153,7 +160,9 @@ x_access_process_vm (struct task_struct *tsk,
|
|||||||
|
|
||||||
return buf - old_buf;
|
return buf - old_buf;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int
|
static int
|
||||||
init_userspace_reader (userspace_reader *reader,
|
init_userspace_reader (userspace_reader *reader,
|
||||||
struct task_struct *task)
|
struct task_struct *task)
|
||||||
@ -165,7 +174,9 @@ init_userspace_reader (userspace_reader *reader,
|
|||||||
reader->cache_address = 0x0;
|
reader->cache_address = 0x0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int
|
static int
|
||||||
page_readable (userspace_reader *reader, unsigned long address)
|
page_readable (userspace_reader *reader, unsigned long address)
|
||||||
{
|
{
|
||||||
@ -188,7 +199,9 @@ page_readable (userspace_reader *reader, unsigned long address)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int
|
static int
|
||||||
read_user_space (userspace_reader *reader,
|
read_user_space (userspace_reader *reader,
|
||||||
unsigned long address,
|
unsigned long address,
|
||||||
@ -219,12 +232,15 @@ read_user_space (userspace_reader *reader,
|
|||||||
*result = reader->cache[index];
|
*result = reader->cache[index];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
done_userspace_reader (userspace_reader *reader)
|
done_userspace_reader (userspace_reader *reader)
|
||||||
{
|
{
|
||||||
kfree (reader->cache);
|
kfree (reader->cache);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct StackFrame StackFrame;
|
typedef struct StackFrame StackFrame;
|
||||||
struct StackFrame {
|
struct StackFrame {
|
||||||
@ -232,6 +248,7 @@ struct StackFrame {
|
|||||||
unsigned long return_address;
|
unsigned long return_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int
|
static int
|
||||||
read_frame (userspace_reader *reader, unsigned long addr, StackFrame *frame)
|
read_frame (userspace_reader *reader, unsigned long addr, StackFrame *frame)
|
||||||
{
|
{
|
||||||
@ -249,7 +266,9 @@ read_frame (userspace_reader *reader, unsigned long addr, StackFrame *frame)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static struct pt_regs *
|
static struct pt_regs *
|
||||||
get_regs (struct task_struct *task)
|
get_regs (struct task_struct *task)
|
||||||
{
|
{
|
||||||
@ -268,16 +287,13 @@ get_regs (struct task_struct *task)
|
|||||||
return task_pt_regs (task);
|
return task_pt_regs (task);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
generate_stack_trace(struct task_struct *task,
|
generate_stack_trace(struct task_struct *task,
|
||||||
SysprofStackTrace *trace)
|
SysprofStackTrace *trace)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_HIGHMEM
|
|
||||||
# define START_OF_STACK 0xFF000000
|
|
||||||
#else
|
|
||||||
# define START_OF_STACK 0xBFFFFFFF
|
|
||||||
#endif
|
|
||||||
struct pt_regs *regs = get_regs (task); // task->thread.regs;
|
struct pt_regs *regs = get_regs (task); // task->thread.regs;
|
||||||
|
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
@ -319,7 +335,9 @@ generate_stack_trace(struct task_struct *task,
|
|||||||
else
|
else
|
||||||
trace->truncated = 0;
|
trace->truncated = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
do_generate (void *data)
|
do_generate (void *data)
|
||||||
{
|
{
|
||||||
@ -341,9 +359,11 @@ do_generate (void *data)
|
|||||||
|
|
||||||
mod_timer(&timer, jiffies + INTERVAL);
|
mod_timer(&timer, jiffies + INTERVAL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
on_timer(unsigned long dong)
|
on_timer(unsigned long dong)
|
||||||
{
|
{
|
||||||
@ -360,6 +380,110 @@ on_timer(unsigned long dong)
|
|||||||
mod_timer(&timer, jiffies + INTERVAL);
|
mod_timer(&timer, jiffies + INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pages_present() from OProfile
|
||||||
|
*
|
||||||
|
* Copyright 2002 OProfile authors
|
||||||
|
*
|
||||||
|
* author John Levon
|
||||||
|
* author David Smith
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_4G
|
||||||
|
/* With a 4G kernel/user split, user pages are not directly
|
||||||
|
* accessible from the kernel, so don't try
|
||||||
|
*/
|
||||||
|
static int pages_present(StackFrame * head)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* check that the page(s) containing the frame head are present */
|
||||||
|
static int pages_present(StackFrame * head)
|
||||||
|
{
|
||||||
|
struct mm_struct * mm = current->mm;
|
||||||
|
|
||||||
|
/* FIXME: only necessary once per page */
|
||||||
|
if (!check_user_page_readable(mm, (unsigned long)head))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return check_user_page_readable(mm, (unsigned long)(head + 1));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_X86_4G */
|
||||||
|
|
||||||
|
static int
|
||||||
|
timer_notify (struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
# define START_OF_STACK 0xFF000000
|
||||||
|
#else
|
||||||
|
# define START_OF_STACK 0xBFFFFFFF
|
||||||
|
#endif
|
||||||
|
StackFrame *frame;
|
||||||
|
static int n_samples;
|
||||||
|
SysprofStackTrace *trace = head;
|
||||||
|
int i;
|
||||||
|
int is_user;
|
||||||
|
|
||||||
|
if ((n_samples++ % INTERVAL) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
is_user = user_mode(regs);
|
||||||
|
|
||||||
|
if (!current || current->pid == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (is_user && current->state != TASK_RUNNING)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!is_user)
|
||||||
|
{
|
||||||
|
/* kernel */
|
||||||
|
|
||||||
|
trace->pid = -1;
|
||||||
|
trace->truncated = 0;
|
||||||
|
trace->n_addresses = 1;
|
||||||
|
trace->addresses[0] = 0x0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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 (pages_present (frame) &&
|
||||||
|
i < SYSPROF_MAX_ADDRESSES &&
|
||||||
|
((unsigned long)frame) < START_OF_STACK &&
|
||||||
|
(unsigned long)frame >= regs->esp)
|
||||||
|
{
|
||||||
|
trace->addresses[i++] = (void *)frame->return_address;
|
||||||
|
frame = (StackFrame *)frame->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace->n_addresses = i;
|
||||||
|
|
||||||
|
if (i == SYSPROF_MAX_ADDRESSES)
|
||||||
|
trace->truncated = 1;
|
||||||
|
else
|
||||||
|
trace->truncated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head++ == &stack_traces[N_TRACES - 1])
|
||||||
|
head = &stack_traces[0];
|
||||||
|
|
||||||
|
wake_up (&wait_for_trace);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
procfile_read(char *buffer,
|
procfile_read(char *buffer,
|
||||||
@ -408,9 +532,13 @@ init_module(void)
|
|||||||
trace_proc_file->proc_fops->poll = procfile_poll;
|
trace_proc_file->proc_fops->poll = procfile_poll;
|
||||||
trace_proc_file->size = sizeof (SysprofStackTrace);
|
trace_proc_file->size = sizeof (SysprofStackTrace);
|
||||||
|
|
||||||
|
register_timer_hook (timer_notify);
|
||||||
|
|
||||||
|
#if 0
|
||||||
init_timer(&timer);
|
init_timer(&timer);
|
||||||
timer.function = on_timer;
|
timer.function = on_timer;
|
||||||
mod_timer(&timer, jiffies + INTERVAL);
|
mod_timer(&timer, jiffies + INTERVAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
printk(KERN_ALERT "starting sysprof module\n");
|
printk(KERN_ALERT "starting sysprof module\n");
|
||||||
|
|
||||||
@ -420,7 +548,11 @@ init_module(void)
|
|||||||
void
|
void
|
||||||
cleanup_module(void)
|
cleanup_module(void)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
del_timer (&timer);
|
del_timer (&timer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unregister_timer_hook (timer_notify);
|
||||||
|
|
||||||
remove_proc_entry("sysprof-trace", &proc_root);
|
remove_proc_entry("sysprof-trace", &proc_root);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ typedef struct SysprofStackTrace SysprofStackTrace;
|
|||||||
|
|
||||||
struct SysprofStackTrace
|
struct SysprofStackTrace
|
||||||
{
|
{
|
||||||
int pid;
|
int pid; /* -1 if in kernel */
|
||||||
int truncated;
|
int truncated;
|
||||||
int n_addresses; /* note: this can be 1 if the process was compiled
|
int n_addresses; /* note: this can be 1 if the process was compiled
|
||||||
* with -fomit-frame-pointer or is otherwise weird
|
* with -fomit-frame-pointer or is otherwise weird
|
||||||
|
|||||||
@ -292,7 +292,10 @@ get_statname (int pid)
|
|||||||
static char *
|
static char *
|
||||||
get_pidname (int pid)
|
get_pidname (int pid)
|
||||||
{
|
{
|
||||||
return g_strdup_printf ("[pid %d]", pid);
|
if (pid == -1)
|
||||||
|
return g_strdup_printf ("kernel", pid);
|
||||||
|
else
|
||||||
|
return g_strdup_printf ("pid %d", pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
|||||||
Reference in New Issue
Block a user