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