1179237Sjb/*
2179237Sjb * CDDL HEADER START
3179237Sjb *
4179237Sjb * The contents of this file are subject to the terms of the
5179237Sjb * Common Development and Distribution License (the "License").
6179237Sjb * You may not use this file except in compliance with the License.
7179237Sjb *
8179237Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9179237Sjb * or http://www.opensolaris.org/os/licensing.
10179237Sjb * See the License for the specific language governing permissions
11179237Sjb * and limitations under the License.
12179237Sjb *
13179237Sjb * When distributing Covered Code, include this CDDL HEADER in each
14179237Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15179237Sjb * If applicable, add the following below this CDDL HEADER, with the
16179237Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17179237Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18179237Sjb *
19179237Sjb * CDDL HEADER END
20179237Sjb *
21179237Sjb * $FreeBSD$
22179237Sjb *
23179237Sjb */
24179237Sjb
25179237Sjbstatic int
26179237Sjbdtrace_unload()
27179237Sjb{
28179237Sjb	dtrace_state_t *state;
29179237Sjb	int error = 0;
30179237Sjb
31184698Srodrigc	destroy_dev(dtrace_dev);
32211611Srpaulo	destroy_dev(helper_dev);
33179237Sjb
34179237Sjb	mutex_enter(&dtrace_provider_lock);
35179237Sjb	mutex_enter(&dtrace_lock);
36179237Sjb	mutex_enter(&cpu_lock);
37179237Sjb
38179237Sjb	ASSERT(dtrace_opens == 0);
39179237Sjb
40179237Sjb	if (dtrace_helpers > 0) {
41179237Sjb		mutex_exit(&cpu_lock);
42179237Sjb		mutex_exit(&dtrace_lock);
43179237Sjb		mutex_exit(&dtrace_provider_lock);
44179237Sjb		return (EBUSY);
45179237Sjb	}
46179237Sjb
47179237Sjb	if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) {
48179237Sjb		mutex_exit(&cpu_lock);
49179237Sjb		mutex_exit(&dtrace_lock);
50179237Sjb		mutex_exit(&dtrace_provider_lock);
51179237Sjb		return (EBUSY);
52179237Sjb	}
53179237Sjb
54179237Sjb	dtrace_provider = NULL;
55254309Smarkj	EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag);
56254813Smarkj	EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag);
57179237Sjb
58179237Sjb	if ((state = dtrace_anon_grab()) != NULL) {
59179237Sjb		/*
60179237Sjb		 * If there were ECBs on this state, the provider should
61179237Sjb		 * have not been allowed to detach; assert that there is
62179237Sjb		 * none.
63179237Sjb		 */
64179237Sjb		ASSERT(state->dts_necbs == 0);
65179237Sjb		dtrace_state_destroy(state);
66179237Sjb	}
67179237Sjb
68179237Sjb	bzero(&dtrace_anon, sizeof (dtrace_anon_t));
69179237Sjb
70179237Sjb	mutex_exit(&cpu_lock);
71179237Sjb
72179237Sjb	if (dtrace_probes != NULL) {
73179237Sjb		kmem_free(dtrace_probes, 0);
74179237Sjb		dtrace_probes = NULL;
75179237Sjb		dtrace_nprobes = 0;
76179237Sjb	}
77179237Sjb
78179237Sjb	dtrace_hash_destroy(dtrace_bymod);
79179237Sjb	dtrace_hash_destroy(dtrace_byfunc);
80179237Sjb	dtrace_hash_destroy(dtrace_byname);
81179237Sjb	dtrace_bymod = NULL;
82179237Sjb	dtrace_byfunc = NULL;
83179237Sjb	dtrace_byname = NULL;
84179237Sjb
85179237Sjb	kmem_cache_destroy(dtrace_state_cache);
86179237Sjb
87260131Smarkj	delete_unrhdr(dtrace_arena);
88179237Sjb
89179237Sjb	if (dtrace_toxrange != NULL) {
90179237Sjb		kmem_free(dtrace_toxrange, 0);
91179237Sjb		dtrace_toxrange = NULL;
92179237Sjb		dtrace_toxranges = 0;
93179237Sjb		dtrace_toxranges_max = 0;
94179237Sjb	}
95179237Sjb
96179237Sjb	ASSERT(dtrace_vtime_references == 0);
97179237Sjb	ASSERT(dtrace_opens == 0);
98179237Sjb	ASSERT(dtrace_retained == NULL);
99179237Sjb
100179237Sjb	mutex_exit(&dtrace_lock);
101179237Sjb	mutex_exit(&dtrace_provider_lock);
102179237Sjb
103179237Sjb	mutex_destroy(&dtrace_meta_lock);
104179237Sjb	mutex_destroy(&dtrace_provider_lock);
105179237Sjb	mutex_destroy(&dtrace_lock);
106253996Savg#ifdef DEBUG
107179237Sjb	mutex_destroy(&dtrace_errlock);
108253996Savg#endif
109179237Sjb
110256148Smarkj	taskq_destroy(dtrace_taskq);
111256148Smarkj
112179237Sjb	/* Reset our hook for exceptions. */
113179237Sjb	dtrace_invop_uninit();
114179237Sjb
115179237Sjb	/*
116179237Sjb	 * Reset our hook for thread switches, but ensure that vtime isn't
117179237Sjb	 * active first.
118179237Sjb	 */
119179237Sjb	dtrace_vtime_active = 0;
120179237Sjb	dtrace_vtime_switch_func = NULL;
121179237Sjb
122179237Sjb	/* Unhook from the trap handler. */
123179237Sjb	dtrace_trap_func = NULL;
124179237Sjb
125179237Sjb	return (error);
126179237Sjb}
127