mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Make n_samples per-cpu. Add an atomic variable in_timer_notify and use it
Sat Aug 12 16:13:05 2006 Søren Sandmann <sandmann@redhat.com> * module/sysprof-module.c: Make n_samples per-cpu. Add an atomic variable in_timer_notify and use it to lock out simultaneous timer interrupts. * stackstash.c (decorate_node): Make decorate_node() static * TODO
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
060fd343a8
commit
c2f754dfb6
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
Sat Aug 12 16:13:05 2006 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
|
* module/sysprof-module.c: Make n_samples per-cpu. Add an atomic
|
||||||
|
variable in_timer_notify and use it to lock out simultaneous timer
|
||||||
|
interrupts.
|
||||||
|
|
||||||
|
* stackstash.c (decorate_node): Make decorate_node() static
|
||||||
|
|
||||||
|
* TODO
|
||||||
|
|
||||||
Fri Aug 11 11:41:15 2006 Søren Sandmann <sandmann@redhat.com>
|
Fri Aug 11 11:41:15 2006 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
* TODO: Updates
|
* TODO: Updates
|
||||||
|
|||||||
34
TODO
34
TODO
@ -1,4 +1,4 @@
|
|||||||
Before 1.0.3:
|
Before 1.0.4:
|
||||||
|
|
||||||
* See if we can reproduce the problem where libraries didn't get correctly
|
* See if we can reproduce the problem where libraries didn't get correctly
|
||||||
reloaded after new versions were installed.
|
reloaded after new versions were installed.
|
||||||
@ -32,14 +32,16 @@ Before 1.0.3:
|
|||||||
|
|
||||||
Before 1.2:
|
Before 1.2:
|
||||||
|
|
||||||
* Rename stack_stash_foreach_by_address() to stack_stash_foreach_unique()
|
* Rename stack_stash_foreach_by_address() to stack_stash_foreach_unique(),
|
||||||
|
or maybe not ...
|
||||||
|
|
||||||
* Make it compilable against a non-running kernel.
|
* Make it compilable against a non-running kernel.
|
||||||
|
|
||||||
* commandline version should check that the output file is writable
|
* commandline version should check that the output file is writable
|
||||||
before starting the profiling.
|
before starting the profiling.
|
||||||
|
|
||||||
* Maybe report idle time?
|
* Maybe report idle time? Although this would come for free with the
|
||||||
|
timelines.
|
||||||
|
|
||||||
* Fix (deleted) problem. But more generally, whenever we can't display a
|
* Fix (deleted) problem. But more generally, whenever we can't display a
|
||||||
symbol, display an error message instead, ie.,
|
symbol, display an error message instead, ie.,
|
||||||
@ -366,6 +368,11 @@ When the interrupt happens,
|
|||||||
|
|
||||||
Later:
|
Later:
|
||||||
|
|
||||||
|
- On SMP systems interrupts happen unpredictably, including when another
|
||||||
|
one is running. Right now we are ignoring any interrupts that happen
|
||||||
|
when another one is running, but we should probably just save the data
|
||||||
|
in a per-cpu buffer.
|
||||||
|
|
||||||
- Find out if sysprof accurately reports time spent handling pagefaults.
|
- Find out if sysprof accurately reports time spent handling pagefaults.
|
||||||
There is evidence that it doesn't:
|
There is evidence that it doesn't:
|
||||||
- a version of sysprof took 10 seconds to load a certain profile.
|
- a version of sysprof took 10 seconds to load a certain profile.
|
||||||
@ -553,7 +560,26 @@ Later:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DONE:
|
-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ALREADY DONE -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
|
||||||
|
* It is apparently possible to get another timer interrupt in the middle
|
||||||
|
of timer_notify. If this happens the circular buffer gets screwed up and
|
||||||
|
you get crashes. Note this gets much worse on SMP (in fact how did this
|
||||||
|
work at all previously?)
|
||||||
|
|
||||||
|
Possible fixes
|
||||||
|
- have a "in timer notify" variable, then simply reject nested
|
||||||
|
interrupts
|
||||||
|
- keep a "ghost head" that timers can use to allocate new traces,
|
||||||
|
then update the real head whenever one of them completes. Note
|
||||||
|
though, that the traces will get generated in the wrong order
|
||||||
|
due to the nesting. In fact, only the outermost timernotify
|
||||||
|
can update the real head, and it should update it to ghost_head.
|
||||||
|
- do correct locking? Nah, that's crazy talk
|
||||||
|
Also note: a race is a race, and on SMP we probably can't even make it
|
||||||
|
unlikely enough to not matter.
|
||||||
|
|
||||||
|
Fixed by ignoring the nested interrupts using an atomic variable.
|
||||||
|
|
||||||
* When you load a file from the commandline, there is a weird flash of the toolbar.
|
* When you load a file from the commandline, there is a weird flash of the toolbar.
|
||||||
What's going on is this:
|
What's going on is this:
|
||||||
|
|||||||
@ -107,6 +107,8 @@ read_frame (void *frame_pointer, StackFrame *frame)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_PER_CPU (int, n_samples);
|
||||||
|
|
||||||
#ifdef OLD_PROFILE
|
#ifdef OLD_PROFILE
|
||||||
static int timer_notify(struct notifier_block * self, unsigned long val, void * data)
|
static int timer_notify(struct notifier_block * self, unsigned long val, void * data)
|
||||||
#else
|
#else
|
||||||
@ -118,23 +120,28 @@ timer_notify (struct pt_regs *regs)
|
|||||||
struct pt_regs * regs = (struct pt_regs *)data;
|
struct pt_regs * regs = (struct pt_regs *)data;
|
||||||
#endif
|
#endif
|
||||||
void *frame_pointer;
|
void *frame_pointer;
|
||||||
static int n_samples;
|
|
||||||
SysprofStackTrace *trace = head;
|
SysprofStackTrace *trace = head;
|
||||||
int i;
|
int i;
|
||||||
int is_user;
|
int is_user;
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
int result;
|
int result;
|
||||||
|
static atomic_t in_timer_notify = ATOMIC_INIT(1);
|
||||||
|
|
||||||
if ((++n_samples % INTERVAL) != 0)
|
/* 0: locked, 1: unlocked */
|
||||||
|
|
||||||
|
if (((++get_cpu_var(n_samples)) % INTERVAL) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!atomic_dec_and_test (&in_timer_notify))
|
||||||
|
goto out;
|
||||||
|
|
||||||
is_user = user_mode(regs);
|
is_user = user_mode(regs);
|
||||||
|
|
||||||
if (!current || current->pid == 0 || !current->mm)
|
if (!current || current->pid == 0 || !current->mm)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
if (is_user && current->state != TASK_RUNNING)
|
if (is_user && current->state != TASK_RUNNING)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
memset(trace, 0, sizeof (SysprofStackTrace));
|
memset(trace, 0, sizeof (SysprofStackTrace));
|
||||||
|
|
||||||
@ -171,6 +178,8 @@ timer_notify (struct pt_regs *regs)
|
|||||||
|
|
||||||
wake_up (&wait_for_trace);
|
wake_up (&wait_for_trace);
|
||||||
|
|
||||||
|
out:
|
||||||
|
atomic_inc (&in_timer_notify);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -62,7 +62,7 @@ stack_stash_new (GDestroyNotify destroy)
|
|||||||
return create_stack_stash (destroy);
|
return create_stack_stash (destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
decorate_node (StackStash *stash,
|
decorate_node (StackStash *stash,
|
||||||
StackNode *node)
|
StackNode *node)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user