systemtap/systemtap_improve_gettimeofday_stability.patch
Thomas Renninger 71b8c4302b - Hopefully fix bnc#664105:
Kernel segfault in kernel/timer.c - comm: stapio (process) - related to preloadtrace.ko

OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=20
2011-01-14 14:50:30 +00:00

142 lines
4.5 KiB
Diff

From: Josh Stone <jistone@redhat.com>
Subject: Improve gettimeofday stability
References: bnc#664105
Patch-Mainline: yes
Git-commit: 3fd1c4901e81e5f6b550bb988d612281e0fc231b
Git-repo: git://sources.redhat.com/git/systemtap.git
Signed-off-by: Thomas Renninger <trenn@suse.de>
These are a few tweaks to improve the stability of our gettimeofday
startup and shutdown. Hopefully this helps with PR10651 and PR12182,
but that's not been confirmed yet.
* runtime/runtime.h: Don't include time.c here.
* translate.cxx (c_unparser::emit_common_header): Include time.c here,
only if NEEDed (so we also ensure init/kill_time will be called).
(c_unparser::emit_module_init): Change to STAP_SESSION_STOPPED for the
final cleanup efforts, especially for time.c to wrap up.
(c_unparser::emit_module_exit): Ditto.
* runtime/time.c (__stp_time_timer_callback): Use the session_state
instead of stp_timer_reregister, and continue until STOPPED.
(__stp_init_time): Don't add_timer from the IPI.
(_stp_init_time): Instead, add_timer_on each cpu here.
diff --git a/runtime/runtime.h b/runtime/runtime.h
index d4f41db..814d8ad 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -132,7 +132,6 @@ static struct
#include "copy.c"
#include "regs.c"
#include "regs-ia64.c"
-#include "time.c"
#include "task_finder.c"
diff --git a/runtime/time.c b/runtime/time.c
index 0d13487..38a808a 100644
--- a/runtime/time.c
+++ b/runtime/time.c
@@ -56,9 +56,6 @@ typedef struct __stp_time_t {
static void *stp_time = NULL;
-/* Flag to tell the timer callback whether to reregister */
-static int stp_timer_reregister = 0;
-
/* Try to estimate the number of CPU cycles in a millisecond - i.e. kHz. This
* relies heavily on the accuracy of udelay. By calling udelay twice, we
* attempt to account for overhead in the call.
@@ -134,7 +131,7 @@ __stp_time_timer_callback(unsigned long val)
XXX: The worst that can probably happen is that we get
two consecutive timer resets. */
- if (likely(stp_timer_reregister))
+ if (likely(atomic_read(&session_state) != STAP_SESSION_STOPPED))
mod_timer(&time->timer, jiffies + 1);
}
@@ -154,7 +151,6 @@ __stp_init_time(void *info)
init_timer(&time->timer);
time->timer.expires = jiffies + 1;
time->timer.function = __stp_time_timer_callback;
- add_timer(&time->timer);
}
#ifdef CONFIG_CPU_FREQ
@@ -208,7 +204,6 @@ _stp_kill_time(void)
{
if (stp_time) {
int cpu;
- stp_timer_reregister = 0;
for_each_online_cpu(cpu) {
stp_time_t *time = per_cpu_ptr(stp_time, cpu);
del_timer_sync(&time->timer);
@@ -229,20 +224,23 @@ _stp_kill_time(void)
static int
_stp_init_time(void)
{
- int ret = 0;
+ int cpu, ret = 0;
_stp_kill_time();
stp_time = _stp_alloc_percpu(sizeof(stp_time_t));
if (unlikely(stp_time == 0))
return -1;
-
- stp_timer_reregister = 1;
+
#ifdef STAPCONF_ONEACHCPU_RETRY
ret = on_each_cpu(__stp_init_time, NULL, 0, 1);
#else
ret = on_each_cpu(__stp_init_time, NULL, 1);
#endif
+ for_each_online_cpu(cpu) {
+ stp_time_t *time = per_cpu_ptr(stp_time, cpu);
+ add_timer_on(&time->timer, cpu);
+ }
#ifdef CONFIG_CPU_FREQ
if (!ret && !__stp_constant_freq()) {
@@ -250,7 +248,6 @@ _stp_init_time(void)
CPUFREQ_TRANSITION_NOTIFIER);
if (!ret) {
- int cpu;
for_each_online_cpu(cpu) {
unsigned long flags;
int freq_khz = cpufreq_get(cpu);
diff --git a/translate.cxx b/translate.cxx
index f360940..4447a24 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1085,6 +1085,10 @@ c_unparser::emit_common_header ()
if (!session->stat_decls.empty())
o->newline() << "#include \"stat.c\"\n";
+ o->newline() << "#ifdef STAP_NEED_GETTIMEOFDAY";
+ o->newline() << "#include \"time.c\""; // Don't we all need more?
+ o->newline() << "#endif";
+
o->newline();
}
@@ -1327,6 +1331,7 @@ c_unparser::emit_module_init ()
}
// For any partially registered/unregistered kernel facilities.
+ o->newline() << "atomic_set (&session_state, STAP_SESSION_STOPPED);";
o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
o->newline() << "synchronize_sched();";
o->newline() << "#endif";
@@ -1409,6 +1414,7 @@ c_unparser::emit_module_exit ()
o->newline(-2) << "} while (holdon);";
// cargo cult epilogue
+ o->newline() << "atomic_set (&session_state, STAP_SESSION_STOPPED);";
o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
o->newline() << "synchronize_sched();";
o->newline() << "#endif";