diff options
author | pfg <pfg@FreeBSD.org> | 2013-04-17 02:20:17 +0000 |
---|---|---|
committer | pfg <pfg@FreeBSD.org> | 2013-04-17 02:20:17 +0000 |
commit | f9796e10e2b7bb43bf358c337b15bb183a6b1aaf (patch) | |
tree | daa5db7d59bdba8c6f4ebf57f4923612b4fd09b6 /sys/cddl | |
parent | 3ab51705b73c481b6bc76e733f494db7fa6f31fd (diff) | |
download | FreeBSD-src-f9796e10e2b7bb43bf358c337b15bb183a6b1aaf.zip FreeBSD-src-f9796e10e2b7bb43bf358c337b15bb183a6b1aaf.tar.gz |
DTrace: Revert r249367
The following change from illumos brought caused DTrace to
pause in an interactive environment:
3026 libdtrace should set LD_NOLAZYLOAD=1 to help the pid provider
This was not detected during testing because it doesn't
affect scripts.
We shouldn't be changing the environment, especially since the
LD_NOLAZYLOAD option doesn't apply to our (GNU) ld.
Unfortunately the change from upstream was made in such a way
that it is very difficult to separate this change from the
others so, at least for now, it's better to just revert
everything.
Reference:
https://www.illumos.org/issues/3026
Reported by: Navdeep Parhar and Mark Johnston
Diffstat (limited to 'sys/cddl')
3 files changed, 131 insertions, 189 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 89787e4..c8bb4de 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -23,7 +23,6 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved * Use is subject to license terms. */ @@ -2346,10 +2345,9 @@ dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu, { dtrace_speculation_t *spec; dtrace_buffer_t *src, *dest; - uintptr_t daddr, saddr, dlimit, slimit; + uintptr_t daddr, saddr, dlimit; dtrace_speculation_state_t current, new = 0; intptr_t offs; - uint64_t timestamp; if (which == 0) return; @@ -2425,37 +2423,7 @@ dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu, } /* - * We have sufficient space to copy the speculative buffer into the - * primary buffer. First, modify the speculative buffer, filling - * in the timestamp of all entries with the current time. The data - * must have the commit() time rather than the time it was traced, - * so that all entries in the primary buffer are in timestamp order. - */ - timestamp = dtrace_gethrtime(); - saddr = (uintptr_t)src->dtb_tomax; - slimit = saddr + src->dtb_offset; - while (saddr < slimit) { - size_t size; - dtrace_rechdr_t *dtrh = (dtrace_rechdr_t *)saddr; - - if (dtrh->dtrh_epid == DTRACE_EPIDNONE) { - saddr += sizeof (dtrace_epid_t); - continue; - } - ASSERT3U(dtrh->dtrh_epid, <=, state->dts_necbs); - size = state->dts_ecbs[dtrh->dtrh_epid - 1]->dte_size; - - ASSERT3U(saddr + size, <=, slimit); - ASSERT3U(size, >=, sizeof (dtrace_rechdr_t)); - ASSERT3U(DTRACE_RECORD_LOAD_TIMESTAMP(dtrh), ==, UINT64_MAX); - - DTRACE_RECORD_STORE_TIMESTAMP(dtrh, timestamp); - - saddr += size; - } - - /* - * Copy the buffer across. (Note that this is a + * We have the space; copy the buffer across. (Note that this is a * highly subobtimal bcopy(); in the unlikely event that this becomes * a serious performance issue, a high-performance DTrace-specific * bcopy() should obviously be invented.) @@ -6238,7 +6206,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, if (now - state->dts_alive > dtrace_deadman_timeout) { /* * We seem to be dead. Unless we (a) have kernel - * destructive permissions (b) have explicitly enabled + * destructive permissions (b) have expicitly enabled * destructive actions and (c) destructive actions have * not been disabled, we're going to transition into * the KILLED state, from which no further processing @@ -6266,18 +6234,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, tomax = buf->dtb_tomax; ASSERT(tomax != NULL); - if (ecb->dte_size != 0) { - dtrace_rechdr_t dtrh; - if (!(mstate.dtms_present & DTRACE_MSTATE_TIMESTAMP)) { - mstate.dtms_timestamp = dtrace_gethrtime(); - mstate.dtms_present |= DTRACE_MSTATE_TIMESTAMP; - } - ASSERT3U(ecb->dte_size, >=, sizeof (dtrace_rechdr_t)); - dtrh.dtrh_epid = ecb->dte_epid; - DTRACE_RECORD_STORE_TIMESTAMP(&dtrh, - mstate.dtms_timestamp); - *((dtrace_rechdr_t *)(tomax + offs)) = dtrh; - } + if (ecb->dte_size != 0) + DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid); mstate.dtms_epid = ecb->dte_epid; mstate.dtms_present |= DTRACE_MSTATE_EPID; @@ -6424,9 +6382,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, continue; switch (act->dta_kind) { - case DTRACEACT_SPECULATE: { - dtrace_rechdr_t *dtrh; - + case DTRACEACT_SPECULATE: ASSERT(buf == &state->dts_buffer[cpuid]); buf = dtrace_speculation_buffer(state, cpuid, val); @@ -6448,23 +6404,10 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, tomax = buf->dtb_tomax; ASSERT(tomax != NULL); - if (ecb->dte_size == 0) - continue; - - ASSERT3U(ecb->dte_size, >=, - sizeof (dtrace_rechdr_t)); - dtrh = ((void *)(tomax + offs)); - dtrh->dtrh_epid = ecb->dte_epid; - /* - * When the speculation is committed, all of - * the records in the speculative buffer will - * have their timestamps set to the commit - * time. Until then, it is set to a sentinel - * value, for debugability. - */ - DTRACE_RECORD_STORE_TIMESTAMP(dtrh, UINT64_MAX); + if (ecb->dte_size != 0) + DTRACE_STORE(uint32_t, tomax, offs, + ecb->dte_epid); continue; - } case DTRACEACT_PRINTM: { /* The DIF returns a 'memref'. */ @@ -9811,9 +9754,9 @@ dtrace_ecb_add(dtrace_state_t *state, dtrace_probe_t *probe) /* * The default size is the size of the default action: recording - * the header. + * the epid. */ - ecb->dte_size = ecb->dte_needed = sizeof (dtrace_rechdr_t); + ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t); ecb->dte_alignment = sizeof (dtrace_epid_t); epid = state->dts_epid++; @@ -9911,89 +9854,122 @@ dtrace_ecb_enable(dtrace_ecb_t *ecb) static void dtrace_ecb_resize(dtrace_ecb_t *ecb) { + uint32_t maxalign = sizeof (dtrace_epid_t); + uint32_t align = sizeof (uint8_t), offs, diff; dtrace_action_t *act; - uint32_t curneeded = UINT32_MAX; + int wastuple = 0; uint32_t aggbase = UINT32_MAX; + dtrace_state_t *state = ecb->dte_state; /* - * If we record anything, we always record the dtrace_rechdr_t. (And - * we always record it first.) + * If we record anything, we always record the epid. (And we always + * record it first.) */ - ecb->dte_size = sizeof (dtrace_rechdr_t); - ecb->dte_alignment = sizeof (dtrace_epid_t); + offs = sizeof (dtrace_epid_t); + ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t); for (act = ecb->dte_action; act != NULL; act = act->dta_next) { dtrace_recdesc_t *rec = &act->dta_rec; - ASSERT(rec->dtrd_size > 0 || rec->dtrd_alignment == 1); - ecb->dte_alignment = MAX(ecb->dte_alignment, - rec->dtrd_alignment); + if ((align = rec->dtrd_alignment) > maxalign) + maxalign = align; + + if (!wastuple && act->dta_intuple) { + /* + * This is the first record in a tuple. Align the + * offset to be at offset 4 in an 8-byte aligned + * block. + */ + diff = offs + sizeof (dtrace_aggid_t); + + if ((diff = (diff & (sizeof (uint64_t) - 1)))) + offs += sizeof (uint64_t) - diff; + + aggbase = offs - sizeof (dtrace_aggid_t); + ASSERT(!(aggbase & (sizeof (uint64_t) - 1))); + } + + /*LINTED*/ + if (rec->dtrd_size != 0 && (diff = (offs & (align - 1)))) { + /* + * The current offset is not properly aligned; align it. + */ + offs += align - diff; + } + + rec->dtrd_offset = offs; + + if (offs + rec->dtrd_size > ecb->dte_needed) { + ecb->dte_needed = offs + rec->dtrd_size; + + if (ecb->dte_needed > state->dts_needed) + state->dts_needed = ecb->dte_needed; + } if (DTRACEACT_ISAGG(act->dta_kind)) { dtrace_aggregation_t *agg = (dtrace_aggregation_t *)act; + dtrace_action_t *first = agg->dtag_first, *prev; - ASSERT(rec->dtrd_size != 0); - ASSERT(agg->dtag_first != NULL); - ASSERT(act->dta_prev->dta_intuple); + ASSERT(rec->dtrd_size != 0 && first != NULL); + ASSERT(wastuple); ASSERT(aggbase != UINT32_MAX); - ASSERT(curneeded != UINT32_MAX); agg->dtag_base = aggbase; - curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment); - rec->dtrd_offset = curneeded; - curneeded += rec->dtrd_size; - ecb->dte_needed = MAX(ecb->dte_needed, curneeded); + while ((prev = first->dta_prev) != NULL && + DTRACEACT_ISAGG(prev->dta_kind)) { + agg = (dtrace_aggregation_t *)prev; + first = agg->dtag_first; + } - aggbase = UINT32_MAX; - curneeded = UINT32_MAX; - } else if (act->dta_intuple) { - if (curneeded == UINT32_MAX) { - /* - * This is the first record in a tuple. Align - * curneeded to be at offset 4 in an 8-byte - * aligned block. - */ - ASSERT(act->dta_prev == NULL || - !act->dta_prev->dta_intuple); - ASSERT3U(aggbase, ==, UINT32_MAX); - curneeded = P2PHASEUP(ecb->dte_size, - sizeof (uint64_t), sizeof (dtrace_aggid_t)); - - aggbase = curneeded - sizeof (dtrace_aggid_t); - ASSERT(IS_P2ALIGNED(aggbase, - sizeof (uint64_t))); + if (prev != NULL) { + offs = prev->dta_rec.dtrd_offset + + prev->dta_rec.dtrd_size; + } else { + offs = sizeof (dtrace_epid_t); } - curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment); - rec->dtrd_offset = curneeded; - curneeded += rec->dtrd_size; + wastuple = 0; } else { - /* tuples must be followed by an aggregation */ - ASSERT(act->dta_prev == NULL || - !act->dta_prev->dta_intuple); + if (!act->dta_intuple) + ecb->dte_size = offs + rec->dtrd_size; - ecb->dte_size = P2ROUNDUP(ecb->dte_size, - rec->dtrd_alignment); - rec->dtrd_offset = ecb->dte_size; - ecb->dte_size += rec->dtrd_size; - ecb->dte_needed = MAX(ecb->dte_needed, ecb->dte_size); + offs += rec->dtrd_size; } + + wastuple = act->dta_intuple; } if ((act = ecb->dte_action) != NULL && !(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) && - ecb->dte_size == sizeof (dtrace_rechdr_t)) { + ecb->dte_size == sizeof (dtrace_epid_t)) { /* - * If the size is still sizeof (dtrace_rechdr_t), then all + * If the size is still sizeof (dtrace_epid_t), then all * actions store no data; set the size to 0. */ + ecb->dte_alignment = maxalign; ecb->dte_size = 0; + + /* + * If the needed space is still sizeof (dtrace_epid_t), then + * all actions need no additional space; set the needed + * size to 0. + */ + if (ecb->dte_needed == sizeof (dtrace_epid_t)) + ecb->dte_needed = 0; + + return; } - ecb->dte_size = P2ROUNDUP(ecb->dte_size, sizeof (dtrace_epid_t)); - ecb->dte_needed = P2ROUNDUP(ecb->dte_needed, (sizeof (dtrace_epid_t))); - ecb->dte_state->dts_needed = MAX(ecb->dte_state->dts_needed, - ecb->dte_needed); + /* + * Set our alignment, and make sure that the dte_size and dte_needed + * are aligned to the size of an EPID. + */ + ecb->dte_alignment = maxalign; + ecb->dte_size = (ecb->dte_size + (sizeof (dtrace_epid_t) - 1)) & + ~(sizeof (dtrace_epid_t) - 1); + ecb->dte_needed = (ecb->dte_needed + (sizeof (dtrace_epid_t) - 1)) & + ~(sizeof (dtrace_epid_t) - 1); + ASSERT(ecb->dte_size <= ecb->dte_needed); } static dtrace_action_t * @@ -10373,7 +10349,7 @@ dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc) break; case DTRACEACT_SPECULATE: - if (ecb->dte_size > sizeof (dtrace_rechdr_t)) + if (ecb->dte_size > sizeof (dtrace_epid_t)) return (EINVAL); if (dp == NULL) @@ -10494,7 +10470,7 @@ dtrace_ecb_action_remove(dtrace_ecb_t *ecb) ecb->dte_action = NULL; ecb->dte_action_last = NULL; - ecb->dte_size = 0; + ecb->dte_size = sizeof (dtrace_epid_t); } static void @@ -10763,13 +10739,12 @@ dtrace_buffer_switch(dtrace_buffer_t *buf) caddr_t tomax = buf->dtb_tomax; caddr_t xamot = buf->dtb_xamot; dtrace_icookie_t cookie; - hrtime_t now; + hrtime_t now = dtrace_gethrtime(); ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH)); ASSERT(!(buf->dtb_flags & DTRACEBUF_RING)); cookie = dtrace_interrupt_disable(); - now = dtrace_gethrtime(); buf->dtb_tomax = xamot; buf->dtb_xamot = tomax; buf->dtb_xamot_drops = buf->dtb_drops; @@ -11135,7 +11110,7 @@ dtrace_buffer_reserve(dtrace_buffer_t *buf, size_t needed, size_t align, if (epid == DTRACE_EPIDNONE) { size = sizeof (uint32_t); } else { - ASSERT3U(epid, <=, state->dts_necbs); + ASSERT(epid <= state->dts_necbs); ASSERT(state->dts_ecbs[epid - 1] != NULL); size = state->dts_ecbs[epid - 1]->dte_size; @@ -16412,7 +16387,6 @@ dtrace_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) desc.dtbd_drops = buf->dtb_drops; desc.dtbd_errors = buf->dtb_errors; desc.dtbd_oldest = buf->dtb_xamot_offset; - desc.dtbd_timestamp = dtrace_gethrtime(); mutex_exit(&dtrace_lock); diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index 4595c2e..4968352 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -26,7 +26,6 @@ /* * Copyright (c) 2011, Joyent, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_DTRACE_H @@ -931,10 +930,10 @@ typedef struct dtrace_ecbdesc { * DTrace Metadata Description Structures * * DTrace separates the trace data stream from the metadata stream. The only - * metadata tokens placed in the data stream are the dtrace_rechdr_t (EPID + - * timestamp) or (in the case of aggregations) aggregation identifiers. To - * determine the structure of the data, DTrace consumers pass the token to the - * kernel, and receive in return a corresponding description of the enabled + * metadata tokens placed in the data stream are enabled probe identifiers + * (EPIDs) or (in the case of aggregations) aggregation identifiers. In order + * to determine the structure of the data, DTrace consumers pass the token to + * the kernel, and receive in return a corresponding description of the enabled * probe (via the dtrace_eprobedesc structure) or the aggregation (via the * dtrace_aggdesc structure). Both of these structures are expressed in terms * of record descriptions (via the dtrace_recdesc structure) that describe the @@ -1029,8 +1028,7 @@ typedef struct dtrace_fmtdesc { #define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */ #define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */ #define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */ -#define DTRACEOPT_TEMPORAL 27 /* temporally ordered output */ -#define DTRACEOPT_MAX 28 /* number of options */ +#define DTRACEOPT_MAX 27 /* number of options */ #define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */ @@ -1050,9 +1048,7 @@ typedef struct dtrace_fmtdesc { * where user-level wishes the kernel to snapshot the buffer to (the * dtbd_data field). The kernel uses the same structure to pass back some * information regarding the buffer: the size of data actually copied out, the - * number of drops, the number of errors, the offset of the oldest record, - * and the time of the snapshot. - * + * number of drops, the number of errors, and the offset of the oldest record. * If the buffer policy is a "switch" policy, taking a snapshot of the * principal buffer has the additional effect of switching the active and * inactive buffers. Taking a snapshot of the aggregation buffer _always_ has @@ -1065,30 +1061,9 @@ typedef struct dtrace_bufdesc { uint64_t dtbd_drops; /* number of drops */ DTRACE_PTR(char, dtbd_data); /* data */ uint64_t dtbd_oldest; /* offset of oldest record */ - uint64_t dtbd_timestamp; /* hrtime of snapshot */ } dtrace_bufdesc_t; /* - * Each record in the buffer (dtbd_data) begins with a header that includes - * the epid and a timestamp. The timestamp is split into two 4-byte parts - * so that we do not require 8-byte alignment. - */ -typedef struct dtrace_rechdr { - dtrace_epid_t dtrh_epid; /* enabled probe id */ - uint32_t dtrh_timestamp_hi; /* high bits of hrtime_t */ - uint32_t dtrh_timestamp_lo; /* low bits of hrtime_t */ -} dtrace_rechdr_t; - -#define DTRACE_RECORD_LOAD_TIMESTAMP(dtrh) \ - ((dtrh)->dtrh_timestamp_lo + \ - ((uint64_t)(dtrh)->dtrh_timestamp_hi << 32)) - -#define DTRACE_RECORD_STORE_TIMESTAMP(dtrh, hrtime) { \ - (dtrh)->dtrh_timestamp_lo = (uint32_t)hrtime; \ - (dtrh)->dtrh_timestamp_hi = hrtime >> 32; \ -} - -/* * DTrace Status * * The status of DTrace is relayed via the dtrace_status structure. This diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h index 7355aa8..4d9a4f8 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h @@ -23,7 +23,6 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. * Use is subject to license terms. */ @@ -210,18 +209,15 @@ typedef struct dtrace_hash { * predicate is non-NULL, the DIF object is executed. If the result is * non-zero, the action list is processed, with each action being executed * accordingly. When the action list has been completely executed, processing - * advances to the next ECB. The ECB abstraction allows disjoint consumers - * to multiplex on single probes. - * - * Execution of the ECB results in consuming dte_size bytes in the buffer - * to record data. During execution, dte_needed bytes must be available in - * the buffer. This space is used for both recorded data and tuple data. + * advances to the next ECB. processing advances to the next ECB. If the + * result is non-zero; For each ECB, it first determines the The ECB + * abstraction allows disjoint consumers to multiplex on single probes. */ struct dtrace_ecb { dtrace_epid_t dte_epid; /* enabled probe ID */ uint32_t dte_alignment; /* required alignment */ - size_t dte_needed; /* space needed for execution */ - size_t dte_size; /* size of recorded payload */ + size_t dte_needed; /* bytes needed */ + size_t dte_size; /* total size of payload */ dtrace_predicate_t *dte_predicate; /* predicate, if any */ dtrace_action_t *dte_action; /* actions, if any */ dtrace_ecb_t *dte_next; /* next ECB on probe */ @@ -279,30 +275,27 @@ typedef struct dtrace_aggregation { * the EPID, the consumer can determine the data layout. (The data buffer * layout is shown schematically below.) By assuring that one can determine * data layout from the EPID, the metadata stream can be separated from the - * data stream -- simplifying the data stream enormously. The ECB always - * proceeds the recorded data as part of the dtrace_rechdr_t structure that - * includes the EPID and a high-resolution timestamp used for output ordering - * consistency. - * - * base of data buffer ---> +--------+--------------------+--------+ - * | rechdr | data | rechdr | - * +--------+------+--------+----+--------+ - * | data | rechdr | data | - * +---------------+--------+-------------+ - * | data, cont. | - * +--------+--------------------+--------+ - * | rechdr | data | | - * +--------+--------------------+ | - * | || | - * | || | - * | \/ | - * : : - * . . - * . . - * . . - * : : - * | | - * limit of data buffer ---> +--------------------------------------+ + * data stream -- simplifying the data stream enormously. + * + * base of data buffer ---> +------+--------------------+------+ + * | EPID | data | EPID | + * +------+--------+------+----+------+ + * | data | EPID | data | + * +---------------+------+-----------+ + * | data, cont. | + * +------+--------------------+------+ + * | EPID | data | | + * +------+--------------------+ | + * | || | + * | || | + * | \/ | + * : : + * . . + * . . + * . . + * : : + * | | + * limit of data buffer ---> +----------------------------------+ * * When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the * principal buffer (both scratch and payload) exceed the available space. If |