1179237Sjb/* 2179237Sjb * CDDL HEADER START 3179237Sjb * 4179237Sjb * The contents of this file are subject to the terms of the 5179237Sjb * Common Development and Distribution License (the "License"). 6179237Sjb * You may not use this file except in compliance with the License. 7179237Sjb * 8179237Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9179237Sjb * or http://www.opensolaris.org/os/licensing. 10179237Sjb * See the License for the specific language governing permissions 11179237Sjb * and limitations under the License. 12179237Sjb * 13179237Sjb * When distributing Covered Code, include this CDDL HEADER in each 14179237Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15179237Sjb * If applicable, add the following below this CDDL HEADER, with the 16179237Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17179237Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18179237Sjb * 19179237Sjb * CDDL HEADER END 20179237Sjb * 21179237Sjb * $FreeBSD$ 22179237Sjb * 23179237Sjb */ 24179237Sjb 25179237Sjbstatic int 26179237Sjbdtrace_unload() 27179237Sjb{ 28179237Sjb dtrace_state_t *state; 29179237Sjb int error = 0; 30179237Sjb 31184698Srodrigc#if __FreeBSD_version < 800039 32179237Sjb /* 33179237Sjb * Check if there is still an event handler callback 34179237Sjb * registered. 35179237Sjb */ 36179237Sjb if (eh_tag != 0) { 37179237Sjb /* De-register the device cloning event handler. */ 38179237Sjb EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 39179237Sjb eh_tag = 0; 40179237Sjb 41179237Sjb /* Stop device cloning. */ 42179237Sjb clone_cleanup(&dtrace_clones); 43179237Sjb } 44184698Srodrigc#else 45184698Srodrigc destroy_dev(dtrace_dev); 46211611Srpaulo destroy_dev(helper_dev); 47184698Srodrigc#endif 48179237Sjb 49179237Sjb mutex_enter(&dtrace_provider_lock); 50179237Sjb mutex_enter(&dtrace_lock); 51179237Sjb mutex_enter(&cpu_lock); 52179237Sjb 53179237Sjb ASSERT(dtrace_opens == 0); 54179237Sjb 55179237Sjb if (dtrace_helpers > 0) { 56179237Sjb mutex_exit(&cpu_lock); 57179237Sjb mutex_exit(&dtrace_lock); 58179237Sjb mutex_exit(&dtrace_provider_lock); 59179237Sjb return (EBUSY); 60179237Sjb } 61179237Sjb 62179237Sjb if (dtrace_unregister((dtrace_provider_id_t)dtrace_provider) != 0) { 63179237Sjb mutex_exit(&cpu_lock); 64179237Sjb mutex_exit(&dtrace_lock); 65179237Sjb mutex_exit(&dtrace_provider_lock); 66179237Sjb return (EBUSY); 67179237Sjb } 68179237Sjb 69179237Sjb dtrace_provider = NULL; 70254309Smarkj EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag); 71254813Smarkj EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag); 72179237Sjb 73179237Sjb if ((state = dtrace_anon_grab()) != NULL) { 74179237Sjb /* 75179237Sjb * If there were ECBs on this state, the provider should 76179237Sjb * have not been allowed to detach; assert that there is 77179237Sjb * none. 78179237Sjb */ 79179237Sjb ASSERT(state->dts_necbs == 0); 80179237Sjb dtrace_state_destroy(state); 81179237Sjb } 82179237Sjb 83179237Sjb bzero(&dtrace_anon, sizeof (dtrace_anon_t)); 84179237Sjb 85179237Sjb mutex_exit(&cpu_lock); 86179237Sjb 87179237Sjb if (dtrace_helptrace_enabled) { 88179237Sjb kmem_free(dtrace_helptrace_buffer, 0); 89179237Sjb dtrace_helptrace_buffer = NULL; 90179237Sjb } 91179237Sjb 92179237Sjb if (dtrace_probes != NULL) { 93179237Sjb kmem_free(dtrace_probes, 0); 94179237Sjb dtrace_probes = NULL; 95179237Sjb dtrace_nprobes = 0; 96179237Sjb } 97179237Sjb 98179237Sjb dtrace_hash_destroy(dtrace_bymod); 99179237Sjb dtrace_hash_destroy(dtrace_byfunc); 100179237Sjb dtrace_hash_destroy(dtrace_byname); 101179237Sjb dtrace_bymod = NULL; 102179237Sjb dtrace_byfunc = NULL; 103179237Sjb dtrace_byname = NULL; 104179237Sjb 105179237Sjb kmem_cache_destroy(dtrace_state_cache); 106179237Sjb 107179237Sjb delete_unrhdr(dtrace_arena); 108179237Sjb 109179237Sjb if (dtrace_toxrange != NULL) { 110179237Sjb kmem_free(dtrace_toxrange, 0); 111179237Sjb dtrace_toxrange = NULL; 112179237Sjb dtrace_toxranges = 0; 113179237Sjb dtrace_toxranges_max = 0; 114179237Sjb } 115179237Sjb 116179237Sjb ASSERT(dtrace_vtime_references == 0); 117179237Sjb ASSERT(dtrace_opens == 0); 118179237Sjb ASSERT(dtrace_retained == NULL); 119179237Sjb 120179237Sjb mutex_exit(&dtrace_lock); 121179237Sjb mutex_exit(&dtrace_provider_lock); 122179237Sjb 123179237Sjb mutex_destroy(&dtrace_meta_lock); 124179237Sjb mutex_destroy(&dtrace_provider_lock); 125179237Sjb mutex_destroy(&dtrace_lock); 126253996Savg#ifdef DEBUG 127179237Sjb mutex_destroy(&dtrace_errlock); 128253996Savg#endif 129179237Sjb 130256148Smarkj taskq_destroy(dtrace_taskq); 131256148Smarkj 132179237Sjb /* Reset our hook for exceptions. */ 133179237Sjb dtrace_invop_uninit(); 134179237Sjb 135179237Sjb /* 136179237Sjb * Reset our hook for thread switches, but ensure that vtime isn't 137179237Sjb * active first. 138179237Sjb */ 139179237Sjb dtrace_vtime_active = 0; 140179237Sjb dtrace_vtime_switch_func = NULL; 141179237Sjb 142179237Sjb /* Unhook from the trap handler. */ 143179237Sjb dtrace_trap_func = NULL; 144179237Sjb 145179237Sjb return (error); 146179237Sjb} 147