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 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