diff options
Diffstat (limited to 'sys/cddl/dev/dtrace/dtrace_unload.c')
-rw-r--r-- | sys/cddl/dev/dtrace/dtrace_unload.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/sys/cddl/dev/dtrace/dtrace_unload.c b/sys/cddl/dev/dtrace/dtrace_unload.c new file mode 100644 index 0000000..eb14543 --- /dev/null +++ b/sys/cddl/dev/dtrace/dtrace_unload.c @@ -0,0 +1,138 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + * + */ + +static int +dtrace_unload() +{ + dtrace_state_t *state; + int error = 0; + + /* + * Check if there is still an event handler callback + * registered. + */ + if (eh_tag != 0) { + /* De-register the device cloning event handler. */ + EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); + eh_tag = 0; + + /* Stop device cloning. */ + clone_cleanup(&dtrace_clones); + } + + mutex_enter(&dtrace_provider_lock); + mutex_enter(&dtrace_lock); + mutex_enter(&cpu_lock); + + ASSERT(dtrace_opens == 0); + + if (dtrace_helpers > 0) { + mutex_exit(&cpu_lock); + mutex_exit(&dtrace_lock); + mutex_exit(&dtrace_provider_lock); + return (EBUSY); + } + + if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) { + mutex_exit(&cpu_lock); + mutex_exit(&dtrace_lock); + mutex_exit(&dtrace_provider_lock); + return (EBUSY); + } + + dtrace_provider = NULL; + + if ((state = dtrace_anon_grab()) != NULL) { + /* + * If there were ECBs on this state, the provider should + * have not been allowed to detach; assert that there is + * none. + */ + ASSERT(state->dts_necbs == 0); + dtrace_state_destroy(state); + } + + bzero(&dtrace_anon, sizeof (dtrace_anon_t)); + + mutex_exit(&cpu_lock); + + if (dtrace_helptrace_enabled) { + kmem_free(dtrace_helptrace_buffer, 0); + dtrace_helptrace_buffer = NULL; + } + + if (dtrace_probes != NULL) { + kmem_free(dtrace_probes, 0); + dtrace_probes = NULL; + dtrace_nprobes = 0; + } + + dtrace_hash_destroy(dtrace_bymod); + dtrace_hash_destroy(dtrace_byfunc); + dtrace_hash_destroy(dtrace_byname); + dtrace_bymod = NULL; + dtrace_byfunc = NULL; + dtrace_byname = NULL; + + kmem_cache_destroy(dtrace_state_cache); + + delete_unrhdr(dtrace_arena); + + if (dtrace_toxrange != NULL) { + kmem_free(dtrace_toxrange, 0); + dtrace_toxrange = NULL; + dtrace_toxranges = 0; + dtrace_toxranges_max = 0; + } + + ASSERT(dtrace_vtime_references == 0); + ASSERT(dtrace_opens == 0); + ASSERT(dtrace_retained == NULL); + + mutex_exit(&dtrace_lock); + mutex_exit(&dtrace_provider_lock); + + mutex_destroy(&dtrace_meta_lock); + mutex_destroy(&dtrace_provider_lock); + mutex_destroy(&dtrace_lock); + mutex_destroy(&dtrace_errlock); + + /* XXX Hack */ + mutex_destroy(&mod_lock); + + /* Reset our hook for exceptions. */ + dtrace_invop_uninit(); + + /* + * Reset our hook for thread switches, but ensure that vtime isn't + * active first. + */ + dtrace_vtime_active = 0; + dtrace_vtime_switch_func = NULL; + + /* Unhook from the trap handler. */ + dtrace_trap_func = NULL; + + return (error); +} |