dtrace_unload.c revision 262052
140617Smsmith/*
240617Smsmith * CDDL HEADER START
340617Smsmith *
440617Smsmith * The contents of this file are subject to the terms of the
540617Smsmith * Common Development and Distribution License (the "License").
640617Smsmith * You may not use this file except in compliance with the License.
740617Smsmith *
840617Smsmith * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940617Smsmith * or http://www.opensolaris.org/os/licensing.
1040617Smsmith * See the License for the specific language governing permissions
1140617Smsmith * and limitations under the License.
1240617Smsmith *
1340617Smsmith * When distributing Covered Code, include this CDDL HEADER in each
1440617Smsmith * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540617Smsmith * If applicable, add the following below this CDDL HEADER, with the
1640617Smsmith * fields enclosed by brackets "[]" replaced with your own identifying
1740617Smsmith * information: Portions Copyright [yyyy] [name of copyright owner]
1840617Smsmith *
1940617Smsmith * CDDL HEADER END
2040617Smsmith *
2140617Smsmith * $FreeBSD: stable/9/sys/cddl/dev/dtrace/dtrace_unload.c 262052 2014-02-17 13:29:48Z avg $
2240617Smsmith *
2340617Smsmith */
2440617Smsmith
2540617Smsmithstatic int
2640617Smsmithdtrace_unload()
27119482Sobrien{
28119482Sobrien	dtrace_state_t *state;
29119482Sobrien	int error = 0;
3040617Smsmith
3140617Smsmith#if __FreeBSD_version < 800039
3240617Smsmith	/*
3340617Smsmith	 * Check if there is still an event handler callback
3440617Smsmith	 * registered.
3540617Smsmith	 */
3640617Smsmith	if (eh_tag != 0) {
3740617Smsmith		/* De-register the device cloning event handler. */
3840617Smsmith		EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
39162814Sru		eh_tag = 0;
4040617Smsmith
4140617Smsmith		/* Stop device cloning. */
4240617Smsmith		clone_cleanup(&dtrace_clones);
4340617Smsmith	}
4440617Smsmith#else
4540617Smsmith	destroy_dev(dtrace_dev);
4640617Smsmith	destroy_dev(helper_dev);
4740617Smsmith#endif
4840617Smsmith
4940617Smsmith	mutex_enter(&dtrace_provider_lock);
5040617Smsmith	mutex_enter(&dtrace_lock);
5140617Smsmith	mutex_enter(&cpu_lock);
5264187Sjhb
5340617Smsmith	ASSERT(dtrace_opens == 0);
5440617Smsmith
5540617Smsmith	if (dtrace_helpers > 0) {
5640617Smsmith		mutex_exit(&cpu_lock);
5740617Smsmith		mutex_exit(&dtrace_lock);
5840617Smsmith		mutex_exit(&dtrace_provider_lock);
5940617Smsmith		return (EBUSY);
6040617Smsmith	}
6140617Smsmith
6240617Smsmith	if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) {
6340617Smsmith		mutex_exit(&cpu_lock);
6440617Smsmith		mutex_exit(&dtrace_lock);
6540617Smsmith		mutex_exit(&dtrace_provider_lock);
6640617Smsmith		return (EBUSY);
6740617Smsmith	}
6840617Smsmith
6940617Smsmith	dtrace_provider = NULL;
7040617Smsmith	EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag);
7140617Smsmith	EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag);
7240617Smsmith
7340617Smsmith	if ((state = dtrace_anon_grab()) != NULL) {
7440617Smsmith		/*
7540617Smsmith		 * If there were ECBs on this state, the provider should
7640617Smsmith		 * have not been allowed to detach; assert that there is
7740617Smsmith		 * none.
7840617Smsmith		 */
7940617Smsmith		ASSERT(state->dts_necbs == 0);
8040617Smsmith		dtrace_state_destroy(state);
8140617Smsmith	}
8240617Smsmith
8340617Smsmith	bzero(&dtrace_anon, sizeof (dtrace_anon_t));
8440617Smsmith
8540617Smsmith	mutex_exit(&cpu_lock);
8640617Smsmith
8740617Smsmith	if (dtrace_helptrace_enabled) {
8840617Smsmith		kmem_free(dtrace_helptrace_buffer, 0);
8940617Smsmith		dtrace_helptrace_buffer = NULL;
9040617Smsmith	}
9140617Smsmith
9240617Smsmith	if (dtrace_probes != NULL) {
9340617Smsmith		kmem_free(dtrace_probes, 0);
9440617Smsmith		dtrace_probes = NULL;
9540617Smsmith		dtrace_nprobes = 0;
9640617Smsmith	}
9740617Smsmith
9840617Smsmith	dtrace_hash_destroy(dtrace_bymod);
9940617Smsmith	dtrace_hash_destroy(dtrace_byfunc);
10040617Smsmith	dtrace_hash_destroy(dtrace_byname);
10140617Smsmith	dtrace_bymod = NULL;
10240617Smsmith	dtrace_byfunc = NULL;
10340617Smsmith	dtrace_byname = NULL;
10440617Smsmith
10540617Smsmith	kmem_cache_destroy(dtrace_state_cache);
10640617Smsmith
10740617Smsmith	delete_unrhdr(dtrace_arena);
10840617Smsmith
10940617Smsmith	if (dtrace_toxrange != NULL) {
11040617Smsmith		kmem_free(dtrace_toxrange, 0);
11140617Smsmith		dtrace_toxrange = NULL;
11240617Smsmith		dtrace_toxranges = 0;
11340617Smsmith		dtrace_toxranges_max = 0;
11440617Smsmith	}
11540617Smsmith
116136779Ssimokawa	ASSERT(dtrace_vtime_references == 0);
117136779Ssimokawa	ASSERT(dtrace_opens == 0);
118136779Ssimokawa	ASSERT(dtrace_retained == NULL);
119136779Ssimokawa
12040617Smsmith	mutex_exit(&dtrace_lock);
12140617Smsmith	mutex_exit(&dtrace_provider_lock);
12240617Smsmith
12340617Smsmith	mutex_destroy(&dtrace_meta_lock);
12464187Sjhb	mutex_destroy(&dtrace_provider_lock);
12540617Smsmith	mutex_destroy(&dtrace_lock);
12640617Smsmith#ifdef DEBUG
12740617Smsmith	mutex_destroy(&dtrace_errlock);
12840617Smsmith#endif
12940617Smsmith
13040617Smsmith	/* Reset our hook for exceptions. */
13140617Smsmith	dtrace_invop_uninit();
13240617Smsmith
13340617Smsmith	/*
13440617Smsmith	 * Reset our hook for thread switches, but ensure that vtime isn't
13540617Smsmith	 * active first.
13640617Smsmith	 */
13740617Smsmith	dtrace_vtime_active = 0;
13840617Smsmith	dtrace_vtime_switch_func = NULL;
13940617Smsmith
14040617Smsmith	/* Unhook from the trap handler. */
14140617Smsmith	dtrace_trap_func = NULL;
14240617Smsmith
14340617Smsmith	return (error);
14440617Smsmith}
14540617Smsmith