diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | module/sysprof-module.c | 21 |
2 files changed, 23 insertions, 6 deletions
@@ -1,4 +1,10 @@ -2006-06-08 Søren Sandmann <ssp@localhost.localdomain> +Sat Aug 12 16:27:13 2006 Søren Sandmann <sandmann@redhat.com> + + * module/sysprof-module.c (timer_notify): Bugfix for SMP kernel: + Make n_samples a per-CPU variable. Protect timer_notify() with an + atomic variable. + +2006-06-08 Soren Sandmann <sandmann@redhat.com> * announce-1.0.3: Fix forgotten 1.0.2 -> 1.0.3. diff --git a/module/sysprof-module.c b/module/sysprof-module.c index 100c3d5..5cee6b6 100644 --- a/module/sysprof-module.c +++ b/module/sysprof-module.c @@ -111,24 +111,31 @@ read_frame (void *frame_pointer, StackFrame *frame) return 0; } +DEFINE_PER_CPU(int, n_samples); + static int timer_notify (struct pt_regs *regs) { - static int n_samples; SysprofStackTrace *trace = head; int i; int is_user; + static atomic_t in_timer_notify = ATOMIC_INIT(1); - if ((n_samples++ % INTERVAL) != 0) + if ((++get_cpu_var(n_samples) % INTERVAL) != 0) return 0; + /* 0: locked, 1: unlocked */ + + if (!atomic_dec_and_test(&in_timer_notify)) + goto out; + is_user = user_mode(regs); if (!current || current->pid == 0) - return 0; + goto out; if (is_user && current->state != TASK_RUNNING) - return 0; + goto out; if (!is_user) { @@ -176,7 +183,9 @@ timer_notify (struct pt_regs *regs) head = &stack_traces[0]; wake_up (&wait_for_trace); - + +out: + atomic_inc(&in_timer_notify); return 0; } @@ -192,6 +201,8 @@ procfile_read(char *buffer, return -EWOULDBLOCK; *buffer_location = (char *)tail; + + BUG_ON(tail->pid == 0); if (tail++ == &stack_traces[N_TRACES - 1]) tail = &stack_traces[0]; |