changeset 3426:e69c0764a03e

6498304 too much CPU time winding up in LMS_WAIT_CPU
author johansen
date Tue, 16 Jan 2007 14:09:46 -0800
parents 69e10a2dd6f0
children fa42dcd66837
files usr/src/uts/common/disp/disp.c usr/src/uts/common/disp/shuttle.c usr/src/uts/common/os/msacct.c
diffstat 3 files changed, 77 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/disp/disp.c	Tue Jan 16 07:17:31 2007 -0800
+++ b/usr/src/uts/common/disp/disp.c	Tue Jan 16 14:09:46 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -626,7 +626,6 @@
 			if (t == T_DONTSTEAL)
 				continue;
 			idle_exit();
-			restore_mstate(t);
 			swtch_to(t);
 		}
 		idle_enter(); /* returned from swtch/swtch_to */
@@ -715,7 +714,6 @@
 		if (disp_ratify(tp, kpq) != NULL) {
 			TRACE_1(TR_FAC_DISP, TR_DISP_END,
 			    "disp_end:tid %p", tp);
-			restore_mstate(tp);
 			return (tp);
 		}
 	}
@@ -754,7 +752,6 @@
 		}
 		TRACE_1(TR_FAC_DISP, TR_DISP_END,
 			"disp_end:tid %p", tp);
-		restore_mstate(tp);
 		return (tp);
 	}
 
@@ -820,7 +817,6 @@
 	if (disp_ratify(tp, kpq) == NULL)
 		goto reschedule;
 
-	restore_mstate(tp);
 	return (tp);
 }
 
@@ -883,6 +879,22 @@
 				CHIP_NRUNNING(cp->cpu_chip, -1);
 			}
 
+			/*
+			 * If t was previously in the TS_ONPROC state,
+			 * setfrontdq and setbackdq won't have set its t_waitrq.
+			 * Since we now finally know that we're switching away
+			 * from this thread, set its t_waitrq if it is on a run
+			 * queue.
+			 */
+			if ((t->t_state == TS_RUN) && (t->t_waitrq == 0)) {
+				t->t_waitrq = gethrtime_unscaled();
+			}
+
+			/*
+			 * restore mstate of thread that we are switching to
+			 */
+			restore_mstate(next);
+
 			CPU_STATS_ADDQ(cp, sys, pswitch, 1);
 			cp->cpu_last_swtch = t->t_disp_time = lbolt;
 			TRACE_0(TR_FAC_DISP, TR_RESUME_START, "resume_start");
@@ -934,6 +946,8 @@
 	if (next == cpu->cpu_idle_thread)
 		CHIP_NRUNNING(cpu->cpu_chip, -1);
 
+	restore_mstate(next);
+
 	if (dtrace_vtime_active)
 		dtrace_vtime_switch(next);
 
@@ -1018,6 +1032,19 @@
 	/* record last execution time */
 	cp->cpu_last_swtch = curthread->t_disp_time = lbolt;
 
+	/*
+	 * If t was previously in the TS_ONPROC state, setfrontdq and setbackdq
+	 * won't have set its t_waitrq.  Since we now finally know that we're
+	 * switching away from this thread, set its t_waitrq if it is on a run
+	 * queue.
+	 */
+	if ((curthread->t_state == TS_RUN) && (curthread->t_waitrq == 0)) {
+		curthread->t_waitrq = gethrtime_unscaled();
+	}
+
+	/* restore next thread to previously running microstate */
+	restore_mstate(next);
+
 	if (dtrace_vtime_active)
 		dtrace_vtime_switch(next);
 
@@ -1161,17 +1188,6 @@
 
 	ASSERT(THREAD_LOCK_HELD(tp));
 	ASSERT((tp->t_schedflag & TS_ALLSTART) == 0);
