xref: /freebsd/sys/cddl/dev/dtrace/dtrace_unload.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
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  * $FreeBSD$
22  *
23  */
24 
25 static int
26 dtrace_unload()
27 {
28 	dtrace_state_t *state;
29 	int error = 0;
30 
31 #if __FreeBSD_version < 800039
32 	/*
33 	 * Check if there is still an event handler callback
34 	 * registered.
35 	 */
36 	if (eh_tag != 0) {
37 		/* De-register the device cloning event handler. */
38 		EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
39 		eh_tag = 0;
40 
41 		/* Stop device cloning. */
42 		clone_cleanup(&dtrace_clones);
43 	}
44 #else
45 	destroy_dev(dtrace_dev);
46 	destroy_dev(helper_dev);
47 #endif
48 
49 	mutex_enter(&dtrace_provider_lock);
50 	mutex_enter(&dtrace_lock);
51 	mutex_enter(&cpu_lock);
52 
53 	ASSERT(dtrace_opens == 0);
54 
55 	if (dtrace_helpers > 0) {
56 		mutex_exit(&cpu_lock);
57 		mutex_exit(&dtrace_lock);
58 		mutex_exit(&dtrace_provider_lock);
59 		return (EBUSY);
60 	}
61 
62 	if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) {
63 		mutex_exit(&cpu_lock);
64 		mutex_exit(&dtrace_lock);
65 		mutex_exit(&dtrace_provider_lock);
66 		return (EBUSY);
67 	}
68 
69 	dtrace_provider = NULL;
70 	EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag);
71 	EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag);
72 
73 	if ((state = dtrace_anon_grab()) != NULL) {
74 		/*
75 		 * If there were ECBs on this state, the provider should
76 		 * have not been allowed to detach; assert that there is
77 		 * none.
78 		 */
79 		ASSERT(state->dts_necbs == 0);
80 		dtrace_state_destroy(state);
81 	}
82 
83 	bzero(&dtrace_anon, sizeof (dtrace_anon_t));
84 
85 	mutex_exit(&cpu_lock);
86 
87 	if (dtrace_helptrace_enabled) {
88 		kmem_free(dtrace_helptrace_buffer, 0);
89 		dtrace_helptrace_buffer = NULL;
90 	}
91 
92 	if (dtrace_probes != NULL) {
93 		kmem_free(dtrace_probes, 0);
94 		dtrace_probes = NULL;
95 		dtrace_nprobes = 0;
96 	}
97 
98 	dtrace_hash_destroy(dtrace_bymod);
99 	dtrace_hash_destroy(dtrace_byfunc);
100 	dtrace_hash_destroy(dtrace_byname);
101 	dtrace_bymod = NULL;
102 	dtrace_byfunc = NULL;
103 	dtrace_byname = NULL;
104 
105 	kmem_cache_destroy(dtrace_state_cache);
106 
107 	delete_unrhdr(dtrace_arena);
108 
109 	if (dtrace_toxrange != NULL) {
110 		kmem_free(dtrace_toxrange, 0);
111 		dtrace_toxrange = NULL;
112 		dtrace_toxranges = 0;
113 		dtrace_toxranges_max = 0;
114 	}
115 
116 	ASSERT(dtrace_vtime_references == 0);
117 	ASSERT(dtrace_opens == 0);
118 	ASSERT(dtrace_retained == NULL);
119 
120 	mutex_exit(&dtrace_lock);
121 	mutex_exit(&dtrace_provider_lock);
122 
123 	mutex_destroy(&dtrace_meta_lock);
124 	mutex_destroy(&dtrace_provider_lock);
125 	mutex_destroy(&dtrace_lock);
126 #ifdef DEBUG
127 	mutex_destroy(&dtrace_errlock);
128 #endif
129 
130 	taskq_destroy(dtrace_taskq);
131 
132 	/* Reset our hook for exceptions. */
133 	dtrace_invop_uninit();
134 
135 	/*
136 	 * Reset our hook for thread switches, but ensure that vtime isn't
137 	 * active first.
138 	 */
139 	dtrace_vtime_active = 0;
140 	dtrace_vtime_switch_func = NULL;
141 
142 	/* Unhook from the trap handler. */
143 	dtrace_trap_func = NULL;
144 
145 	return (error);
146 }
147