Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Apr 2006 01:22:09 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 95649 for review
Message-ID:  <200604200122.k3K1M9TL093388@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=95649

Change 95649 by jb@jb_freebsd2 on 2006/04/20 01:21:25

	Work-in-progress update.
	
	Suck in the bulk of the Solaris dtrace device definitions, leaving
	things commented out that would cause compiler errors/warnings.

Affected files ...

.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace.c#5 edit

Differences ...

==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace.c#5 (text+ko) ====

@@ -22,6 +22,50 @@
  *
  */
 
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * DTrace - Dynamic Tracing for Solaris
+ *
+ * This is the implementation of the Solaris Dynamic Tracing framework
+ * (DTrace).  The user-visible interface to DTrace is described at length in
+ * the "Solaris Dynamic Tracing Guide".  The interfaces between the libdtrace
+ * library, the in-kernel DTrace framework, and the DTrace providers are
+ * described in the block comments in the <sys/dtrace.h> header file.  The
+ * internal architecture of DTrace is described in the block comments in the
+ * <sys/dtrace_impl.h> header file.  The comments contained within the DTrace
+ * implementation very much assume mastery of all of these sources; if one has
+ * an unanswered question about the implementation, one should consult them
+ * first.
+ *
+ * The functions here are ordered roughly as follows:
+ *
+ *   - Probe context functions
+ *   - Probe hashing functions
+ *   - Non-probe context utility functions
+ *   - Matching functions
+ *   - Provider-to-Framework API functions
+ *   - Probe management functions
+ *   - DIF object functions
+ *   - Format functions
+ *   - Predicate functions
+ *   - ECB functions
+ *   - Buffer functions
+ *   - Enabling functions
+ *   - DOF functions
+ *   - Anonymous enabling functions
+ *   - Consumer state functions
+ *   - Helper functions
+ *   - Hook functions
+ *   - Driver cookbook functions
+ *
+ * Each group of functions begins with a block comment labelled the "DTrace
+ * [Group] Functions", allowing one to find each block by searching forward
+ * on capital-f functions.
+ */
 #include <sys/cdefs.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -41,15 +85,20 @@
 #include <sys/sysctl.h>
 #include <sys/uio.h>
 #include <sys/unistd.h>
+#include <machine/stdarg.h>
 
-#include <machine/bus.h>
-#include <machine/cpu.h>
+#include <contrib/opensolaris/uts/common/sys/dtrace_impl.h>
 
-#include <contrib/opensolaris/uts/common/sys/dtrace.h>
-#include <cddl/dev/dtrace/dtrace.h>
+/* For compatibility with Solaris code. */
+typedef struct mtx	kmutex_t;
+#define	mutex_enter(_a)	mtx_lock(_a)
+#define	mutex_exit(_a)	mtx_unlock(_a)
 
 #define DTRACE_MINOR	0
 
+MALLOC_DECLARE(M_DTRACE);
+MALLOC_DEFINE(M_DTRACE, "dtrace", "Dynamic Trace");
+
 static d_close_t	dtrace_close;
 static d_ioctl_t	dtrace_ioctl;
 static d_open_t		dtrace_open;
@@ -57,23 +106,380 @@
 static int		dtrace_unload(void);
 
 static struct cdevsw dtrace_cdevsw = {
-	.d_version = D_VERSION,
-	.d_close = dtrace_close,
-	.d_ioctl = dtrace_ioctl,
-	.d_open = dtrace_open,
-	.d_name = "dtrace",
+	.d_version	= D_VERSION,
+	.d_close	= dtrace_close,
+	.d_ioctl	= dtrace_ioctl,
+	.d_open		= dtrace_open,
+	.d_name		= "dtrace",
 };
 
 /* For use with make_dev(9)/destroy_dev(9). */
