Assert that dtrace_probe() doesn't re-enter itself.
This helps catch cases where an instrumented function is called while in probe context. Submitted by: Domagoj Stolfa <domagoj.stolfa@gmail.com> MFC after: 2 weeks Sponsored by: DARPA/AFRL Differential Revision: https://reviews.freebsd.org/D14863
This commit is contained in:
parent
97c2ab4351
commit
59b1fdfb3d
@ -7256,6 +7256,44 @@ dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
|
||||
*valoffsp = valoffs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables interrupts and sets the per-thread inprobe flag. When DEBUG is
|
||||
* defined, we also assert that we are not recursing unless the probe ID is an
|
||||
* error probe.
|
||||
*/
|
||||
static dtrace_icookie_t
|
||||
dtrace_probe_enter(dtrace_id_t id)
|
||||
{
|
||||
dtrace_icookie_t cookie;
|
||||
|
||||
cookie = dtrace_interrupt_disable();
|
||||
|
||||
/*
|
||||
* Unless this is an ERROR probe, we are not allowed to recurse in
|
||||
* dtrace_probe(). Recursing into DTrace probe usually means that a
|
||||
* function is instrumented that should not have been instrumented or
|
||||
* that the ordering guarantee of the records will be violated,
|
||||
* resulting in unexpected output. If there is an exception to this
|
||||
* assertion, a new case should be added.
|
||||
*/
|
||||
ASSERT(curthread->t_dtrace_inprobe == 0 ||
|
||||
id == dtrace_probeid_error);
|
||||
curthread->t_dtrace_inprobe = 1;
|
||||
|
||||
return (cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables interrupts and clears the per-thread inprobe flag.
|
||||
*/
|
||||
static void
|
||||
dtrace_probe_exit(dtrace_icookie_t cookie)
|
||||
{
|
||||
|
||||
curthread->t_dtrace_inprobe = 0;
|
||||
dtrace_interrupt_enable(cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
* If you're looking for the epicenter of DTrace, you just found it. This
|
||||
* is the function called by the provider to fire a probe -- from which all
|
||||
@ -7290,7 +7328,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
||||
return;
|
||||
#endif
|
||||
|
||||
cookie = dtrace_interrupt_disable();
|
||||
cookie = dtrace_probe_enter(id);
|
||||
probe = dtrace_probes[id - 1];
|
||||
cpuid = curcpu;
|
||||
onintr = CPU_ON_INTR(CPU);
|
||||
@ -7301,7 +7339,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
||||
* We have hit in the predicate cache; we know that
|
||||
* this predicate would evaluate to be false.
|
||||
*/
|
||||
dtrace_interrupt_enable(cookie);
|
||||
dtrace_probe_exit(cookie);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7313,7 +7351,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
||||
/*
|
||||
* We don't trace anything if we're panicking.
|
||||
*/
|
||||
dtrace_interrupt_enable(cookie);
|
||||
dtrace_probe_exit(cookie);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7939,7 +7977,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
||||
if (vtime)
|
||||
curthread->t_dtrace_start = dtrace_gethrtime();
|
||||
|
||||
dtrace_interrupt_enable(cookie);
|
||||
dtrace_probe_exit(cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -46,6 +46,7 @@ typedef struct kdtrace_proc {
|
||||
typedef struct kdtrace_thread {
|
||||
u_int8_t td_dtrace_stop; /* Indicates a DTrace-desired stop */
|
||||
u_int8_t td_dtrace_sig; /* Signal sent via DTrace's raise() */
|
||||
u_int8_t td_dtrace_inprobe; /* Are we in a probe? */
|
||||
u_int td_predcache; /* DTrace predicate cache */
|
||||
u_int64_t td_dtrace_vtime; /* DTrace virtual time */
|
||||
u_int64_t td_dtrace_start; /* DTrace slice start time */
|
||||
@ -97,6 +98,7 @@ typedef struct kdtrace_thread {
|
||||
#define t_dtrace_start td_dtrace->td_dtrace_start
|
||||
#define t_dtrace_stop td_dtrace->td_dtrace_stop
|
||||
#define t_dtrace_sig td_dtrace->td_dtrace_sig
|
||||
#define t_dtrace_inprobe td_dtrace->td_dtrace_inprobe
|
||||
#define t_predcache td_dtrace->td_predcache
|
||||
#define t_dtrace_ft td_dtrace->td_dtrace_ft
|
||||
#define t_dtrace_on td_dtrace->td_dtrace_on
|
||||
|
Loading…
x
Reference in New Issue
Block a user