Module Name: src Committed By: yamt Date: Wed Oct 19 11:02:09 UTC 2011
Modified Files: src/external/cddl/osnet/dist/uts/common/dtrace: dtrace.c src/external/cddl/osnet/dist/uts/common/sys: dtrace_impl.h Log Message: because our xcall stuff can't be used in softint, use kernel threads for cleaner/deadman low-level cyclic replacement. PR/44905 To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 \ src/external/cddl/osnet/dist/uts/common/dtrace/dtrace.c cvs rdiff -u -r1.4 -r1.5 \ src/external/cddl/osnet/dist/uts/common/sys/dtrace_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dist/uts/common/dtrace/dtrace.c diff -u src/external/cddl/osnet/dist/uts/common/dtrace/dtrace.c:1.18 src/external/cddl/osnet/dist/uts/common/dtrace/dtrace.c:1.19 --- src/external/cddl/osnet/dist/uts/common/dtrace/dtrace.c:1.18 Wed Sep 7 21:32:07 2011 +++ src/external/cddl/osnet/dist/uts/common/dtrace/dtrace.c Wed Oct 19 11:02:08 2011 @@ -118,7 +118,6 @@ /* FreeBSD includes: */ #if !defined(sun) -#include <sys/callout.h> #include <sys/ctype.h> #include <sys/limits.h> //#include <sys/kdb.h> @@ -250,10 +249,6 @@ int dtrace_in_probe; /* non-zero if exe #if defined(__i386__) || defined(__amd64__) uintptr_t dtrace_in_probe_addr; /* Address of invop when already in probe */ #endif - -void *dtrace_deadman_wchan; -int dtrace_deadman_alive; /* deadman thread keep alive */ -lwp_t *dtrace_deadman_proc; #endif /* @@ -12836,7 +12831,6 @@ dtrace_vstate_fini(dtrace_vstate_t *vsta } } -#if defined(sun) static void dtrace_state_clean(dtrace_state_t *state) { @@ -12873,72 +12867,11 @@ dtrace_state_deadman(dtrace_state_t *sta 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, ((dtrace_optval_t)hz * opt[DTRACEOPT_CLEANRATE]) / NANOSEC, - dtrace_state_clean, state); -} -static void -dtrace_state_deadman(void *arg) -{ - dtrace_state_t *state = arg; - hrtime_t now; - int res; - kmutex_t dtrace_deadman_mutex; - - mutex_init(&dtrace_deadman_mutex, NULL, MUTEX_DEFAULT, NULL); - - while (dtrace_deadman_alive) { - mutex_enter(&dtrace_deadman_mutex); - res = mtsleep(&dtrace_deadman_wchan, PRI_BIO, "dtrace_deadman", - ((dtrace_optval_t)hz * dtrace_deadman_interval) / NANOSEC, - &dtrace_deadman_mutex); - mutex_exit(&dtrace_deadman_mutex); - - if (!dtrace_deadman_alive) { - break; - } - - dtrace_sync(); - - dtrace_debug_output(); - - now = dtrace_gethrtime(); - - if (state != dtrace_anon.dta_state && - now - state->dts_laststatus >= dtrace_deadman_user) - continue; - - /* - * 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; - } - - mutex_destroy(&dtrace_deadman_mutex); - - kthread_exit(0); -} +#if !defined(sun) +struct dtrace_state_worker *dtrace_state_worker_add(void (*)(dtrace_state_t *), + dtrace_state_t *, hrtime_t); +void dtrace_state_worker_remove(struct dtrace_state_worker *); #endif static dtrace_state_t * @@ -13015,7 +12948,8 @@ dtrace_state_create(dev_t dev, cred_t *c state->dts_cleaner = CYCLIC_NONE; state->dts_deadman = CYCLIC_NONE; #else - callout_init(&state->dts_cleaner, CALLOUT_MPSAFE); + state->dts_cleaner = NULL; + state->dts_deadman = NULL; #endif state->dts_vstate.dtvs_state = state; @@ -13503,19 +13437,10 @@ dtrace_state_go(dtrace_state_t *state, p state->dts_deadman = cyclic_add(&hdlr, &when); #else - callout_reset(&state->dts_cleaner, - ((dtrace_optval_t)hz * opt[DTRACEOPT_CLEANRATE]) / NANOSEC, - dtrace_state_clean, state); - - dtrace_deadman_wchan = &dtrace_deadman_wchan; - dtrace_deadman_alive = 1; - - if ((rval = kthread_create(PRI_BIO, KTHREAD_MPSAFE, - NULL, dtrace_state_deadman, state, - &dtrace_deadman_proc, "dtrace_deadman")) != 0) { - printf("failed to create deadman thread, error=%d\n", rval); - goto out; - } + state->dts_cleaner = dtrace_state_worker_add( + dtrace_state_clean, state, opt[DTRACEOPT_CLEANRATE]); + state->dts_deadman = dtrace_state_worker_add( + dtrace_state_deadman, state, dtrace_deadman_interval); #endif state->dts_activity = DTRACE_ACTIVITY_WARMUP; @@ -13789,13 +13714,11 @@ dtrace_state_destroy(dtrace_state_t *sta if (state->dts_deadman != CYCLIC_NONE) cyclic_remove(state->dts_deadman); #else - callout_stop(&state->dts_cleaner); + if (state->dts_cleaner != NULL) + dtrace_state_worker_remove(state->dts_cleaner); - if (dtrace_deadman_alive) { - /* tell the deadman thread to exit */ - dtrace_deadman_alive = 0; - wakeup(dtrace_deadman_wchan); - } + if (state->dts_deadman != NULL) + dtrace_state_worker_remove(state->dts_deadman); #endif dtrace_dstate_fini(&vstate->dtvs_dynvars); @@ -16691,3 +16614,74 @@ MODULE_DEPEND(dtrace, cyclic, 1, 1, 1); MODULE_DEPEND(dtrace, opensolaris, 1, 1, 1); #endif #endif + +#if !defined(sun) +#undef mutex_init + +struct dtrace_state_worker { + kmutex_t lock; + kcondvar_t cv; + void (*fn)(dtrace_state_t *); + dtrace_state_t *state; + int interval; + lwp_t *lwp; + bool exiting; +}; + +static void +dtrace_state_worker_thread(void *vp) +{ + struct dtrace_state_worker *w = vp; + + mutex_enter(&w->lock); + while (!w->exiting) { + int error; + + error = cv_timedwait(&w->cv, &w->lock, w->interval); + if (error == EWOULDBLOCK) { + mutex_exit(&w->lock); + w->fn(w->state); + mutex_enter(&w->lock); + } + } + mutex_exit(&w->lock); + kthread_exit(0); +} + +struct dtrace_state_worker * +dtrace_state_worker_add(void (*fn)(dtrace_state_t *), dtrace_state_t *state, + hrtime_t interval) +{ + struct dtrace_state_worker *w; + int error; + + w = kmem_alloc(sizeof(*w), KM_SLEEP); + mutex_init(&w->lock, MUTEX_DEFAULT, IPL_NONE); + cv_init(&w->cv, "dtrace"); + w->interval = ((uintmax_t)hz * interval) / NANOSEC, + w->fn = fn; + w->state = state; + w->exiting = false; + error = kthread_create(PRI_NONE, KTHREAD_MPSAFE|KTHREAD_MUSTJOIN, NULL, + dtrace_state_worker_thread, w, &w->lwp, "dtrace-state-worker"); + KASSERT(error == 0); /* XXX */ + return w; +} + +void +dtrace_state_worker_remove(struct dtrace_state_worker *w) +{ + int error; + + KASSERT(!w->exiting); + mutex_enter(&w->lock); + w->exiting = true; + cv_signal(&w->cv); + mutex_exit(&w->lock); + error = kthread_join(w->lwp); + KASSERT(error == 0); + cv_destroy(&w->cv); + mutex_destroy(&w->lock); + kmem_free(w, sizeof(*w)); +} +#endif Index: src/external/cddl/osnet/dist/uts/common/sys/dtrace_impl.h diff -u src/external/cddl/osnet/dist/uts/common/sys/dtrace_impl.h:1.4 src/external/cddl/osnet/dist/uts/common/sys/dtrace_impl.h:1.5 --- src/external/cddl/osnet/dist/uts/common/sys/dtrace_impl.h:1.4 Sat Mar 13 22:31:15 2010 +++ src/external/cddl/osnet/dist/uts/common/sys/dtrace_impl.h Wed Oct 19 11:02:09 2011 @@ -1135,8 +1135,8 @@ struct dtrace_state { 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. */ + struct dtrace_state_worker *dts_cleaner;/* cleaning cyclic */ + struct dtrace_state_worker *dts_deadman;/* deadman cyclic */ #endif hrtime_t dts_alive; /* time last alive */ char dts_speculates; /* boolean: has speculations */