From: Josh Stone 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 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";