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 #endif 47 48 mutex_enter(&dtrace_provider_lock); 49 mutex_enter(&dtrace_lock); 50 mutex_enter(&cpu_lock); 51 52 ASSERT(dtrace_opens == 0); 53 54 if (dtrace_helpers > 0) { 55 mutex_exit(&cpu_lock); 56 mutex_exit(&dtrace_lock); 57 mutex_exit(&dtrace_provider_lock); 58 return (EBUSY); 59 } 60 61 if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) { 62 mutex_exit(&cpu_lock); 63 mutex_exit(&dtrace_lock); 64 mutex_exit(&dtrace_provider_lock); 65 return (EBUSY); 66 } 67 68 dtrace_provider = NULL; 69 70 if ((state = dtrace_anon_grab()) != NULL) { 71 /* 72 * If there were ECBs on this state, the provider should 73 * have not been allowed to detach; assert that there is 74 * none. 75 */ 76 ASSERT(state->dts_necbs == 0); 77 dtrace_state_destroy(state); 78 } 79 80 bzero(&dtrace_anon, sizeof (dtrace_anon_t)); 81 82 mutex_exit(&cpu_lock); 83 84 if (dtrace_helptrace_enabled) { 85 kmem_free(dtrace_helptrace_buffer, 0); 86 dtrace_helptrace_buffer = NULL; 87 } 88 89 if (dtrace_probes != NULL) { 90 kmem_free(dtrace_probes, 0); 91 dtrace_probes = NULL; 92 dtrace_nprobes = 0; 93 } 94 95 dtrace_hash_destroy(dtrace_bymod); 96 dtrace_hash_destroy(dtrace_byfunc); 97 dtrace_hash_destroy(dtrace_byname); 98 dtrace_bymod = NULL; 99 dtrace_byfunc = NULL; 100 dtrace_byname = NULL; 101 102 kmem_cache_destroy(dtrace_state_cache); 103 104 delete_unrhdr(dtrace_arena); 105 106 if (dtrace_toxrange != NULL) { 107 kmem_free(dtrace_toxrange, 0); 108 dtrace_toxrange = NULL; 109 dtrace_toxranges = 0; 110 dtrace_toxranges_max = 0; 111 } 112 113 ASSERT(dtrace_vtime_references == 0); 114 ASSERT(dtrace_opens == 0); 115 ASSERT(dtrace_retained == NULL); 116 117 mutex_exit(&dtrace_lock); 118 mutex_exit(&dtrace_provider_lock); 119 120 mutex_destroy(&dtrace_meta_lock); 121 mutex_destroy(&dtrace_provider_lock); 122 mutex_destroy(&dtrace_lock); 123 mutex_destroy(&dtrace_errlock); 124 125 /* XXX Hack */ 126 mutex_destroy(&mod_lock); 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