From 8811ade6940ff3b458de0d0d35fe3bbc893ffa8c Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Wed, 8 Mar 2017 01:38:26 -0500 Subject: [PATCH] dtrace: get rid of dtrace_gethrtime() Remove the need for dtrace_gethrtime() and dtrace_getwalltime() because the current implementations are not deadlock safe. Signed-off-by: Kris Van Hees --- dtrace/Kbuild | 2 - dtrace/dtrace_dev.c | 6 +-- dtrace/dtrace_dif.c | 9 ++-- dtrace/dtrace_isa.c | 5 --- dtrace/dtrace_probe.c | 65 +++-------------------------- dtrace/dtrace_state.c | 20 ++++----- dtrace/include/dtrace/dtrace_impl.h | 4 +- dtrace/include/dtrace/types.h | 5 ++- dtrace/profile_dev.c | 8 ++-- 9 files changed, 30 insertions(+), 94 deletions(-) diff --git a/dtrace/Kbuild b/dtrace/Kbuild index 785bc2335c23..63892057cc39 100644 --- a/dtrace/Kbuild +++ b/dtrace/Kbuild @@ -34,7 +34,6 @@ obj-$(CONFIG_DT_PROFILE) += profile.o obj-$(CONFIG_DT_SDT) += sdt.o obj-$(CONFIG_DT_SYSTRACE) += systrace.o obj-$(CONFIG_DT_DT_TEST) += dt_test.o -obj-$(CONFIG_DT_DT_PERF) += dt_perf.o dtrace-y := dtrace_mod.o dtrace_dev.o \ dtrace_asm_$(UTS_MACHINE).o \ @@ -53,4 +52,3 @@ profile-y := profile_mod.o profile_dev.o sdt-y := sdt_mod.o sdt_dev.o sdt_$(UTS_MACHINE).o systrace-y := systrace_mod.o systrace_dev.o dt_test-y := dt_test_mod.o dt_test_dev.o -dt_perf-y := dt_perf_mod.o dt_perf_dev.o diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c index 4e08146519a5..000dcc70b2c3 100644 --- a/dtrace/dtrace_dev.c +++ b/dtrace/dtrace_dev.c @@ -840,12 +840,12 @@ static long dtrace_ioctl(struct file *file, /* * See the comment in dtrace_state_deadman() for the reason - * for setting dts_laststatus to INT64_MAX before setting + * for setting dts_laststatus to UINT64_MAX before setting * it to the correct value. */ - state->dts_laststatus = ns_to_ktime(INT64_MAX); + state->dts_laststatus = UINT64_MAX; dtrace_membar_producer(); - state->dts_laststatus = dtrace_gethrtime(); + state->dts_laststatus = jiffies; memset(&stat, 0, sizeof(stat)); diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c index 6cd62dc63bc1..046f314a40d1 100644 --- a/dtrace/dtrace_dif.c +++ b/dtrace/dtrace_dif.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -2079,8 +2080,9 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate, return (uint64_t)(uintptr_t)current; case DIF_VAR_TIMESTAMP: + case DIF_VAR_WALLTIMESTAMP: if (!(mstate->dtms_present & DTRACE_MSTATE_TIMESTAMP)) { - mstate->dtms_timestamp = dtrace_gethrtime(); + mstate->dtms_timestamp = current->dtrace_start; mstate->dtms_present |= DTRACE_MSTATE_TIMESTAMP; } @@ -2091,9 +2093,6 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate, return ktime_to_ns(current->dtrace_vtime); - case DIF_VAR_WALLTIMESTAMP: - return ktime_to_ns(dtrace_getwalltime()); - case DIF_VAR_IPL: if (!dtrace_priv_kernel(state)) return 0; @@ -2382,7 +2381,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, switch (subr) { case DIF_SUBR_RAND: - regs[rd] = ktime_to_ns(dtrace_gethrtime()) * 2416 + 374441; + regs[rd] = jiffies * 2416 + 374441; regs[rd] = do_div(regs[rd], 1771875); break; diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c index cb29accd2782..5642cedef9e0 100644 --- a/dtrace/dtrace_isa.c +++ b/dtrace/dtrace_isa.c @@ -121,11 +121,6 @@ void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, dtrace_copyinstr_arch(uaddr, kaddr, size, flags); } -ktime_t dtrace_gethrestime(void) -{ - return dtrace_gethrtime(); -} - void dtrace_getpcstack(uint64_t *pcstack, int pcstack_limit, int aframes, uint32_t *intrpc) { diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c index 3ace8ee087a0..c06089ab0864 100644 --- a/dtrace/dtrace_probe.c +++ b/dtrace/dtrace_probe.c @@ -393,49 +393,12 @@ static void dtrace_action_stop(void) static void dtrace_action_chill(dtrace_mstate_t *mstate, ktime_t val) { - ktime_t now; - volatile uint16_t *flags; - cpu_core_t *cpu = this_cpu_core; - if (dtrace_destructive_disallow) return; - flags = (volatile uint16_t *)&cpu->cpuc_dtrace_flags; - - now = dtrace_gethrtime(); - - if (ktime_gt(ktime_sub(now, cpu->cpu_dtrace_chillmark), - dtrace_chill_interval)) { - /* - * We need to advance the mark to the current time. - */ - cpu->cpu_dtrace_chillmark = now; - cpu->cpu_dtrace_chilled = ktime_set(0, 0); - } + dtrace_chill(val, dtrace_chill_interval, dtrace_chill_max); - /* - * Now check to see if the requested chill time would take us over - * the maximum amount of time allowed in the chill interval. (Or - * worse, if the calculation itself induces overflow.) - */ - if (ktime_gt(ktime_add(cpu->cpu_dtrace_chilled, val), - dtrace_chill_max) || - ktime_lt(ktime_add(cpu->cpu_dtrace_chilled, val), - cpu->cpu_dtrace_chilled)) { - *flags |= CPU_DTRACE_ILLOP; - return; - } - - while (ktime_lt(ktime_sub(dtrace_gethrtime(), now), val)) - continue; - - /* - * Normally, we assure that the value of the variable "timestamp" does - * not change within an ECB. The presence of chill() represents an - * exception to this rule, however. - */ mstate->dtms_present &= ~DTRACE_MSTATE_TIMESTAMP; - cpu->cpu_dtrace_chilled = ktime_add(cpu->cpu_dtrace_chilled, val); } static void dtrace_action_ustack(dtrace_mstate_t *mstate, @@ -559,9 +522,8 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, dtrace_action_t *act; intptr_t offs; size_t size; - int vtime, onintr; + int onintr; volatile uint16_t *flags; - ktime_t now; int pflag = 0; #ifdef FIXME @@ -629,13 +591,8 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, *flags |= CPU_DTRACE_PROBE_CTX; this_cpu_core->cpu_dtrace_caller = id; - now = dtrace_gethrtime(); - vtime = (dtrace_vtime_references > 0); - - if (vtime && ktime_nz(current->dtrace_start)) - current->dtrace_vtime = - ktime_add(current->dtrace_vtime, - ktime_sub(now, current->dtrace_start)); + if (id != dtrace_probeid_error) + dtrace_vtime_suspend(); mstate.dtms_difo = NULL; mstate.dtms_probe = probe; @@ -753,7 +710,7 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, } } - if (ktime_gt(ktime_sub(now, state->dts_alive), + if (ktime_gt(ktime_sub(current->dtrace_start, state->dts_alive), dtrace_deadman_timeout)) { /* * We seem to be dead. Unless we (a) have kernel @@ -1241,15 +1198,6 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, continue; } - if (vtime) - /* - * Before recursing on dtrace_probe(), we - * need to explicitly clear out our start - * time to prevent it from being accumulated - * into t_dtrace_vtime. - */ - current->dtrace_start = ktime_set(0, 0); - /* * Iterate over the actions to figure out which action * we were processing when we experienced the error. @@ -1283,8 +1231,7 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, id, ecb->dte_epid); } - if (vtime) - current->dtrace_start = dtrace_gethrtime(); + dtrace_vtime_resume(); /* * Only clear the flag if this is not the ERROR probe. We know that diff --git a/dtrace/dtrace_state.c b/dtrace/dtrace_state.c index 837879dd7cdd..2098d4e29bd5 100644 --- a/dtrace/dtrace_state.c +++ b/dtrace/dtrace_state.c @@ -54,11 +54,11 @@ dtrace_optval_t dtrace_jstackstrsize_default = 512; #if 1 ktime_t dtrace_deadman_interval = KTIME_INIT(10, 0); ktime_t dtrace_deadman_timeout = KTIME_INIT(120, 0); -ktime_t dtrace_deadman_user = KTIME_INIT(120, 0); +uint64_t dtrace_deadman_user = SECS_TO_JIFFIES(120); #else ktime_t dtrace_deadman_interval = KTIME_INIT(1, 0); ktime_t dtrace_deadman_timeout = KTIME_INIT(10, 0); -ktime_t dtrace_deadman_user = KTIME_INIT(30, 0); +uint64_t dtrace_deadman_user = SECS_TO_JIFFIES(30); #endif dtrace_id_t dtrace_probeid_begin; @@ -289,7 +289,7 @@ void dtrace_vstate_fini(dtrace_vstate_t *vstate) vfree(vstate->dtvs_locals); } -static void dtrace_state_clean(dtrace_state_t *state) +static void dtrace_state_clean(dtrace_state_t *state, ktime_t when) { if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE && state->dts_activity != DTRACE_ACTIVITY_DRAINING) @@ -299,10 +299,8 @@ static void dtrace_state_clean(dtrace_state_t *state) dtrace_speculation_clean(state); } -static void dtrace_state_deadman(dtrace_state_t *state) +static void dtrace_state_deadman(dtrace_state_t *state, ktime_t when) { - ktime_t now; - #ifdef FIXME /* * This may not be needed for Linux - we'll see. @@ -310,11 +308,8 @@ static void dtrace_state_deadman(dtrace_state_t *state) dtrace_sync(); #endif - now = dtrace_gethrtime(); - if (state != dtrace_anon.dta_state && - ktime_ge(ktime_sub(now, state->dts_laststatus), - dtrace_deadman_user)) + time_after_eq(jiffies, state->dts_laststatus + dtrace_deadman_user)) return; /* @@ -328,7 +323,7 @@ static void dtrace_state_deadman(dtrace_state_t *state) */ state->dts_alive = ktime_set(KTIME_SEC_MAX, 0); dtrace_membar_producer(); - state->dts_alive = now; + state->dts_alive = when; } dtrace_state_t *dtrace_state_create(struct file *file) @@ -801,8 +796,9 @@ int dtrace_state_go(dtrace_state_t *state, processorid_t *cpu) when.cyt_when = ktime_set(0, 0); when.cyt_interval = dtrace_deadman_interval; - state->dts_alive = state->dts_laststatus = dtrace_gethrtime(); state->dts_deadman = cyclic_add(&hdlr, &when); + state->dts_alive = when.cyt_when; + state->dts_laststatus = jiffies; state->dts_activity = DTRACE_ACTIVITY_WARMUP; diff --git a/dtrace/include/dtrace/dtrace_impl.h b/dtrace/include/dtrace/dtrace_impl.h index 8dcc36e447c5..0eac655974dc 100644 --- a/dtrace/include/dtrace/dtrace_impl.h +++ b/dtrace/include/dtrace/dtrace_impl.h @@ -275,9 +275,9 @@ struct dtrace_state { uint32_t dts_stkstroverflows; uint32_t dts_dblerrors; uint32_t dts_reserve; - ktime_t dts_laststatus; cyclic_id_t dts_cleaner; cyclic_id_t dts_deadman; + uint64_t dts_laststatus; ktime_t dts_alive; char dts_speculates; char dts_destructive; @@ -871,8 +871,6 @@ extern void dtrace_toxic_ranges(void (*)(uintptr_t, uintptr_t)); extern void dtrace_vpanic(const char *, va_list); extern int dtrace_getipl(void); -extern ktime_t dtrace_gethrestime(void); - extern dtrace_icookie_t dtrace_interrupt_disable(void); extern void dtrace_interrupt_enable(dtrace_icookie_t); diff --git a/dtrace/include/dtrace/types.h b/dtrace/include/dtrace/types.h index be23a34fc902..58f0331b9475 100644 --- a/dtrace/include/dtrace/types.h +++ b/dtrace/include/dtrace/types.h @@ -28,7 +28,7 @@ * * CDDL HEADER END * - * Copyright 2009 -- 2013 Oracle, Inc. All rights reserved. + * Copyright 2009-2017 Oracle, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,6 +51,7 @@ #include #include +#include typedef unsigned char uchar_t; typedef unsigned int uint_t; @@ -127,6 +128,8 @@ typedef enum { #define ktime_gt(t0, t1) ((t0).tv64 > (t1).tv64) #define ktime_cp(t0, t1) ((t0).tv64 = (t1).tv64) +#define SECS_TO_JIFFIES(s) (((s) * SEC_CONVERSION) >> SEC_JIFFIE_SC) + /* * Translate between kernel config options and userspace-compatible definitions. */ diff --git a/dtrace/profile_dev.c b/dtrace/profile_dev.c index 73aba6fd9d04..f855ed805db3 100644 --- a/dtrace/profile_dev.c +++ b/dtrace/profile_dev.c @@ -87,7 +87,7 @@ static int profile_ticks[] = { static int profile_max; /* maximum number of profile probes */ static atomic_t profile_total; /* current number of profile probes */ -static void profile_tick_fn(uintptr_t arg) +static void profile_tick_fn(uintptr_t arg, ktime_t when) { profile_probe_t *prof = (profile_probe_t *)arg; unsigned long pc = 0, upc = 0; @@ -114,7 +114,7 @@ static void profile_tick_fn(uintptr_t arg) dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0); } -static void profile_prof_fn(uintptr_t arg) +static void profile_prof_fn(uintptr_t arg, ktime_t when) { profile_probe_percpu_t *pcpu = (profile_probe_percpu_t *)arg; profile_probe_t *prof = pcpu->profc_probe; @@ -122,7 +122,7 @@ static void profile_prof_fn(uintptr_t arg) struct pt_regs *regs = get_irq_regs(); unsigned long pc = 0, upc = 0; - late = ktime_sub(dtrace_gethrtime(), pcpu->profc_expected); + late = ktime_sub(when, pcpu->profc_expected); pcpu->profc_expected = ktime_add(pcpu->profc_expected, pcpu->profc_interval); @@ -161,7 +161,7 @@ static void profile_online(void *arg, processorid_t cpu, cyc_handler_t *hdlr, hdlr->cyh_level = CY_HIGH_LEVEL; when->cyt_interval = prof->prof_interval; - when->cyt_when = ktime_add(dtrace_gethrtime(), when->cyt_interval); + when->cyt_when = ktime_add(when->cyt_when, when->cyt_interval); pcpu->profc_expected = when->cyt_when; pcpu->profc_interval = when->cyt_interval; -- 2.50.1