1 /*	$NetBSD: dtrace_unload.c,v 1.4 2010/04/23 16:44:10 ahoka Exp $	*/
2 
3 /*
4  * CDDL HEADER START
5  *
6  * The contents of this file are subject to the terms of the
7  * Common Development and Distribution License (the "License").
8  * You may not use this file except in compliance with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * $FreeBSD: src/sys/cddl/dev/dtrace/dtrace_unload.c,v 1.2.2.1 2009/08/03 08:13:06 kensmith Exp $
24  *
25  */
26 
27 extern int dtrace_probes_size;
28 extern int dtrace_helptrace_size;
29 
30 static int
31 dtrace_unload()
32 {
33 	dtrace_state_t *state;
34 	int error = 0;
35 
36 	mutex_enter(&dtrace_provider_lock);
37 	mutex_enter(&dtrace_lock);
38 	mutex_enter(&cpu_lock);
39 
40 	ASSERT(dtrace_opens == 0);
41 
42 	if (dtrace_helpers > 0) {
43 		mutex_exit(&cpu_lock);
44 		mutex_exit(&dtrace_lock);
45 		mutex_exit(&dtrace_provider_lock);
46 		return (EBUSY);
47 	}
48 
49 	if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) {
50 		mutex_exit(&cpu_lock);
51 		mutex_exit(&dtrace_lock);
52 		mutex_exit(&dtrace_provider_lock);
53 		return (EBUSY);
54 	}
55 
56 	dtrace_provider = NULL;
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, dtrace_helptrace_size);
74 		dtrace_helptrace_buffer = NULL;
75 	}
76 
77 	if (dtrace_probes != NULL) {
78 		kmem_free(dtrace_probes, dtrace_probes_size);
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 	vmem_destroy(dtrace_arena);
93 
94 	if (dtrace_toxrange != NULL) {
95 		kmem_free(dtrace_toxrange, sizeof (dtrace_toxrange_t *));
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 	mutex_destroy(&dtrace_errlock);
112 
113 	/* XXX Hack */
114 	mutex_destroy(&mod_lock);
115 
116 	/* Reset our hook for exceptions. */
117 	dtrace_invop_uninit();
118 
119 	/*
120 	 * Reset our hook for thread switches, but ensure that vtime isn't
121 	 * active first.
122 	 */
123 	dtrace_vtime_active = 0;
124 	dtrace_vtime_switch_func = NULL;
125 
126 	/* Unhook from the trap handler. */
127 	dtrace_trap_func = NULL;
128 
129 	return (error);
130 }
131