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 71 if ((state = dtrace_anon_grab()) != NULL) { 72 /* 73 * If there were ECBs on this state, the provider should 74 * have not been allowed to detach; assert that there is 75 * none. 76 */ 77 ASSERT(state->dts_necbs == 0); 78 dtrace_state_destroy(state); 79 } 80 81 bzero(&dtrace_anon, sizeof (dtrace_anon_t)); 82 83 mutex_exit(&cpu_lock); 84 85 if (dtrace_helptrace_enabled) { 86 kmem_free(dtrace_helptrace_buffer, 0); 87 dtrace_helptrace_buffer = NULL; 88 } 89 90 if (dtrace_probes != NULL) { 91 kmem_free(dtrace_probes, 0); 92 dtrace_probes = NULL; 93 dtrace_nprobes = 0; 94 } 95 96 dtrace_hash_destroy(dtrace_bymod); 97 dtrace_hash_destroy(dtrace_byfunc); 98 dtrace_hash_destroy(dtrace_byname); 99 dtrace_bymod = NULL; 100 dtrace_byfunc = NULL; 101 dtrace_byname = NULL; 102 103 kmem_cache_destroy(dtrace_state_cache); 104 105 delete_unrhdr(dtrace_arena); 106 107 if (dtrace_toxrange != NULL) { 108 kmem_free(dtrace_toxrange, 0); 109 dtrace_toxrange = NULL; 110 dtrace_toxranges = 0; 111 dtrace_toxranges_max = 0; 112 } 113 114 ASSERT(dtrace_vtime_references == 0); 115 ASSERT(dtrace_opens == 0); 116 ASSERT(dtrace_retained == NULL); 117 118 mutex_exit(&dtrace_lock); 119 mutex_exit(&dtrace_provider_lock); 120 121 mutex_destroy(&dtrace_meta_lock); 122 mutex_destroy(&dtrace_provider_lock); 123 mutex_destroy(&dtrace_lock); 124 mutex_destroy(&dtrace_errlock); 125 126 /* Reset our hook for exceptions. */ 127 dtrace_invop_uninit(); 128 129 /* 130 * Reset our hook for thread switches, but ensure that vtime isn't 131 * active first. 132 */ 133 dtrace_vtime_active = 0; 134 dtrace_vtime_switch_func = NULL; 135 136 /* Unhook from the trap handler. */ 137 dtrace_trap_func = NULL; 138 139 return (error); 140 } 141