svn commit: r318319 - head/sys/cddl/dev/profile
Mark Johnston
markj at FreeBSD.org
Mon May 15 21:44:41 UTC 2017
Author: markj
Date: Mon May 15 21:44:40 2017
New Revision: 318319
URL: https://svnweb.freebsd.org/changeset/base/318319
Log:
Ensure that profile and tick probes provide a non-zero PC value.
The idle thread may process callouts while reloading the timer in
cpu_activeclock(). In this case, provide a representative value, &cpu_idle,
instead of 0 for args[0] so that the active thread can be more easily
identified from the probe.
This addresses intermittent failures of the profile-n/tst.argtest.d test.
MFC after: 2 weeks
Sponsored by: Dell EMC Isilon
Differential Revision: https://reviews.freebsd.org/D10651
Modified:
head/sys/cddl/dev/profile/profile.c
Modified: head/sys/cddl/dev/profile/profile.c
==============================================================================
--- head/sys/cddl/dev/profile/profile.c Mon May 15 20:52:43 2017 (r318318)
+++ head/sys/cddl/dev/profile/profile.c Mon May 15 21:44:40 2017 (r318319)
@@ -266,37 +266,43 @@ sbt_to_nsec(sbintime_t sbt)
}
static void
-profile_fire(void *arg)
+profile_probe(profile_probe_t *prof, hrtime_t late)
{
- profile_probe_percpu_t *pcpu = arg;
- profile_probe_t *prof = pcpu->profc_probe;
- hrtime_t late;
+ struct thread *td;
struct trapframe *frame;
uintfptr_t pc, upc;
-#ifdef illumos
- late = gethrtime() - pcpu->profc_expected;
-#else
- late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected);
-#endif
-
- pc = 0;
- upc = 0;
+ td = curthread;
+ pc = upc = 0;
/*
- * td_intr_frame can be unset if this is a catch up event
- * after waking up from idle sleep.
- * This can only happen on a CPU idle thread.
+ * td_intr_frame can be unset if this is a catch-up event upon waking up
+ * from idle sleep. This can only happen on a CPU idle thread. Use a
+ * representative arg0 value in this case so that one of the probe
+ * arguments is non-zero.
*/
- frame = curthread->td_intr_frame;
+ frame = td->td_intr_frame;
if (frame != NULL) {
if (TRAPF_USERMODE(frame))
upc = TRAPF_PC(frame);
else
pc = TRAPF_PC(frame);
- }
+ } else if (TD_IS_IDLETHREAD(td))
+ pc = (uintfptr_t)&cpu_idle;
+
dtrace_probe(prof->prof_id, pc, upc, late, 0, 0);
+}
+static void
+profile_fire(void *arg)
+{
+ profile_probe_percpu_t *pcpu = arg;
+ profile_probe_t *prof = pcpu->profc_probe;
+ hrtime_t late;
+
+ late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected);
+
+ profile_probe(prof, late);
pcpu->profc_expected += pcpu->profc_interval;
callout_schedule_sbt_curcpu(&pcpu->profc_cyclic,
pcpu->profc_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE);
@@ -306,26 +312,8 @@ static void
profile_tick(void *arg)
{
profile_probe_t *prof = arg;
- struct trapframe *frame;
- uintfptr_t pc, upc;
-
- pc = 0;
- upc = 0;
-
- /*
- * td_intr_frame can be unset if this is a catch up event
- * after waking up from idle sleep.
- * This can only happen on a CPU idle thread.
- */
- frame = curthread->td_intr_frame;
- if (frame != NULL) {
- if (TRAPF_USERMODE(frame))
- upc = TRAPF_PC(frame);
- else
- pc = TRAPF_PC(frame);
- }
- dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0);
+ profile_probe(prof, 0);
prof->prof_expected += prof->prof_interval;
callout_schedule_sbt(&prof->prof_cyclic,
prof->prof_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE);
More information about the svn-src-head
mailing list