Date: Sun, 7 Dec 2014 11:21:42 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r275576 - in head/sys: cddl/compat/opensolaris/sys cddl/contrib/opensolaris/uts/common/dtrace cddl/contrib/opensolaris/uts/common/sys cddl/dev/cyclic cddl/dev/fbt cddl/dev/profile kern ... Message-ID: <201412071121.sB7BLgnH040986@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Sun Dec 7 11:21:41 2014 New Revision: 275576 URL: https://svnweb.freebsd.org/changeset/base/275576 Log: remove opensolaris cyclic code, replace with high-precision callouts In the old days callout(9) had 1 tick precision and that was inadequate for some uses, e.g. DTrace profile module, so we had to emulate cyclic API and behavior. Now we can directly use callout(9) in the very few places where cyclic was used. Differential Revision: https://reviews.freebsd.org/D1161 Reviewed by: gnn, jhb, markj MFC after: 2 weeks Deleted: head/sys/cddl/compat/opensolaris/sys/cyclic.h head/sys/cddl/compat/opensolaris/sys/cyclic_impl.h head/sys/cddl/dev/cyclic/ head/sys/modules/cyclic/ Modified: head/sys/cddl/compat/opensolaris/sys/cpuvar.h head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h head/sys/cddl/dev/fbt/fbt.c head/sys/cddl/dev/profile/profile.c head/sys/kern/kern_clocksource.c head/sys/modules/Makefile head/sys/modules/dtrace/Makefile.inc head/sys/modules/dtrace/dtraceall/dtraceall.c head/sys/sys/dtrace_bsd.h Modified: head/sys/cddl/compat/opensolaris/sys/cpuvar.h ============================================================================== --- head/sys/cddl/compat/opensolaris/sys/cpuvar.h Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/cddl/compat/opensolaris/sys/cpuvar.h Sun Dec 7 11:21:41 2014 (r275576) @@ -38,11 +38,8 @@ struct cyc_cpu; typedef struct { int cpuid; - struct cyc_cpu *cpu_cyclic; uint32_t cpu_flags; uint_t cpu_intr_actv; - uintptr_t cpu_profile_pc; - uintptr_t cpu_profile_upc; uintptr_t cpu_dtrace_caller; /* DTrace: caller, if any */ hrtime_t cpu_dtrace_chillmark; /* DTrace: chill mark time */ hrtime_t cpu_dtrace_chilled; /* DTrace: total chill time */ Modified: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c Sun Dec 7 11:21:41 2014 (r275576) @@ -17947,6 +17947,5 @@ SYSINIT(dtrace_anon_init, SI_SUB_DTRACE_ DEV_MODULE(dtrace, dtrace_modevent, NULL); MODULE_VERSION(dtrace, 1); -MODULE_DEPEND(dtrace, cyclic, 1, 1, 1); MODULE_DEPEND(dtrace, opensolaris, 1, 1, 1); #endif Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h Sun Dec 7 11:21:41 2014 (r275576) @@ -57,6 +57,7 @@ extern "C" { #if defined(sun) #include <sys/systm.h> #else +#include <sys/cpuvar.h> #include <sys/param.h> #include <sys/linker.h> #include <sys/ioccom.h> @@ -64,8 +65,8 @@ extern "C" { typedef int model_t; #endif #include <sys/ctf_api.h> -#include <sys/cyclic.h> #if defined(sun) +#include <sys/cyclic.h> #include <sys/int_limits.h> #else #include <sys/stdint.h> Modified: head/sys/cddl/dev/fbt/fbt.c ============================================================================== --- head/sys/cddl/dev/fbt/fbt.c Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/cddl/dev/fbt/fbt.c Sun Dec 7 11:21:41 2014 (r275576) @@ -145,13 +145,6 @@ fbt_provide_module(void *arg, modctl_t * return; /* - * The cyclic timer subsystem can be built as a module and DTrace - * depends on that, so it is ineligible too. - */ - if (strcmp(modname, "cyclic") == 0) - return; - - /* * To register with DTrace, a module must list 'dtrace' as a * dependency in order for the kernel linker to resolve * symbols like dtrace_register(). All modules with such a Modified: head/sys/cddl/dev/profile/profile.c ============================================================================== --- head/sys/cddl/dev/profile/profile.c Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/cddl/dev/profile/profile.c Sun Dec 7 11:21:41 2014 (r275576) @@ -52,9 +52,9 @@ #include <sys/smp.h> #include <sys/uio.h> #include <sys/unistd.h> +#include <machine/cpu.h> #include <machine/stdarg.h> -#include <sys/cyclic.h> #include <sys/dtrace.h> #include <sys/dtrace_bsd.h> @@ -97,7 +97,7 @@ * allow for a manual override in case we get it completely wrong. */ #ifdef __amd64 -#define PROF_ARTIFICIAL_FRAMES 7 +#define PROF_ARTIFICIAL_FRAMES 10 #else #ifdef __i386 #define PROF_ARTIFICIAL_FRAMES 6 @@ -126,18 +126,30 @@ #define PROF_ARTIFICIAL_FRAMES 3 #endif +struct profile_probe_percpu; + typedef struct profile_probe { char prof_name[PROF_NAMELEN]; dtrace_id_t prof_id; int prof_kind; +#ifdef illumos hrtime_t prof_interval; cyclic_id_t prof_cyclic; +#else + sbintime_t prof_interval; + struct callout prof_cyclic; + sbintime_t prof_expected; + struct profile_probe_percpu **prof_pcpus; +#endif } profile_probe_t; typedef struct profile_probe_percpu { hrtime_t profc_expected; hrtime_t profc_interval; profile_probe_t *profc_probe; +#ifdef __FreeBSD__ + struct callout profc_cyclic; +#endif } profile_probe_percpu_t; static d_open_t profile_open; @@ -206,29 +218,92 @@ static dtrace_provider_id_t profile_id; static hrtime_t profile_interval_min = NANOSEC / 5000; /* 5000 hz */ static int profile_aframes = 0; /* override */ +static sbintime_t +nsec_to_sbt(hrtime_t nsec) +{ + time_t sec; + + /* + * We need to calculate nsec * 2^32 / 10^9 + * Seconds and nanoseconds are split to avoid overflow. + */ + sec = nsec / NANOSEC; + nsec = nsec % NANOSEC; + return (((sbintime_t)sec << 32) | ((sbintime_t)nsec << 32) / NANOSEC); +} + +static hrtime_t +sbt_to_nsec(sbintime_t sbt) +{ + + return ((sbt >> 32) * NANOSEC + + (((uint32_t)sbt * (hrtime_t)NANOSEC) >> 32)); +} + static void profile_fire(void *arg) { profile_probe_percpu_t *pcpu = arg; profile_probe_t *prof = pcpu->profc_probe; hrtime_t late; - solaris_cpu_t *c = &solaris_cpu[curcpu]; + struct trapframe *frame; + uintfptr_t pc, upc; +#ifdef illumos late = gethrtime() - pcpu->profc_expected; - pcpu->profc_expected += pcpu->profc_interval; +#else + late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected); +#endif - dtrace_probe(prof->prof_id, c->cpu_profile_pc, - c->cpu_profile_upc, late, 0, 0); + pc = 0; + upc = 0; + + /* + * td_intr_frame can be unset if this is a catch up event + * after waking up from idle sleep. + * This can only happen on a CPU idle thread. + */ + frame = curthread->td_intr_frame; + if (frame != NULL) { + if (TRAPF_USERMODE(frame)) + upc = TRAPF_PC(frame); + else + pc = TRAPF_PC(frame); + } + dtrace_probe(prof->prof_id, pc, upc, late, 0, 0); + + pcpu->profc_expected += pcpu->profc_interval; + callout_schedule_sbt_curcpu(&pcpu->profc_cyclic, + pcpu->profc_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE); } static void profile_tick(void *arg) { profile_probe_t *prof = arg; - solaris_cpu_t *c = &solaris_cpu[curcpu]; + struct trapframe *frame; + uintfptr_t pc, upc; + + pc = 0; + upc = 0; + + /* + * td_intr_frame can be unset if this is a catch up event + * after waking up from idle sleep. + * This can only happen on a CPU idle thread. + */ + frame = curthread->td_intr_frame; + if (frame != NULL) { + if (TRAPF_USERMODE(frame)) + upc = TRAPF_PC(frame); + else + pc = TRAPF_PC(frame); + } + dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0); - dtrace_probe(prof->prof_id, c->cpu_profile_pc, - c->cpu_profile_upc, 0, 0, 0); + prof->prof_expected += prof->prof_interval; + callout_schedule_sbt(&prof->prof_cyclic, + prof->prof_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE); } static void @@ -250,8 +325,13 @@ profile_create(hrtime_t interval, char * prof = kmem_zalloc(sizeof (profile_probe_t), KM_SLEEP); (void) strcpy(prof->prof_name, name); +#ifdef illumos prof->prof_interval = interval; prof->prof_cyclic = CYCLIC_NONE; +#else + prof->prof_interval = nsec_to_sbt(interval); + callout_init(&prof->prof_cyclic, CALLOUT_MPSAFE); +#endif prof->prof_kind = kind; prof->prof_id = dtrace_probe_create(profile_id, NULL, NULL, name, @@ -396,13 +476,18 @@ profile_destroy(void *arg, dtrace_id_t i { profile_probe_t *prof = parg; +#ifdef illumos ASSERT(prof->prof_cyclic == CYCLIC_NONE); +#else + ASSERT(!callout_active(&prof->prof_cyclic) && prof->prof_pcpus == NULL); +#endif kmem_free(prof, sizeof (profile_probe_t)); ASSERT(profile_total >= 1); atomic_add_32(&profile_total, -1); } +#ifdef illumos /*ARGSUSED*/ static void profile_online(void *arg, cpu_t *cpu, cyc_handler_t *hdlr, cyc_time_t *when) @@ -478,6 +563,81 @@ profile_disable(void *arg, dtrace_id_t i prof->prof_cyclic = CYCLIC_NONE; } +#else + +static void +profile_enable_omni(profile_probe_t *prof) +{ + profile_probe_percpu_t *pcpu; + int cpu; + + prof->prof_pcpus = kmem_zalloc((mp_maxid + 1) * sizeof(pcpu), KM_SLEEP); + CPU_FOREACH(cpu) { + pcpu = kmem_zalloc(sizeof(profile_probe_percpu_t), KM_SLEEP); + prof->prof_pcpus[cpu] = pcpu; + pcpu->profc_probe = prof; + pcpu->profc_expected = sbinuptime() + prof->prof_interval; + pcpu->profc_interval = prof->prof_interval; + callout_init(&pcpu->profc_cyclic, CALLOUT_MPSAFE); + callout_reset_sbt_on(&pcpu->profc_cyclic, + pcpu->profc_expected, 0, profile_fire, pcpu, + cpu, C_DIRECT_EXEC | C_ABSOLUTE); + } +} + +static void +profile_disable_omni(profile_probe_t *prof) +{ + profile_probe_percpu_t *pcpu; + int cpu; + + ASSERT(prof->prof_pcpus != NULL); + CPU_FOREACH(cpu) { + pcpu = prof->prof_pcpus[cpu]; + ASSERT(pcpu->profc_probe == prof); + ASSERT(callout_active(&pcpu->profc_cyclic)); + callout_stop(&pcpu->profc_cyclic); + callout_drain(&pcpu->profc_cyclic); + kmem_free(pcpu, sizeof(profile_probe_percpu_t)); + } + kmem_free(prof->prof_pcpus, (mp_maxid + 1) * sizeof(pcpu)); + prof->prof_pcpus = NULL; +} + +/* ARGSUSED */ +static void +profile_enable(void *arg, dtrace_id_t id, void *parg) +{ + profile_probe_t *prof = parg; + + if (prof->prof_kind == PROF_TICK) { + prof->prof_expected = sbinuptime() + prof->prof_interval; + callout_reset_sbt(&prof->prof_cyclic, + prof->prof_expected, 0, profile_tick, prof, + C_DIRECT_EXEC | C_ABSOLUTE); + } else { + ASSERT(prof->prof_kind == PROF_PROFILE); + profile_enable_omni(prof); + } +} + +/* ARGSUSED */ +static void +profile_disable(void *arg, dtrace_id_t id, void *parg) +{ + profile_probe_t *prof = parg; + + if (prof->prof_kind == PROF_TICK) { + ASSERT(callout_active(&prof->prof_cyclic)); + callout_stop(&prof->prof_cyclic); + callout_drain(&prof->prof_cyclic); + } else { + ASSERT(prof->prof_kind == PROF_PROFILE); + profile_disable_omni(prof); + } +} +#endif + static void profile_load(void *dummy) { @@ -541,5 +701,4 @@ SYSUNINIT(profile_unload, SI_SUB_DTRACE_ DEV_MODULE(profile, profile_modevent, NULL); MODULE_VERSION(profile, 1); MODULE_DEPEND(profile, dtrace, 1, 1, 1); -MODULE_DEPEND(profile, cyclic, 1, 1, 1); MODULE_DEPEND(profile, opensolaris, 1, 1, 1); Modified: head/sys/kern/kern_clocksource.c ============================================================================== --- head/sys/kern/kern_clocksource.c Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/kern/kern_clocksource.c Sun Dec 7 11:21:41 2014 (r275576) @@ -54,11 +54,6 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/smp.h> -#ifdef KDTRACE_HOOKS -#include <sys/dtrace_bsd.h> -cyclic_clock_func_t cyclic_clock_func = NULL; -#endif - int cpu_can_deep_sleep = 0; /* C3 state is available. */ int cpu_disable_deep_sleep = 0; /* Timer dies in C3. */ @@ -125,9 +120,6 @@ struct pcpu_state { sbintime_t nextprof; /* Next profclock() event. */ sbintime_t nextcall; /* Next callout event. */ sbintime_t nextcallopt; /* Next optional callout event. */ -#ifdef KDTRACE_HOOKS - sbintime_t nextcyc; /* Next OpenSolaris cyclics event. */ -#endif int ipi; /* This CPU needs IPI. */ int idle; /* This CPU is in idle mode. */ }; @@ -219,13 +211,6 @@ handleevents(sbintime_t now, int fake) callout_process(now); } -#ifdef KDTRACE_HOOKS - if (fake == 0 && now >= state->nextcyc && cyclic_clock_func != NULL) { - state->nextcyc = SBT_MAX; - (*cyclic_clock_func)(frame); - } -#endif - t = getnextcpuevent(0); ET_HW_LOCK(state); if (!busy) { @@ -271,10 +256,6 @@ getnextcpuevent(int idle) if (profiling && event > state->nextprof) event = state->nextprof; } -#ifdef KDTRACE_HOOKS - if (event > state->nextcyc) - event = state->nextcyc; -#endif return (event); } @@ -595,9 +576,6 @@ cpu_initclocks_bsp(void) CPU_FOREACH(cpu) { state = DPCPU_ID_PTR(cpu, timerstate); mtx_init(&state->et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); -#ifdef KDTRACE_HOOKS - state->nextcyc = SBT_MAX; -#endif state->nextcall = SBT_MAX; state->nextcallopt = SBT_MAX; } @@ -816,41 +794,6 @@ cpu_et_frequency(struct eventtimer *et, ET_UNLOCK(); } -#ifdef KDTRACE_HOOKS -void -clocksource_cyc_set(const struct bintime *bt) -{ - sbintime_t now, t; - struct pcpu_state *state; - - /* Do not touch anything if somebody reconfiguring timers. */ - if (busy) - return; - t = bttosbt(*bt); - state = DPCPU_PTR(timerstate); - if (periodic) - now = state->now; - else - now = sbinuptime(); - - CTR5(KTR_SPARE2, "set_cyc at %d: now %d.%08x t %d.%08x", - curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff), - (int)(t >> 32), (u_int)(t & 0xffffffff)); - - ET_HW_LOCK(state); - if (t == state->nextcyc) - goto done; - state->nextcyc = t; - if (t >= state->nextevent) - goto done; - state->nextevent = t; - if (!periodic) - loadtimer(now, 0); -done: - ET_HW_UNLOCK(state); -} -#endif - void cpu_new_callout(int cpu, sbintime_t bt, sbintime_t bt_opt) { Modified: head/sys/modules/Makefile ============================================================================== --- head/sys/modules/Makefile Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/modules/Makefile Sun Dec 7 11:21:41 2014 (r275576) @@ -90,7 +90,6 @@ SUBDIR= \ cuse \ ${_cxgb} \ ${_cxgbe} \ - ${_cyclic} \ dc \ dcons \ dcons_crom \ @@ -476,9 +475,6 @@ _cardbus= cardbus _cbb= cbb _cpuctl= cpuctl _cpufreq= cpufreq -.if ${MK_CDDL} != "no" || defined(ALL_MODULES) -_cyclic= cyclic -.endif _dpms= dpms _drm= drm _drm2= drm2 @@ -686,9 +682,6 @@ _cardbus= cardbus _cbb= cbb _cfi= cfi _cpufreq= cpufreq -.if ${MK_CDDL} != "no" || defined(ALL_MODULES) -_cyclic= cyclic -.endif _drm= drm .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _dtrace= dtrace Modified: head/sys/modules/dtrace/Makefile.inc ============================================================================== --- head/sys/modules/dtrace/Makefile.inc Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/modules/dtrace/Makefile.inc Sun Dec 7 11:21:41 2014 (r275576) @@ -3,7 +3,6 @@ IGNORE_PRAGMA= 1 load : - -kldload cyclic -kldload dtrace .if ${MACHINE_CPUARCH} == "i386" -kldload sdt @@ -25,5 +24,4 @@ unload : -kldunload sdt .endif -kldunload dtrace - -kldunload cyclic kldstat Modified: head/sys/modules/dtrace/dtraceall/dtraceall.c ============================================================================== --- head/sys/modules/dtrace/dtraceall/dtraceall.c Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/modules/dtrace/dtraceall/dtraceall.c Sun Dec 7 11:21:41 2014 (r275576) @@ -63,7 +63,6 @@ DEV_MODULE(dtraceall, dtraceall_modevent MODULE_VERSION(dtraceall, 1); /* All the DTrace modules should be dependencies here: */ -MODULE_DEPEND(dtraceall, cyclic, 1, 1, 1); MODULE_DEPEND(dtraceall, opensolaris, 1, 1, 1); MODULE_DEPEND(dtraceall, dtrace, 1, 1, 1); MODULE_DEPEND(dtraceall, dtmalloc, 1, 1, 1); Modified: head/sys/sys/dtrace_bsd.h ============================================================================== --- head/sys/sys/dtrace_bsd.h Sun Dec 7 06:47:00 2014 (r275575) +++ head/sys/sys/dtrace_bsd.h Sun Dec 7 11:21:41 2014 (r275576) @@ -39,15 +39,6 @@ struct vattr; struct vnode; struct reg; -/* - * Cyclic clock function type definition used to hook the cyclic - * subsystem into the appropriate timer interrupt. - */ -typedef void (*cyclic_clock_func_t)(struct trapframe *); -extern cyclic_clock_func_t cyclic_clock_func; - -void clocksource_cyc_set(const struct bintime *t); - int dtrace_trap(struct trapframe *); /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412071121.sB7BLgnH040986>