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 /* 32 * Check if there is still an event handler callback 33 * registered. 34 */ 35 if (eh_tag != 0) { 36 /* De-register the device cloning event handler. */ 37 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 38 eh_tag = 0; 39 40 /* Stop device cloning. */ 41 clone_cleanup(&dtrace_clones); 42 } 43 44 mutex_enter(&dtrace_provider_lock); 45 mutex_enter(&dtrace_lock); 46 mutex_enter(&cpu_lock); 47 48 ASSERT(dtrace_opens == 0); 49 50 if (dtrace_helpers > 0) { 51 mutex_exit(&cpu_lock); 52 mutex_exit(&dtrace_lock); 53 mutex_exit(&dtrace_provider_lock); 54 return (EBUSY); 55 } 56 57 if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) { 58 mutex_exit(&cpu_lock); 59 mutex_exit(&dtrace_lock); 60 mutex_exit(&dtrace_provider_lock); 61 return (EBUSY); 62 } 63 64 dtrace_provider = NULL; 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_helptrace_enabled) { 81 kmem_free(dtrace_helptrace_buffer, 0); 82 dtrace_helptrace_buffer = NULL; 83 } 84 85 if (dtrace_probes != NULL) { 86 kmem_free(dtrace_probes, 0); 87 dtrace_probes = NULL; 88 dtrace_nprobes = 0; 89 } 90 91 dtrace_hash_destroy(dtrace_bymod); 92 dtrace_hash_destroy(dtrace_byfunc); 93 dtrace_hash_destroy(dtrace_byname); 94 dtrace_bymod = NULL; 95 dtrace_byfunc = NULL; 96 dtrace_byname = NULL; 97 98 kmem_cache_destroy(dtrace_state_cache); 99 100 delete_unrhdr(dtrace_arena); 101 102 if (dtrace_toxrange != NULL) { 103 kmem_free(dtrace_toxrange, 0); 104 dtrace_toxrange = NULL; 105 dtrace_toxranges = 0; 106 dtrace_toxranges_max = 0; 107 } 108 109 ASSERT(dtrace_vtime_references == 0); 110 ASSERT(dtrace_opens == 0); 111 ASSERT(dtrace_retained == NULL); 112 113 mutex_exit(&dtrace_lock); 114 mutex_exit(&dtrace_provider_lock); 115 116 mutex_destroy(&dtrace_meta_lock); 117 mutex_destroy(&dtrace_provider_lock); 118 mutex_destroy(&dtrace_lock); 119 mutex_destroy(&dtrace_errlock); 120 121 /* XXX Hack */ 122 mutex_destroy(&mod_lock); 123 124 /* Reset our hook for exceptions. */ 125 dtrace_invop_uninit(); 126 127 /* 128 * Reset our hook for thread switches, but ensure that vtime isn't 129 * active first. 130 */ 131 dtrace_vtime_active = 0; 132 dtrace_vtime_switch_func = NULL; 133 134 /* Unhook from the trap handler. */ 135 dtrace_trap_func = NULL; 136 137 return (error); 138 } 139