1 /*        $NetBSD: dtrace_unload.c,v 1.7 2018/05/28 21:05:03 chs 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: head/sys/cddl/dev/dtrace/dtrace_unload.c 278166 2015-02-03 19:39:53Z pfg $
24  *
25  */
26 
27 static int
dtrace_unload()28 dtrace_unload()
29 {
30           dtrace_state_t *state;
31           int error = 0;
32 
33 #ifdef __FreeBSD__
34           destroy_dev(dtrace_dev);
35           destroy_dev(helper_dev);
36 #endif
37 
38 #ifdef __NetBSD__
39           module_unregister_callbacks(dtrace_modcb);
40 #endif
41 
42           mutex_enter(&dtrace_provider_lock);
43           mutex_enter(&dtrace_lock);
44           mutex_enter(&cpu_lock);
45 
46           if (dtrace_opens > 0 || dtrace_helpers > 0) {
47                     mutex_exit(&cpu_lock);
48                     mutex_exit(&dtrace_lock);
49                     mutex_exit(&dtrace_provider_lock);
50                     return (EBUSY);
51           }
52 
53           if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) {
54                     mutex_exit(&cpu_lock);
55                     mutex_exit(&dtrace_lock);
56                     mutex_exit(&dtrace_provider_lock);
57                     return (EBUSY);
58           }
59 
60           dtrace_provider = NULL;
61 #ifdef __FreeBSD__
62           EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag);
63           EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag);
64 #endif
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_probes != NULL) {
81                     kmem_free(dtrace_probes, dtrace_nprobes * sizeof (dtrace_probe_t *));
82                     dtrace_probes = NULL;
83                     dtrace_nprobes = 0;
84           }
85 
86           dtrace_hash_destroy(dtrace_bymod);
87           dtrace_hash_destroy(dtrace_byfunc);
88           dtrace_hash_destroy(dtrace_byname);
89           dtrace_bymod = NULL;
90           dtrace_byfunc = NULL;
91           dtrace_byname = NULL;
92 
93           kmem_cache_destroy(dtrace_state_cache);
94 
95 #ifdef __FreeBSD__
96           delete_unrhdr(dtrace_arena);
97 #endif
98 #ifdef __NetBSD__
99           vmem_destroy(dtrace_arena);
100 #endif
101 
102           if (dtrace_toxrange != NULL) {
103                     kmem_free(dtrace_toxrange,
104                         dtrace_toxranges_max * sizeof (dtrace_toxrange_t));
105                     dtrace_toxrange = NULL;
106                     dtrace_toxranges = 0;
107                     dtrace_toxranges_max = 0;
108           }
109 
110           ASSERT(dtrace_vtime_references == 0);
111           ASSERT(dtrace_opens == 0);
112           ASSERT(dtrace_retained == NULL);
113 
114           mutex_exit(&dtrace_lock);
115           mutex_exit(&dtrace_provider_lock);
116 
117           mutex_destroy(&dtrace_meta_lock);
118           mutex_destroy(&dtrace_provider_lock);
119           mutex_destroy(&dtrace_lock);
120 #ifdef DEBUG
121           mutex_destroy(&dtrace_errlock);
122 #endif
123 
124 #ifdef __FreeBSD__
125           taskq_destroy(dtrace_taskq);
126 #endif
127 
128           /* Reset our hook for exceptions. */
129           dtrace_invop_uninit();
130 
131           /*
132            * Reset our hook for thread switches, but ensure that vtime isn't
133            * active first.
134            */
135           dtrace_vtime_active = 0;
136           dtrace_vtime_switch_func = NULL;
137 
138           /* Unhook from the trap handler. */
139           dtrace_trap_func = NULL;
140 
141           return (error);
142 }
143