dtrace_unload.c revision 273110
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: stable/10/sys/cddl/dev/dtrace/dtrace_unload.c 273110 2014-10-14 23:16:52Z pfg $
22 *
23 */
24
25static int
26dtrace_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