PERFORCE change 142657 for review

John Birrell jb at FreeBSD.org
Sun Jun 1 01:35:18 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=142657

Change 142657 by jb at freebsd3 on 2008/06/01 01:34:48

	Use a callout to trigger the deadman and state clean operations (as suggested by jhb@)
	to work around the case where the cyclic timer on FreeBSD behaves differently, 
	causing a deadlock in the ipi code.
	
	Reported by: ps, jhb, peter, thompsa

Affected files ...

.. //depot/projects/dtrace/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c#8 edit
.. //depot/projects/dtrace/src/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h#5 edit

Differences ...

==== //depot/projects/dtrace/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c#8 (text) ====

@@ -111,6 +111,7 @@
 
 /* FreeBSD includes: */
 #if !defined(sun)
+#include <sys/callout.h>
 #include <sys/ctype.h>
 #include <sys/limits.h>
 #include <sys/kdb.h>
@@ -11410,9 +11411,11 @@
 	 * block pending our completion.
 	 */
 	for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next) {
+#if defined(sun)
 		cred_t *cr = enab->dten_vstate->dtvs_state->dts_cred.dcr_cred;
 
 		if (INGLOBALZONE(curproc) || getzoneid() == crgetzoneid(cr))
+#endif
 			(void) dtrace_enabling_match(enab, NULL);
 	}
 
@@ -12688,6 +12691,7 @@
 	}
 }
 
+#if defined(sun)
 static void
 dtrace_state_clean(dtrace_state_t *state)
 {
@@ -12705,9 +12709,51 @@
 
 	dtrace_sync();
 
-#if !defined(sun)
+	now = dtrace_gethrtime();
+
+	if (state != dtrace_anon.dta_state &&
+	    now - state->dts_laststatus >= dtrace_deadman_user)
+		return;
+
+	/*
+	 * We must be sure that dts_alive never appears to be less than the
+	 * value upon entry to dtrace_state_deadman(), and because we lack a
+	 * dtrace_cas64(), we cannot store to it atomically.  We thus instead
+	 * store INT64_MAX to it, followed by a memory barrier, followed by
+	 * the new value.  This assures that dts_alive never appears to be
+	 * less than its true value, regardless of the order in which the
+	 * stores to the underlying storage are issued.
+	 */
+	state->dts_alive = INT64_MAX;
+	dtrace_membar_producer();
+	state->dts_alive = now;
+}
+#else
+static void
+dtrace_state_clean(void *arg)
+{
+	dtrace_state_t *state = arg;
+	dtrace_optval_t *opt = state->dts_options;
+
+	if (state->dts_activity == DTRACE_ACTIVITY_INACTIVE)
+		return;
+
+	dtrace_dynvar_clean(&state->dts_vstate.dtvs_dynvars);
+	dtrace_speculation_clean(state);
+
+	callout_reset(&state->dts_cleaner, hz * opt[DTRACEOPT_CLEANRATE] / NANOSEC,
+	    dtrace_state_clean, state);
+}
+
+static void
+dtrace_state_deadman(void *arg)
+{
+	dtrace_state_t *state = arg;
+	hrtime_t now;
+
+	dtrace_sync();
+
 	dtrace_debug_output();
-#endif
 
 	now = dtrace_gethrtime();
 
@@ -12727,7 +12773,11 @@
 	state->dts_alive = INT64_MAX;
 	dtrace_membar_producer();
 	state->dts_alive = now;
+
+	callout_reset(&state->dts_deadman, hz * dtrace_deadman_interval / NANOSEC,
+	    dtrace_state_deadman, state);
 }
+#endif
 
 static dtrace_state_t *
 #if defined(sun)
@@ -12801,8 +12851,14 @@
 	 */
 	state->dts_buffer = kmem_zalloc(bufsize, KM_SLEEP);
 	state->dts_aggbuffer = kmem_zalloc(bufsize, KM_SLEEP);
+
+#if defined(sun)
 	state->dts_cleaner = CYCLIC_NONE;
 	state->dts_deadman = CYCLIC_NONE;