-
-	if (tp->t_waitrq == 0) {
-		hrtime_t curtime;
-
-		curtime = gethrtime_unscaled();
-		(void) cpu_update_pct(tp, curtime);
-		tp->t_waitrq = curtime;
-	} else {
-		(void) cpu_update_pct(tp, gethrtime_unscaled());
-	}
-
 	ASSERT(!thread_on_queue(tp));	/* make sure tp isn't on a runq */
 
 	/*
@@ -1254,6 +1270,24 @@
 		    tp->t_weakbound_cpu : tp->t_bound_cpu;
 		bound = 1;
 	}
+	/*
+	 * A thread that is ONPROC may be temporarily placed on the run queue
+	 * but then chosen to run again by disp.  If the thread we're placing on
+	 * the queue is in TS_ONPROC state, don't set its t_waitrq until a
+	 * replacement process is actually scheduled in swtch().  In this
+	 * situation, curthread is the only thread that could be in the ONPROC
+	 * state.
+	 */
+	if ((tp != curthread) && (tp->t_waitrq == 0)) {
+		hrtime_t curtime;
+
+		curtime = gethrtime_unscaled();
+		(void) cpu_update_pct(tp, curtime);
+		tp->t_waitrq = curtime;
+	} else {
+		(void) cpu_update_pct(tp, gethrtime_unscaled());
+	}
+
 	dp = cp->cpu_disp;
 	disp_lock_enter_high(&dp->disp_lock);
 
@@ -1332,17 +1366,6 @@
 
 	ASSERT(THREAD_LOCK_HELD(tp));
 	ASSERT((tp->t_schedflag & TS_ALLSTART) == 0);
-
-	if (tp->t_waitrq == 0) {
-		hrtime_t curtime;
-
-		curtime = gethrtime_unscaled();
-		(void) cpu_update_pct(tp, curtime);
-		tp->t_waitrq = curtime;
-	} else {
-		(void) cpu_update_pct(tp, gethrtime_unscaled());
-	}
-
 	ASSERT(!thread_on_queue(tp));	/* make sure tp isn't on a runq */
 
 	/*
@@ -1396,6 +1419,25 @@
 		    tp->t_weakbound_cpu : tp->t_bound_cpu;
 		bound = 1;
 	}
+
+	/*
+	 * A thread that is ONPROC may be temporarily placed on the run queue
+	 * but then chosen to run again by disp.  If the thread we're placing on
+	 * the queue is in TS_ONPROC state, don't set its t_waitrq until a
+	 * replacement process is actually scheduled in swtch().  In this
+	 * situation, curthread is the only thread that could be in the ONPROC
+	 * state.
+	 */
+	if ((tp != curthread) && (tp->t_waitrq == 0)) {
+		hrtime_t curtime;
+
+		curtime = gethrtime_unscaled();
+		(void) cpu_update_pct(tp, curtime);
+		tp->t_waitrq = curtime;
+	} else {
+		(void) cpu_update_pct(tp, gethrtime_unscaled());
+	}
+
 	dp = cp->cpu_disp;
 	disp_lock_enter_high(&dp->disp_lock);
 
--- a/usr/src/uts/common/disp/shuttle.c	Tue Jan 16 07:17:31 2007 -0800
+++ b/usr/src/uts/common/disp/shuttle.c	Tue Jan 16 14:09:46 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -126,7 +125,6 @@
 	thread_lock_high(t);
 	oldtlp = t->t_lockp;
 
-	restore_mstate(t);
 	t->t_flag &= ~T_WAKEABLE;
 	t->t_wchan0 = NULL;
 	t->t_sobj_ops = NULL;
--- a/usr/src/uts/common/os/msacct.c	Tue Jan 16 07:17:31 2007 -0800
+++ b/usr/src/uts/common/os/msacct.c	Tue Jan 16 14:09:46 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -560,8 +559,6 @@
 	return (ms->ms_prev);
 }
 
-static long waitrqis0 = 0;
-
 /*
  * Restore the LWP microstate to the previous runnable state.
  * Called from disp() with the newly selected lwp.
@@ -625,11 +622,10 @@
 			break;
 		}
 		waitrq = t->t_waitrq;	/* hopefully atomic */
-		t->t_waitrq = 0;
-		if (waitrq == 0) {	/* should only happen during boot */
+		if (waitrq == 0) {
 			waitrq = curtime;
-			waitrqis0++;
 		}
+		t->t_waitrq = 0;
 		newtime = waitrq - ms->ms_state_start;
 		if (newtime < 0) {
 			curtime = gethrtime_unscaled();