Thomas Renninger
71b8c4302b
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
142 lines
4.5 KiB
Diff
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";
|