+#else
+	callout_init(&state->dts_cleaner, CALLOUT_MPSAFE);
+	callout_init(&state->dts_deadman, CALLOUT_MPSAFE);
+#endif
 	state->dts_vstate.dtvs_state = state;
 
 	for (i = 0; i < DTRACEOPT_MAX; i++)
@@ -13084,8 +13140,10 @@
 	dtrace_optval_t *opt = state->dts_options, sz, nspec;
 	dtrace_speculation_t *spec;
 	dtrace_buffer_t *buf;
+#if defined(sun)
 	cyc_handler_t hdlr;
 	cyc_time_t when;
+#endif
 	int rval = 0, i, bufsize = NCPU * sizeof (dtrace_buffer_t);
 	dtrace_icookie_t cookie;
 
@@ -13263,11 +13321,11 @@
 	if (opt[DTRACEOPT_CLEANRATE] > dtrace_cleanrate_max)
 		opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_max;
 
+	state->dts_alive = state->dts_laststatus = dtrace_gethrtime();
+#if defined(sun)
 	hdlr.cyh_func = (cyc_func_t)dtrace_state_clean;
 	hdlr.cyh_arg = state;
-#if defined(sun)
 	hdlr.cyh_level = CY_LOW_LEVEL;
-#endif
 
 	when.cyt_when = 0;
 	when.cyt_interval = opt[DTRACEOPT_CLEANRATE];
@@ -13276,15 +13334,18 @@
 
 	hdlr.cyh_func = (cyc_func_t)dtrace_state_deadman;
 	hdlr.cyh_arg = state;
-#if defined(sun)
 	hdlr.cyh_level = CY_LOW_LEVEL;
-#endif
 
 	when.cyt_when = 0;
 	when.cyt_interval = dtrace_deadman_interval;
 
-	state->dts_alive = state->dts_laststatus = dtrace_gethrtime();
 	state->dts_deadman = cyclic_add(&hdlr, &when);
+#else
+	callout_reset(&state->dts_cleaner, hz * opt[DTRACEOPT_CLEANRATE] / NANOSEC,
+	    dtrace_state_clean, state);
+	callout_reset(&state->dts_deadman, hz * dtrace_deadman_interval / NANOSEC,
+	    dtrace_state_deadman, state);
+#endif
 
 	state->dts_activity = DTRACE_ACTIVITY_WARMUP;
 
@@ -13545,11 +13606,16 @@
 	for (i = 0; i < nspec; i++)
 		dtrace_buffer_free(spec[i].dtsp_buffer);
 
+#if defined(sun)
 	if (state->dts_cleaner != CYCLIC_NONE)
 		cyclic_remove(state->dts_cleaner);
 
 	if (state->dts_deadman != CYCLIC_NONE)
 		cyclic_remove(state->dts_deadman);
+#else
+	callout_stop(&state->dts_cleaner);
+	callout_stop(&state->dts_deadman);
+#endif
 
 	dtrace_dstate_fini(&vstate->dtvs_dynvars);
 	dtrace_vstate_fini(vstate);

==== //depot/projects/dtrace/src/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h#5 (text) ====

@@ -1137,8 +1137,13 @@
 	uint32_t dts_dblerrors;			/* errors in ERROR probes */
 	uint32_t dts_reserve;			/* space reserved for END */
 	hrtime_t dts_laststatus;		/* time of last status */
+#if defined(sun)
 	cyclic_id_t dts_cleaner;		/* cleaning cyclic */
 	cyclic_id_t dts_deadman;		/* deadman cyclic */
+#else
+	struct callout dts_cleaner;		/* Cleaning callout. */
+	struct callout dts_deadman;		/* Deadman callout. */
+#endif
 	hrtime_t dts_alive;			/* time last alive */
 	char dts_speculates;			/* boolean: has speculations */
 	char dts_destructive;			/* boolean: has dest. actions */


More information about the p4-projects mailing list