xref: /freebsd/sys/cddl/dev/dtrace/dtrace_unload.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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(void)
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_probes != NULL) {
73 		kmem_free(dtrace_probes, 0);
74 		dtrace_probes = NULL;
75 		dtrace_nprobes = 0;
76 	}
77 
78 	dtrace_hash_destroy(dtrace_bymod);
79 	dtrace_hash_destroy(dtrace_byfunc);
80 	dtrace_hash_destroy(dtrace_byname);
81 	dtrace_bymod = NULL;
82 	dtrace_byfunc = NULL;
83 	dtrace_byname = NULL;
84 
85 	kmem_cache_destroy(dtrace_state_cache);
86 
87 	delete_unrhdr(dtrace_arena);
88 
89 	if (dtrace_toxrange != NULL) {
90 		kmem_free(dtrace_toxrange, 0);
91 		dtrace_toxrange = NULL;
92 		dtrace_toxranges = 0;
93 		dtrace_toxranges_max = 0;
94 	}
95 
96 	ASSERT(dtrace_vtime_references == 0);
97 	ASSERT(dtrace_opens == 0);
98 	ASSERT(dtrace_retained == NULL);
99 
100 	mutex_exit(&dtrace_lock);
101 	mutex_exit(&dtrace_provider_lock);
102 
103 	mutex_destroy(&dtrace_meta_lock);
104 	mutex_destroy(&dtrace_provider_lock);
105 	mutex_destroy(&dtrace_lock);
106 #ifdef DEBUG
107 	mutex_destroy(&dtrace_errlock);
108 #endif
109 
110 	taskq_destroy(dtrace_taskq);
111 
112 	/* Reset our hook for exceptions. */
113 	dtrace_invop_uninit();
114 
115 	/*
116 	 * Reset our hook for thread switches, but ensure that vtime isn't
117 	 * active first.
118 	 */
119 	dtrace_vtime_active = 0;
120 	dtrace_vtime_switch_func = NULL;
121 
122 	/* Unhook from the trap handler. */
123 	dtrace_trap_func = NULL;
124 
125 	return (error);
126 }
127