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 --- 4 unchanged lines hidden (view full) --- 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: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c 248983 2013-04-01 19:13:46Z pfg $ |
22 */ 23 24/* 25 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29#pragma ident "%Z%%M% %I% %E% SMI" --- 147 unchanged lines hidden (view full) --- 177int dtrace_msgdsize_max = 128; 178hrtime_t dtrace_chill_max = 500 * (NANOSEC / MILLISEC); /* 500 ms */ 179hrtime_t dtrace_chill_interval = NANOSEC; /* 1000 ms */ 180int dtrace_devdepth_max = 32; 181int dtrace_err_verbose; 182hrtime_t dtrace_deadman_interval = NANOSEC; 183hrtime_t dtrace_deadman_timeout = (hrtime_t)10 * NANOSEC; 184hrtime_t dtrace_deadman_user = (hrtime_t)30 * NANOSEC; |
185hrtime_t dtrace_unregister_defunct_reap = (hrtime_t)60 * NANOSEC; |
186 187/* 188 * DTrace External Variables 189 * 190 * As dtrace(7D) is a kernel module, any DTrace variables are obviously 191 * available to DTrace consumers via the backtick (`) syntax. One of these, 192 * dtrace_zero, is made deliberately so: it is provided as a source of 193 * well-known, zero-filled memory. While this variable is not documented, --- 5 unchanged lines hidden (view full) --- 199 * DTrace Internal Variables 200 */ 201#if defined(sun) 202static dev_info_t *dtrace_devi; /* device info */ 203#endif 204#if defined(sun) 205static vmem_t *dtrace_arena; /* probe ID arena */ 206static vmem_t *dtrace_minor; /* minor number arena */ |
207#else |
208static taskq_t *dtrace_taskq; /* task queue */ |
209static struct unrhdr *dtrace_arena; /* Probe ID number. */ 210#endif 211static dtrace_probe_t **dtrace_probes; /* array of all probes */ 212static int dtrace_nprobes; /* number of probes */ 213static dtrace_provider_t *dtrace_provider; /* provider list */ 214static dtrace_meta_t *dtrace_meta_pid; /* user-land meta provider */ 215static int dtrace_opens; /* number of opens */ 216static int dtrace_helpers; /* number of helpers */ --- 329 unchanged lines hidden (view full) --- 546 (act)->dta_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) 547 548/* Function prototype definitions: */ 549static size_t dtrace_strlen(const char *, size_t); 550static dtrace_probe_t *dtrace_probe_lookup_id(dtrace_id_t id); 551static void dtrace_enabling_provide(dtrace_provider_t *); 552static int dtrace_enabling_match(dtrace_enabling_t *, int *); 553static void dtrace_enabling_matchall(void); |
554static void dtrace_enabling_reap(void); |
555static dtrace_state_t *dtrace_anon_grab(void); 556static uint64_t dtrace_helper(int, dtrace_mstate_t *, 557 dtrace_state_t *, uint64_t, uint64_t); 558static dtrace_helpers_t *dtrace_helpers_create(proc_t *); 559static void dtrace_buffer_drop(dtrace_buffer_t *); |
560static int dtrace_buffer_consumed(dtrace_buffer_t *, hrtime_t when); |
561static intptr_t dtrace_buffer_reserve(dtrace_buffer_t *, size_t, size_t, 562 dtrace_state_t *, dtrace_mstate_t *); 563static int dtrace_state_option(dtrace_state_t *, dtrace_optid_t, 564 dtrace_optval_t); 565static int dtrace_ecb_create_enable(dtrace_probe_t *, void *); 566static void dtrace_helper_provider_destroy(dtrace_helper_provider_t *); 567uint16_t dtrace_load16(uintptr_t); 568uint32_t dtrace_load32(uintptr_t); --- 7022 unchanged lines hidden (view full) --- 7591 * Unregister the specified provider from the DTrace framework. This should 7592 * generally be called by DTrace providers in their detach(9E) entry point. 7593 */ 7594int 7595dtrace_unregister(dtrace_provider_id_t id) 7596{ 7597 dtrace_provider_t *old = (dtrace_provider_t *)id; 7598 dtrace_provider_t *prev = NULL; |
7599 int i, self = 0, noreap = 0; |
7600 dtrace_probe_t *probe, *first = NULL; 7601 7602 if (old->dtpv_pops.dtps_enable == 7603 (void (*)(void *, dtrace_id_t, void *))dtrace_nullop) { 7604 /* 7605 * If DTrace itself is the provider, we're called with locks 7606 * already held. 7607 */ --- 42 unchanged lines hidden (view full) --- 7650 7651 if (probe->dtpr_provider != old) 7652 continue; 7653 7654 if (probe->dtpr_ecb == NULL) 7655 continue; 7656 7657 /* |
7658 * If we are trying to unregister a defunct provider, and the 7659 * provider was made defunct within the interval dictated by 7660 * dtrace_unregister_defunct_reap, we'll (asynchronously) 7661 * attempt to reap our enablings. To denote that the provider 7662 * should reattempt to unregister itself at some point in the 7663 * future, we will return a differentiable error code (EAGAIN 7664 * instead of EBUSY) in this case. |
7665 */ |
7666 if (dtrace_gethrtime() - old->dtpv_defunct > 7667 dtrace_unregister_defunct_reap) 7668 noreap = 1; 7669 |
7670 if (!self) { 7671 mutex_exit(&dtrace_lock); 7672 mutex_exit(&mod_lock); 7673 mutex_exit(&dtrace_provider_lock); 7674 } |
7675 7676 if (noreap) 7677 return (EBUSY); 7678 7679 (void) taskq_dispatch(dtrace_taskq, 7680 (task_func_t *)dtrace_enabling_reap, NULL, TQ_SLEEP); 7681 7682 return (EAGAIN); |
7683 } 7684 7685 /* 7686 * All of the probes for this provider are disabled; we can safely 7687 * remove all of them from their hash chains and from the probe array. 7688 */ 7689 for (i = 0; i < dtrace_nprobes; i++) { 7690 if ((probe = dtrace_probes[i]) == NULL) --- 80 unchanged lines hidden (view full) --- 7771 dtrace_provider_t *pvp = (dtrace_provider_t *)id; 7772 7773 ASSERT(pvp->dtpv_pops.dtps_enable != 7774 (void (*)(void *, dtrace_id_t, void *))dtrace_nullop); 7775 7776 mutex_enter(&dtrace_provider_lock); 7777 mutex_enter(&dtrace_lock); 7778 |
7779 pvp->dtpv_defunct = dtrace_gethrtime(); |
7780 7781 mutex_exit(&dtrace_lock); 7782 mutex_exit(&dtrace_provider_lock); 7783} 7784 7785/* 7786 * Indicate whether or not DTrace has attached. 7787 */ --- 2946 unchanged lines hidden (view full) --- 10734 * the same CPU. 10735 */ 10736static void 10737dtrace_buffer_switch(dtrace_buffer_t *buf) 10738{ 10739 caddr_t tomax = buf->dtb_tomax; 10740 caddr_t xamot = buf->dtb_xamot; 10741 dtrace_icookie_t cookie; |
10742 hrtime_t now = dtrace_gethrtime(); |
10743 10744 ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH)); 10745 ASSERT(!(buf->dtb_flags & DTRACEBUF_RING)); 10746 10747 cookie = dtrace_interrupt_disable(); 10748 buf->dtb_tomax = xamot; 10749 buf->dtb_xamot = tomax; 10750 buf->dtb_xamot_drops = buf->dtb_drops; 10751 buf->dtb_xamot_offset = buf->dtb_offset; 10752 buf->dtb_xamot_errors = buf->dtb_errors; 10753 buf->dtb_xamot_flags = buf->dtb_flags; 10754 buf->dtb_offset = 0; 10755 buf->dtb_drops = 0; 10756 buf->dtb_errors = 0; 10757 buf->dtb_flags &= ~(DTRACEBUF_ERROR | DTRACEBUF_DROPPED); |
10758 buf->dtb_interval = now - buf->dtb_switched; 10759 buf->dtb_switched = now; |
10760 dtrace_interrupt_enable(cookie); 10761} 10762 10763/* 10764 * Note: called from cross call context. This function activates a buffer 10765 * on a CPU. As with dtrace_buffer_switch(), the atomicity of the operation 10766 * is guaranteed by the disabling of interrupts. 10767 */ --- 472 unchanged lines hidden (view full) --- 11240 11241 if (buf->dtb_offset > buf->dtb_xamot_offset) { 11242 bzero(buf->dtb_tomax + buf->dtb_offset, 11243 buf->dtb_size - buf->dtb_offset); 11244 bzero(buf->dtb_tomax, buf->dtb_xamot_offset); 11245 } 11246} 11247 |
11248/* 11249 * This routine determines if data generated at the specified time has likely 11250 * been entirely consumed at user-level. This routine is called to determine 11251 * if an ECB on a defunct probe (but for an active enabling) can be safely 11252 * disabled and destroyed. 11253 */ 11254static int 11255dtrace_buffer_consumed(dtrace_buffer_t *bufs, hrtime_t when) 11256{ 11257 int i; 11258 11259 for (i = 0; i < NCPU; i++) { 11260 dtrace_buffer_t *buf = &bufs[i]; 11261 11262 if (buf->dtb_size == 0) 11263 continue; 11264 11265 if (buf->dtb_flags & DTRACEBUF_RING) 11266 return (0); 11267 11268 if (!buf->dtb_switched && buf->dtb_offset != 0) 11269 return (0); 11270 11271 if (buf->dtb_switched - buf->dtb_interval < when) 11272 return (0); 11273 } 11274 11275 return (1); 11276} 11277 |
11278static void 11279dtrace_buffer_free(dtrace_buffer_t *bufs) 11280{ 11281 int i; 11282 11283 for (i = 0; i < NCPU; i++) { 11284 dtrace_buffer_t *buf = &bufs[i]; 11285 --- 455 unchanged lines hidden (view full) --- 11741 } while (all && (prv = prv->dtpv_next) != NULL); 11742 11743 mutex_exit(&dtrace_lock); 11744 dtrace_probe_provide(NULL, all ? NULL : prv); 11745 mutex_enter(&dtrace_lock); 11746} 11747 11748/* |
11749 * Called to reap ECBs that are attached to probes from defunct providers. 11750 */ 11751static void 11752dtrace_enabling_reap(void) 11753{ 11754 dtrace_provider_t *prov; 11755 dtrace_probe_t *probe; 11756 dtrace_ecb_t *ecb; 11757 hrtime_t when; 11758 int i; 11759 11760 mutex_enter(&cpu_lock); 11761 mutex_enter(&dtrace_lock); 11762 11763 for (i = 0; i < dtrace_nprobes; i++) { 11764 if ((probe = dtrace_probes[i]) == NULL) 11765 continue; 11766 11767 if (probe->dtpr_ecb == NULL) 11768 continue; 11769 11770 prov = probe->dtpr_provider; 11771 11772 if ((when = prov->dtpv_defunct) == 0) 11773 continue; 11774 11775 /* 11776 * We have ECBs on a defunct provider: we want to reap these 11777 * ECBs to allow the provider to unregister. The destruction 11778 * of these ECBs must be done carefully: if we destroy the ECB 11779 * and the consumer later wishes to consume an EPID that 11780 * corresponds to the destroyed ECB (and if the EPID metadata 11781 * has not been previously consumed), the consumer will abort 11782 * processing on the unknown EPID. To reduce (but not, sadly, 11783 * eliminate) the possibility of this, we will only destroy an 11784 * ECB for a defunct provider if, for the state that 11785 * corresponds to the ECB: 11786 * 11787 * (a) There is no speculative tracing (which can effectively 11788 * cache an EPID for an arbitrary amount of time). 11789 * 11790 * (b) The principal buffers have been switched twice since the 11791 * provider became defunct. 11792 * 11793 * (c) The aggregation buffers are of zero size or have been 11794 * switched twice since the provider became defunct. 11795 * 11796 * We use dts_speculates to determine (a) and call a function 11797 * (dtrace_buffer_consumed()) to determine (b) and (c). Note 11798 * that as soon as we've been unable to destroy one of the ECBs 11799 * associated with the probe, we quit trying -- reaping is only 11800 * fruitful in as much as we can destroy all ECBs associated 11801 * with the defunct provider's probes. 11802 */ 11803 while ((ecb = probe->dtpr_ecb) != NULL) { 11804 dtrace_state_t *state = ecb->dte_state; 11805 dtrace_buffer_t *buf = state->dts_buffer; 11806 dtrace_buffer_t *aggbuf = state->dts_aggbuffer; 11807 11808 if (state->dts_speculates) 11809 break; 11810 11811 if (!dtrace_buffer_consumed(buf, when)) 11812 break; 11813 11814 if (!dtrace_buffer_consumed(aggbuf, when)) 11815 break; 11816 11817 dtrace_ecb_disable(ecb); 11818 ASSERT(probe->dtpr_ecb != ecb); 11819 dtrace_ecb_destroy(ecb); 11820 } 11821 } 11822 11823 mutex_exit(&dtrace_lock); 11824 mutex_exit(&cpu_lock); 11825} 11826 11827/* |
11828 * DTrace DOF Functions 11829 */ 11830/*ARGSUSED*/ 11831static void 11832dtrace_dof_error(dof_hdr_t *dof, const char *str) 11833{ 11834 if (dtrace_err_verbose) 11835 cmn_err(CE_WARN, "failed to process DOF: %s", str); --- 3820 unchanged lines hidden (view full) --- 15656 state = dtrace_state_create(devp, cred_p); 15657#else 15658 state = dtrace_state_create(dev); 15659#if __FreeBSD_version < 800039 15660 dev->si_drv1 = state; 15661#else 15662 devfs_set_cdevpriv(state, dtrace_dtr); 15663#endif |
15664 /* This code actually belongs in dtrace_attach() */ 15665 if (dtrace_opens == 1) 15666 dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 15667 1, INT_MAX, 0); |
15668#endif 15669 15670 mutex_exit(&cpu_lock); 15671 15672 if (state == NULL) { 15673#if defined(sun) 15674 if (--dtrace_opens == 0) 15675 (void) kdi_dtrace_set(KDI_DTSET_DTRACE_DEACTIVATE); --- 71 unchanged lines hidden (view full) --- 15747 } 15748 15749 ASSERT(dtrace_opens > 0); 15750#if defined(sun) 15751 if (--dtrace_opens == 0) 15752 (void) kdi_dtrace_set(KDI_DTSET_DTRACE_DEACTIVATE); 15753#else 15754 --dtrace_opens; |
15755 /* This code actually belongs in dtrace_detach() */ 15756 if ((dtrace_opens == 0) && (dtrace_taskq != NULL)) { 15757 taskq_destroy(dtrace_taskq); 15758 dtrace_taskq = NULL; 15759 } |
15760#endif 15761 15762 mutex_exit(&dtrace_lock); 15763 mutex_exit(&cpu_lock); 15764 15765#if __FreeBSD_version < 800039 15766 /* Schedule this cloned device to be destroyed. */ 15767 destroy_dev_sched(dev); --- 1088 unchanged lines hidden --- |