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 */ 22 23 static int 24 dtrace_unload(void) 25 { 26 dtrace_state_t *state; 27 int error = 0; 28 29 destroy_dev(dtrace_dev); 30 destroy_dev(helper_dev); 31 32 mutex_enter(&dtrace_provider_lock); 33 mutex_enter(&dtrace_lock); 34 mutex_enter(&cpu_lock); 35 36 ASSERT(dtrace_opens == 0); 37 38 if (dtrace_helpers > 0) { 39 mutex_exit(&cpu_lock); 40 mutex_exit(&dtrace_lock); 41 mutex_exit(&dtrace_provider_lock); 42 return (EBUSY); 43 } 44 45 if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) { 46 mutex_exit(&cpu_lock); 47 mutex_exit(&dtrace_lock); 48 mutex_exit(&dtrace_provider_lock); 49 return (EBUSY); 50 } 51 52 dtrace_provider = NULL; 53 EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag); 54 EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag); 55 56 if ((state = dtrace_anon_grab()) != NULL) { 57 /* 58 * If there were ECBs on this state, the provider should 59 * have not been allowed to detach; assert that there is 60 * none. 61 */ 62 ASSERT(state->dts_necbs == 0); 63 dtrace_state_destroy(state); 64 } 65 66 bzero(&dtrace_anon, sizeof (dtrace_anon_t)); 67 68 mutex_exit(&cpu_lock); 69 70 if (dtrace_probes != NULL) { 71 kmem_free(dtrace_probes, 0); 72 dtrace_probes = NULL; 73 dtrace_nprobes = 0; 74 } 75 76 dtrace_hash_destroy(dtrace_bymod); 77 dtrace_hash_destroy(dtrace_byfunc); 78 dtrace_hash_destroy(dtrace_byname); 79 dtrace_bymod = NULL; 80 dtrace_byfunc = NULL; 81 dtrace_byname = NULL; 82 83 kmem_cache_destroy(dtrace_state_cache); 84 85 delete_unrhdr(dtrace_arena); 86 87 if (dtrace_toxrange != NULL) { 88 kmem_free(dtrace_toxrange, 0); 89 dtrace_toxrange = NULL; 90 dtrace_toxranges = 0; 91 dtrace_toxranges_max = 0; 92 } 93 94 ASSERT(dtrace_vtime_references == 0); 95 ASSERT(dtrace_opens == 0); 96 ASSERT(dtrace_retained == NULL); 97 98 mutex_exit(&dtrace_lock); 99 mutex_exit(&dtrace_provider_lock); 100 101 mutex_destroy(&dtrace_meta_lock); 102 mutex_destroy(&dtrace_provider_lock); 103 mutex_destroy(&dtrace_lock); 104 #ifdef DEBUG 105 mutex_destroy(&dtrace_errlock); 106 #endif 107 108 taskq_destroy(dtrace_taskq); 109 110 /* Reset our hook for exceptions. */ 111 dtrace_invop_uninit(); 112 113 /* 114 * Reset our hook for thread switches, but ensure that vtime isn't 115 * active first. 116 */ 117 dtrace_vtime_active = 0; 118 dtrace_vtime_switch_func = NULL; 119 120 /* Unhook from the trap handler. */ 121 dtrace_trap_func = NULL; 122 123 return (error); 124 } 125