-static struct cdev *dtrace_dev;
+static struct cdev 	*dtrace_dev;
+
+/*
+ * DTrace Tunable Variables
+ *
+ * The following variables may be tuned by adding a line to /etc/system that
+ * includes both the name of the DTrace module ("dtrace") and the name of the
+ * variable.  For example:
+ *
+ *   set dtrace:dtrace_destructive_disallow = 1
+ *
+ * In general, the only variables that one should be tuning this way are those
+ * that affect system-wide DTrace behavior, and for which the default behavior
+ * is undesirable.  Most of these variables are tunable on a per-consumer
+ * basis using DTrace options, and need not be tuned on a system-wide basis.
+ * When tuning these variables, avoid pathological values; while some attempt
+ * is made to verify the integrity of these variables, they are not considered
+ * part of the supported interface to DTrace, and they are therefore not
+ * checked comprehensively.  Further, these variables should not be tuned
+ * dynamically via "mdb -kw" or other means; they should only be tuned via
+ * /etc/system.
+ */
+#ifdef DOODAD
+int		dtrace_destructive_disallow = 0;
+dtrace_optval_t	dtrace_nonroot_maxsize = (16 * 1024 * 1024);
+size_t		dtrace_difo_maxsize = (256 * 1024);
+dtrace_optval_t	dtrace_dof_maxsize = (256 * 1024);
+size_t		dtrace_global_maxsize = (16 * 1024);
+size_t		dtrace_actions_max = (16 * 1024);
+size_t		dtrace_retain_max = 1024;
+dtrace_optval_t	dtrace_helper_actions_max = 32;
+dtrace_optval_t	dtrace_helper_providers_max = 32;
+dtrace_optval_t	dtrace_dstate_defsize = (1 * 1024 * 1024);
+size_t		dtrace_strsize_default = 256;
+dtrace_optval_t	dtrace_cleanrate_default = 9900990;		/* 101 hz */
+dtrace_optval_t	dtrace_cleanrate_min = 200000;			/* 5000 hz */
+dtrace_optval_t	dtrace_cleanrate_max = (uint64_t)60 * NANOSEC;	/* 1/minute */
+dtrace_optval_t	dtrace_aggrate_default = NANOSEC;		/* 1 hz */
+dtrace_optval_t	dtrace_statusrate_default = NANOSEC;		/* 1 hz */
+dtrace_optval_t dtrace_statusrate_max = (hrtime_t)10 * NANOSEC;	 /* 6/minute */
+dtrace_optval_t	dtrace_switchrate_default = NANOSEC;		/* 1 hz */
+dtrace_optval_t	dtrace_nspec_default = 1;
+dtrace_optval_t	dtrace_specsize_default = 32 * 1024;
+dtrace_optval_t dtrace_stackframes_default = 20;
+dtrace_optval_t dtrace_ustackframes_default = 20;
+dtrace_optval_t dtrace_jstackframes_default = 50;
+dtrace_optval_t dtrace_jstackstrsize_default = 512;
+int		dtrace_msgdsize_max = 128;
+hrtime_t	dtrace_chill_max = 500 * (NANOSEC / MILLISEC);	/* 500 ms */
+hrtime_t	dtrace_chill_interval = NANOSEC;		/* 1000 ms */
+int		dtrace_devdepth_max = 32;
+int		dtrace_err_verbose;
+hrtime_t	dtrace_deadman_interval = NANOSEC;
+hrtime_t	dtrace_deadman_timeout = (hrtime_t)10 * NANOSEC;
+hrtime_t	dtrace_deadman_user = (hrtime_t)30 * NANOSEC;
+#endif
+
+/*
+ * DTrace External Variables
+ *
+ * As dtrace(7D) is a kernel module, any DTrace variables are obviously
+ * available to DTrace consumers via the backtick (`) syntax.  One of these,
+ * dtrace_zero, is made deliberately so:  it is provided as a source of
+ * well-known, zero-filled memory.  While this variable is not documented,
+ * it is used by some translators as an implementation detail.
+ */
+#ifdef DOODAD
+const char	dtrace_zero[256] = { 0 };	/* zero-filled memory */
+#endif
+
+/*
+ * DTrace Internal Variables
+ */
+#ifdef DOODAD
+static dev_info_t	*dtrace_devi;		/* device info */
+static vmem_t		*dtrace_arena;		/* probe ID arena */
+static vmem_t		*dtrace_minor;		/* minor number arena */
+static taskq_t		*dtrace_taskq;		/* task queue */
+#endif
+static dtrace_probe_t	**dtrace_probes;	/* array of all probes */
+static int		dtrace_nprobes;		/* number of probes */
+static dtrace_provider_t *dtrace_provider;	/* provider list */
+#ifdef DOODAD
+static dtrace_meta_t	*dtrace_meta_pid;	/* user-land meta provider */
+#endif
+static int		dtrace_opens;		/* number of opens */
+static int		dtrace_helpers;		/* number of helpers */
+#ifdef DOODAD
+static void		*dtrace_softstate;	/* softstate pointer */
+static dtrace_hash_t	*dtrace_bymod;		/* probes hashed by module */
+static dtrace_hash_t	*dtrace_byfunc;		/* probes hashed by function */
+static dtrace_hash_t	*dtrace_byname;		/* probes hashed by name */
+static dtrace_toxrange_t *dtrace_toxrange;	/* toxic range array */
+static int		dtrace_toxranges;	/* number of toxic ranges */
+static int		dtrace_toxranges_max;	/* size of toxic range array */
+#endif
+static dtrace_anon_t	dtrace_anon;		/* anonymous enabling */
+#ifdef DOODAD
+static kmem_cache_t	*dtrace_state_cache;	/* cache for dynamic state */
+static uint64_t		dtrace_vtime_references; /* number of vtimestamp refs */
+static kthread_t	*dtrace_panicked;	/* panicking thread */
+static dtrace_ecb_t	*dtrace_ecb_create_cache; /* cached created ECB */
+static dtrace_genid_t	dtrace_probegen;	/* current probe generation */
+static dtrace_helpers_t *dtrace_deferred_pid;	/* deferred helper list */
+static dtrace_enabling_t *dtrace_retained;	/* list of retained enablings */
+static dtrace_dynvar_t	dtrace_dynhash_sink;	/* end of dynamic hash chains */
+#endif
+
+/*
+ * DTrace Locking
+ * DTrace is protected by three (relatively coarse-grained) locks:
+ *
+ * (1) dtrace_lock is required to manipulate essentially any DTrace state,
+ *     including enabling state, probes, ECBs, consumer state, helper state,
+ *     etc.  Importantly, dtrace_lock is _not_ required when in probe context;
+ *     probe context is lock-free -- synchronization is handled via the
+ *     dtrace_sync() cross call mechanism.
+ *
+ * (2) dtrace_provider_lock is required when manipulating provider state, or
+ *     when provider state must be held constant.
+ *
+ * (3) dtrace_meta_lock is required when manipulating meta provider state, or
+ *     when meta provider state must be held constant.
+ *
+ * The lock ordering between these three locks is dtrace_meta_lock before
+ * dtrace_provider_lock before dtrace_lock.  (In particular, there are
+ * several places where dtrace_provider_lock is held by the framework as it
+ * calls into the providers -- which then call back into the framework,
+ * grabbing dtrace_lock.)
+ *
+ * There are two other locks in the mix:  mod_lock and cpu_lock.  With respect
+ * to dtrace_provider_lock and dtrace_lock, cpu_lock continues its historical
+ * role as a coarse-grained lock; it is acquired before both of these locks.
+ * With respect to dtrace_meta_lock, its behavior is stranger:  cpu_lock must
+ * be acquired _between_ dtrace_meta_lock and any other DTrace locks.
+ * mod_lock is similar with respect to dtrace_provider_lock in that it must be
+ * acquired _between_ dtrace_provider_lock and dtrace_lock.
+ */
+
+static kmutex_t		dtrace_lock;		/* probe state lock */
+static kmutex_t		dtrace_provider_lock;	/* provider state lock */
+static kmutex_t		dtrace_meta_lock;	/* meta-provider state lock */
+
+/*
+ * DTrace Provider Variables
+ *
+ * These are the variables relating to DTrace as a provider (that is, the
+ * provider of the BEGIN, END, and ERROR probes).
+ */
+static dtrace_pattr_t	dtrace_provider_attr = {
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+};
+
+static void
+dtrace_nullop(void)
+{}
+
+static dtrace_pops_t	dtrace_provider_ops = {
+	(void (*)(void *, const dtrace_probedesc_t *))dtrace_nullop,
+	(void (*)(void *, struct modctl *))dtrace_nullop,
+	(void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
+	(void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
+	(void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
+	(void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
+	NULL,
+	NULL,
+	NULL,
+	(void (*)(void *, dtrace_id_t, void *))dtrace_nullop
+};
+
+#ifdef DOODAD
+static dtrace_id_t	dtrace_probeid_begin;	/* special BEGIN probe */
+static dtrace_id_t	dtrace_probeid_end;	/* special END probe */
+dtrace_id_t		dtrace_probeid_error;	/* special ERROR probe */
+
+/*
+ * DTrace Helper Tracing Variables
+ */
+uint32_t dtrace_helptrace_next = 0;
+uint32_t dtrace_helptrace_nlocals;
+char	*dtrace_helptrace_buffer;
+int	dtrace_helptrace_bufsize = 512 * 1024;
+
+#ifdef DEBUG
+int	dtrace_helptrace_enabled = 1;
+#else
+int	dtrace_helptrace_enabled = 0;
+#endif
+
+/*
+ * DTrace Error Hashing
+ *
+ * On DEBUG kernels, DTrace will track the errors that has seen in a hash
+ * table.  This is very useful for checking coverage of tests that are
+ * expected to induce DIF or DOF processing errors, and may be useful for
+ * debugging problems in the DIF code generator or in DOF generation .  The
+ * error hash may be examined with the ::dtrace_errhash MDB dcmd.
+ */
+#ifdef DEBUG
+static dtrace_errhash_t	dtrace_errhash[DTRACE_ERRHASHSZ];
+static const char *dtrace_errlast;
+static kthread_t *dtrace_errthread;
+static kmutex_t dtrace_errlock;
+#endif
+
+/*
+ * DTrace Macros and Constants
+ *
+ * These are various macros that are useful in various spots in the
+ * implementation, along with a few random constants that have no meaning
+ * outside of the implementation.  There is no real structure to this cpp
+ * mishmash -- but is there ever?
+ */
+#define	DTRACE_HASHSTR(hash, probe)	\
+	dtrace_hash_str(*((char **)((uintptr_t)(probe) + (hash)->dth_stroffs)))
+
+#define	DTRACE_HASHNEXT(hash, probe)	\
+	(dtrace_probe_t **)((uintptr_t)(probe) + (hash)->dth_nextoffs)
+
+#define	DTRACE_HASHPREV(hash, probe)	\
+	(dtrace_probe_t **)((uintptr_t)(probe) + (hash)->dth_prevoffs)
+
+#define	DTRACE_HASHEQ(hash, lhs, rhs)	\
+	(strcmp(*((char **)((uintptr_t)(lhs) + (hash)->dth_stroffs)), \
+	    *((char **)((uintptr_t)(rhs) + (hash)->dth_stroffs))) == 0)
+
+#define	DTRACE_AGGHASHSIZE_SLEW		17
+
+/*
+ * The key for a thread-local variable consists of the lower 61 bits of the
+ * t_did, plus the 3 bits of the highest active interrupt above LOCK_LEVEL.
+ * We add DIF_VARIABLE_MAX to t_did to assure that the thread key is never
+ * equal to a variable identifier.  This is necessary (but not sufficient) to
+ * assure that global associative arrays never collide with thread-local
+ * variables.  To guarantee that they cannot collide, we must also define the
+ * order for keying dynamic variables.  That order is:
+ *
+ *   [ key0 ] ... [ keyn ] [ variable-key ] [ tls-key ]
+ *
+ * Because the variable-key and the tls-key are in orthogonal spaces, there is
+ * no way for a global variable key signature to match a thread-local key
+ * signature.
+ */
+#define	DTRACE_TLS_THRKEY(where) { \
+	uint_t intr = 0; \
+	uint_t actv = CPU->cpu_intr_actv >> (LOCK_LEVEL + 1); \
+	for (; actv; actv >>= 1) \
+		intr++; \
+	ASSERT(intr < (1 << 3)); \
+	(where) = ((curthread->t_did + DIF_VARIABLE_MAX) & \
+	    (((uint64_t)1 << 61) - 1)) | ((uint64_t)intr << 61); \
+}
+
+#define	DTRACE_STORE(type, tomax, offset, what) \
+	*((type *)((uintptr_t)(tomax) + (uintptr_t)offset)) = (type)(what);
+
+#ifndef __i386
+#define	DTRACE_ALIGNCHECK(addr, size, flags)				\
+	if (addr & (size - 1)) {					\
+		*flags |= CPU_DTRACE_BADALIGN;				\
+		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = addr;	\
+		return (0);						\
+	}
+#else
+#define	DTRACE_ALIGNCHECK(addr, size, flags)
+#endif
+
+#define	DTRACE_LOADFUNC(bits)						\
+/*CSTYLED*/								\
+uint##bits##_t								\
+dtrace_load##bits(uintptr_t addr)					\
+{									\
+	size_t size = bits / NBBY;					\
+	/*CSTYLED*/							\
+	uint##bits##_t rval;						\
+	int i;								\
+	volatile uint16_t *flags = (volatile uint16_t *)		\
+	    &cpu_core[CPU->cpu_id].cpuc_dtrace_flags;			\
+									\
+	DTRACE_ALIGNCHECK(addr, size, flags);				\
+									\
+	for (i = 0; i < dtrace_toxranges; i++) {			\
+		if (addr >= dtrace_toxrange[i].dtt_limit)		\
+			continue;					\
+									\
+		if (addr + size <= dtrace_toxrange[i].dtt_base)		\
+			continue;					\
+									\
+		/*							\
+		 * This address falls within a toxic region; return 0.	\
+		 */							\
+		*flags |= CPU_DTRACE_BADADDR;				\
+		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = addr;	\
+		return (0);						\
+	}								\
+									\
+	*flags |= CPU_DTRACE_NOFAULT;					\
+	/*CSTYLED*/							\
+	rval = *((volatile uint##bits##_t *)addr);			\
+	*flags &= ~CPU_DTRACE_NOFAULT;					\
+									\
+	return (rval);							\
+}
+
+#ifdef _LP64
+#define	dtrace_loadptr	dtrace_load64
+#else
+#define	dtrace_loadptr	dtrace_load32
+#endif
+
+#define	DTRACE_DYNHASH_FREE	0
+#define	DTRACE_DYNHASH_SINK	1
+#define	DTRACE_DYNHASH_VALID	2
+
+#define	DTRACE_MATCH_NEXT	0
+#define	DTRACE_MATCH_DONE	1
+#define	DTRACE_ANCHORED(probe)	((probe)->dtpr_func[0] != '\0')
+#define	DTRACE_STATE_ALIGN	64
+
+#define	DTRACE_FLAGS2FLT(flags)						\
+	(((flags) & CPU_DTRACE_BADADDR) ? DTRACEFLT_BADADDR :		\
+	((flags) & CPU_DTRACE_ILLOP) ? DTRACEFLT_ILLOP :		\
+	((flags) & CPU_DTRACE_DIVZERO) ? DTRACEFLT_DIVZERO :		\
+	((flags) & CPU_DTRACE_KPRIV) ? DTRACEFLT_KPRIV :		\
+	((flags) & CPU_DTRACE_UPRIV) ? DTRACEFLT_UPRIV :		\
+	((flags) & CPU_DTRACE_TUPOFLOW) ?  DTRACEFLT_TUPOFLOW :		\
+	((flags) & CPU_DTRACE_BADALIGN) ?  DTRACEFLT_BADALIGN :		\
+	((flags) & CPU_DTRACE_NOSCRATCH) ?  DTRACEFLT_NOSCRATCH :	\
+	DTRACEFLT_UNKNOWN)
+
+#define	DTRACEACT_ISSTRING(act)						\
+	((act)->dta_kind == DTRACEACT_DIFEXPR &&			\
+	(act)->dta_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING)
+
+static dtrace_probe_t *dtrace_probe_lookup_id(dtrace_id_t id);
+static void dtrace_enabling_provide(dtrace_provider_t *);
+static int dtrace_enabling_match(dtrace_enabling_t *, int *);
+static void dtrace_enabling_matchall(void);
+static dtrace_state_t *dtrace_anon_grab(void);
+static uint64_t dtrace_helper(int, dtrace_mstate_t *,
+    dtrace_state_t *, uint64_t, uint64_t);
+static dtrace_helpers_t *dtrace_helpers_create(proc_t *);
+static void dtrace_buffer_drop(dtrace_buffer_t *);
+static intptr_t dtrace_buffer_reserve(dtrace_buffer_t *, size_t, size_t,
+    dtrace_state_t *, dtrace_mstate_t *);
+static int dtrace_state_option(dtrace_state_t *, dtrace_optid_t,
+    dtrace_optval_t);
+static int dtrace_ecb_create_enable(dtrace_probe_t *, void *);
+#endif
 
+#include <cddl/dev/dtrace/cmn_err.c>
+#include <cddl/dev/dtrace/dtrace_badattr.c>
+#include <cddl/dev/dtrace/dtrace_badname.c>
 #include <cddl/dev/dtrace/dtrace_close.c>
 #include <cddl/dev/dtrace/dtrace_ioctl.c>
 #include <cddl/dev/dtrace/dtrace_load.c>
 #include <cddl/dev/dtrace/dtrace_modevent.c>
 #include <cddl/dev/dtrace/dtrace_open.c>
+#include <cddl/dev/dtrace/dtrace_register.c>
 #include <cddl/dev/dtrace/dtrace_sysctl.c>
 #include <cddl/dev/dtrace/dtrace_unload.c>
+#include <cddl/dev/dtrace/dtrace_unregister.c>
 
 DEV_MODULE(dtrace, dtrace_modevent, NULL);
 MODULE_VERSION(dtrace, 1);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604200122.k3K1M9TL093388>