1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 */
22
23 static int
dtrace_unload(void)24 dtrace_unload(void)
25 {
26 dtrace_state_t *state;
27 int error = 0;
28
29 destroy_dev(dtrace_dev);
30 destroy_dev(helper_dev);
31
32 mutex_enter(&dtrace_provider_lock);
33 mutex_enter(&dtrace_lock);
34 mutex_enter(&cpu_lock);
35
36 ASSERT(dtrace_opens == 0);
37
38 if (dtrace_helpers > 0) {
39 mutex_exit(&cpu_lock);
40 mutex_exit(&dtrace_lock);
41 mutex_exit(&dtrace_provider_lock);
42 return (EBUSY);
43 }
44
45 if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) {
46 mutex_exit(&cpu_lock);
47 mutex_exit(&dtrace_lock);
48 mutex_exit(&dtrace_provider_lock);
49 return (EBUSY);
50 }
51
52 dtrace_provider = NULL;
53 EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag);
54 EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag);
55
56 if ((state = dtrace_anon_grab()) != NULL) {
57 /*
58 * If there were ECBs on this state, the provider should
59 * have not been allowed to detach; assert that there is
60 * none.
61 */
62 ASSERT(state->dts_necbs == 0);
63 dtrace_state_destroy(state);
64 }
65
66 bzero(&dtrace_anon, sizeof (dtrace_anon_t));
67
68 mutex_exit(&cpu_lock);
69
70 if (dtrace_probes != NULL) {
71 kmem_free(dtrace_probes, 0);
72 dtrace_probes = NULL;
73 dtrace_nprobes = 0;
74 }
75
76 dtrace_hash_destroy(dtrace_bymod);
77 dtrace_hash_destroy(dtrace_byfunc);
78 dtrace_hash_destroy(dtrace_byname);
79 dtrace_bymod = NULL;
80 dtrace_byfunc = NULL;
81 dtrace_byname = NULL;
82
83 kmem_cache_destroy(dtrace_state_cache);
84
85 delete_unrhdr(dtrace_arena);
86
87 if (dtrace_toxrange != NULL) {
88 kmem_free(dtrace_toxrange, 0);
89 dtrace_toxrange = NULL;
90 dtrace_toxranges = 0;
91 dtrace_toxranges_max = 0;
92 }
93
94 ASSERT(dtrace_vtime_references == 0);
95 ASSERT(dtrace_opens == 0);
96 ASSERT(dtrace_retained == NULL);
97
98 mutex_exit(&dtrace_lock);
99 mutex_exit(&dtrace_provider_lock);
100
101 mutex_destroy(&dtrace_meta_lock);
102 mutex_destroy(&dtrace_provider_lock);
103 mutex_destroy(&dtrace_lock);
104 #ifdef DEBUG
105 mutex_destroy(&dtrace_errlock);
106 #endif
107
108 taskq_destroy(dtrace_taskq);
109
110 /* Reset our hook for exceptions. */
111 dtrace_invop_uninit();
112
113 /*
114 * Reset our hook for thread switches, but ensure that vtime isn't
115 * active first.
116 */
117 dtrace_vtime_active = 0;
118 dtrace_vtime_switch_func = NULL;
119
120 /* Unhook from the trap handler. */
121 dtrace_trap_func = NULL;
122
123 return (error);
124 }
125