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