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