Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 May 2017 21:44:40 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r318319 - head/sys/cddl/dev/profile
Message-ID:  <201705152144.v4FLieu1046125@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



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