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 ...

Andriy Gapon avg at FreeBSD.org
Sun Dec 7 11:21:44 UTC 2014


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 *);
 
 /*


More information about the svn-src-head mailing list