xref: /freebsd/sys/cddl/dev/dtrace/dtrace_unload.c (revision 069ac184)
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
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