Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Sep 2007 17:05:57 -0700 (PDT)
From:      Jeff Roberson <jroberson@chesapeake.net>
To:        arch@freebsd.org
Subject:   Changing p_swtime and td_slptime to ticks
Message-ID:  <20070917165657.B558@10.0.0.1>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Enclosed is a patch that fixes swapping with ULE.  ULE has never properly 
set p_swtime and td_slptime which are used by the swapout/swapin code to 
select the appropriate thread to swap.

In 4BSD these two variables are increment once per-second as schedcpu() 
iterates over all threads.  ULE does not have a once per-second loop 
iterating over all threads.  So I have changed p_swtime to p_swtick and 
td_slptime to td_slptick.  These record the value of 'ticks' when the 
thread slept or was last swapped in or out.

For backwards compatibility I leave the values in kinfo_proc with the 
legacy meaning by subtracting from ticks and dividing by hz.  I perform a 
similar transformation in the swapout code to convert to seconds.  This 
change does make it possible to use sub-second granular decisions in the 
swap code, however I'm not sure if that's really necessary.

So that I did not disturb the 4BSD mechanism I kept the original 
td_slptime in the td_sched area.  It should be possible to use td_slptick 
directly but especially this close to release I did not want to change 
4BSD.

Feedback and testing welcome.

Thanks,
Jeff
[-- Attachment #2 --]
Index: lib/libkvm/kvm_proc.c
===================================================================
RCS file: /home/ncvs/src/lib/libkvm/kvm_proc.c,v
retrieving revision 1.93
diff -u -p -r1.93 kvm_proc.c
--- lib/libkvm/kvm_proc.c	17 Sep 2007 05:27:18 -0000	1.93
+++ lib/libkvm/kvm_proc.c	17 Sep 2007 05:58:09 -0000
@@ -85,6 +85,9 @@ __FBSDID("$FreeBSD: src/lib/libkvm/kvm_p
 #define KREAD(kd, addr, obj) \
 	(kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj))
 
+int ticks;
+int hz;
+
 /*
  * Read proc's from memory file into buffer bp, which has space to hold
  * at most maxcnt procs.
@@ -368,7 +371,7 @@ nopgrp:
 		kp->ki_acflag = proc.p_acflag;
 		kp->ki_lock = proc.p_lock;
 		if (proc.p_state != PRS_ZOMBIE) {
-			kp->ki_swtime = proc.p_swtime;
+			kp->ki_swtime = (ticks - proc.p_swtick) / hz;
 			kp->ki_flag = proc.p_flag;
 			kp->ki_sflag = 0;
 			kp->ki_nice = proc.p_nice;
@@ -535,12 +538,14 @@ kvm_getprocs(kd, op, arg, cnt)
 liveout:
 		nprocs = size == 0 ? 0 : size / kd->procbase->ki_structsize;
 	} else {
-		struct nlist nl[4], *p;
+		struct nlist nl[6], *p;
 
 		nl[0].n_name = "_nprocs";
 		nl[1].n_name = "_allproc";
 		nl[2].n_name = "_zombproc";
-		nl[3].n_name = 0;
+		nl[3].n_name = "_ticks";
+		nl[4].n_name = "_hz";
+		nl[5].n_name = 0;
 
 		if (kvm_nlist(kd, nl) != 0) {
 			for (p = nl; p->n_type != 0; ++p)
@@ -553,6 +558,14 @@ liveout:
 			_kvm_err(kd, kd->program, "can't read nprocs");
 			return (0);
 		}
+		if (KREAD(kd, nl[3].n_value, &ticks)) {
+			_kvm_err(kd, kd->program, "can't read ticks");
+			return (0);
+		}
+		if (KREAD(kd, nl[4].n_value, &hz)) {
+			_kvm_err(kd, kd->program, "can't read hz");
+			return (0);
+		}
 		size = nprocs * sizeof(struct kinfo_proc);
 		kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
 		if (kd->procbase == 0)
Index: sys/kern/kern_fork.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.281
diff -u -p -r1.281 kern_fork.c
--- sys/kern/kern_fork.c	17 Sep 2007 05:27:20 -0000	1.281
+++ sys/kern/kern_fork.c	17 Sep 2007 05:48:53 -0000
@@ -500,6 +500,7 @@ again:
 	 * Increase reference counts on shared objects.
 	 */
 	p2->p_flag = P_INMEM;
+	p2->p_swtick = ticks;
 	if (p1->p_flag & P_PROFIL)
 		startprofclock(p2);
 	td2->td_ucred = crhold(p2->p_ucred);
Index: sys/kern/kern_proc.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.251
diff -u -p -r1.251 kern_proc.c
--- sys/kern/kern_proc.c	17 Sep 2007 05:27:20 -0000	1.251
+++ sys/kern/kern_proc.c	17 Sep 2007 06:03:21 -0000
@@ -694,7 +694,8 @@ fill_kinfo_proc_only(struct proc *p, str
 		kp->ki_sflag = PS_INMEM;
 	else
 		kp->ki_sflag = 0;
-	kp->ki_swtime = p->p_swtime;
+	/* Calculate legacy swtime as seconds since 'swtick'. */
+	kp->ki_swtime = (ticks - p->p_swtick) / hz;
 	kp->ki_pid = p->p_pid;
 	kp->ki_nice = p->p_nice;
 	rufetch(p, &kp->ki_rusage);
@@ -812,7 +813,7 @@ fill_kinfo_thread(struct thread *td, str
 	kp->ki_kstack = (void *)td->td_kstack;
 	kp->ki_pctcpu = sched_pctcpu(td);
 	kp->ki_estcpu = td->td_estcpu;
-	kp->ki_slptime = td->td_slptime;
+	kp->ki_slptime = (ticks - td->td_slptick) / hz;
 	kp->ki_pri.pri_class = td->td_pri_class;
 	kp->ki_pri.pri_user = td->td_user_pri;
 
Index: sys/kern/kern_thread.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_thread.c,v
retrieving revision 1.253
diff -u -p -r1.253 kern_thread.c
--- sys/kern/kern_thread.c	17 Sep 2007 05:27:20 -0000	1.253
+++ sys/kern/kern_thread.c	17 Sep 2007 23:56:45 -0000
@@ -852,6 +852,7 @@ thread_suspend_switch(struct thread *td)
 	p->p_suspcount++;
 	PROC_UNLOCK(p);
 	thread_lock(td);
+	sched_sleep(td);
 	TD_SET_SUSPENDED(td);
 	PROC_SUNLOCK(p);
 	DROP_GIANT();
@@ -871,6 +872,7 @@ thread_suspend_one(struct thread *td)
 	THREAD_LOCK_ASSERT(td, MA_OWNED);
 	KASSERT(!TD_IS_SUSPENDED(td), ("already suspended"));
 	p->p_suspcount++;
+	sched_sleep(td);
 	TD_SET_SUSPENDED(td);
 }
 
Index: sys/kern/sched_4bsd.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sched_4bsd.c,v
retrieving revision 1.104
diff -u -p -r1.104 sched_4bsd.c
--- sys/kern/sched_4bsd.c	17 Sep 2007 05:27:20 -0000	1.104
+++ sys/kern/sched_4bsd.c	17 Sep 2007 06:06:39 -0000
@@ -84,6 +84,7 @@ struct td_sched {
 	fixpt_t		ts_pctcpu;	/* (j) %cpu during p_swtime. */
 	u_char		ts_rqindex;	/* (j) Run queue index. */
 	int		ts_cpticks;	/* (j) Ticks of cpu time. */
+	int		ts_slptime;	/* (j) Seconds !RUNNING. */
 	struct runq	*ts_runq;	/* runq the thread is currently on */
 };
 
@@ -379,11 +380,6 @@ schedcpu(void)
 	sx_slock(&allproc_lock);
 	FOREACH_PROC_IN_SYSTEM(p) {
 		PROC_SLOCK(p);
-		/*
-		 * Increment time in/out of memory.  We ignore overflow; with
-		 * 16-bit int's (remember them?) overflow takes 45 days.
-		 */
-		p->p_swtime++;
 		FOREACH_THREAD_IN_PROC(p, td) { 
 			awake = 0;
 			thread_lock(td);
@@ -440,7 +436,7 @@ XXX  this is broken
 
 			 */
 			if (awake) {
-				if (td->td_slptime > 1) {
+				if (ts->ts_slptime > 1) {
 					/*
 					 * In an ideal world, this should not
 					 * happen, because whoever woke us
@@ -452,10 +448,10 @@ XXX  this is broken
 					 */
 					updatepri(td);
 				}
-				td->td_slptime = 0;
+				ts->ts_slptime = 0;
 			} else
-				td->td_slptime++;
-			if (td->td_slptime > 1) {
+				ts->ts_slptime++;
+			if (ts->ts_slptime > 1) {
 				thread_unlock(td);
 				continue;
 			}
@@ -490,16 +486,18 @@ schedcpu_thread(void)
 static void
 updatepri(struct thread *td)
 {
-	register fixpt_t loadfac;
-	register unsigned int newcpu;
+	struct td_sched *ts;
+	fixpt_t loadfac;
+	unsigned int newcpu;
 
+	ts = td->td_sched;
 	loadfac = loadfactor(averunnable.ldavg[0]);
-	if (td->td_slptime > 5 * loadfac)
+	if (ts->ts_slptime > 5 * loadfac)
 		td->td_estcpu = 0;
 	else {
 		newcpu = td->td_estcpu;
-		td->td_slptime--;	/* was incremented in schedcpu() */
-		while (newcpu && --td->td_slptime)
+		ts->ts_slptime--;	/* was incremented in schedcpu() */
+		while (newcpu && --ts->ts_slptime)
 			newcpu = decay_cpu(loadfac, newcpu);
 		td->td_estcpu = newcpu;
 	}
@@ -827,7 +825,8 @@ sched_sleep(struct thread *td)
 {
 
 	THREAD_LOCK_ASSERT(td, MA_OWNED);
-	td->td_slptime = 0;
+	td->td_slptick = ticks;
+	td->td_sched->ts_slptime = 0;
 }
 
 void
@@ -939,12 +938,16 @@ sched_switch(struct thread *td, struct t
 void
 sched_wakeup(struct thread *td)
 {
+	struct td_sched *ts;
+
 	THREAD_LOCK_ASSERT(td, MA_OWNED);
-	if (td->td_slptime > 1) {
+	ts = td->td_sched;
+	if (ts->ts_slptime > 1) {
 		updatepri(td);
 		resetpriority(td);
 	}
-	td->td_slptime = 0;
+	td->td_slptick = ticks;
+	ts->ts_slptime = 0;
 	sched_add(td, SRQ_BORING);
 }
 
Index: sys/kern/sched_ule.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sched_ule.c,v
retrieving revision 1.206
diff -u -p -r1.206 sched_ule.c
--- sys/kern/sched_ule.c	17 Sep 2007 05:27:20 -0000	1.206
+++ sys/kern/sched_ule.c	17 Sep 2007 06:07:30 -0000
@@ -88,7 +88,6 @@ struct td_sched {	
 	short		ts_flags;	/* TSF_* flags. */
 	u_char		ts_rqindex;	/* Run queue index. */
 	u_char		ts_cpu;		/* CPU that we have affinity for. */
-	int		ts_slptick;	/* Tick when we went to sleep. */
 	int		ts_slice;	/* Ticks of slice remaining. */
 	u_int		ts_slptime;	/* Number of ticks we vol. slept */
 	u_int		ts_runtime;	/* Number of ticks we were running */
@@ -1914,7 +1913,7 @@ sched_sleep(struct thread *td)
 
 	THREAD_LOCK_ASSERT(td, MA_OWNED);
 
-	td->td_sched->ts_slptick = ticks;
+	td->td_slptick = ticks;
 }
 
 /*
@@ -1933,8 +1932,8 @@ sched_wakeup(struct thread *td)
 	 * If we slept for more than a tick update our interactivity and
 	 * priority.
 	 */
-	slptick = ts->ts_slptick;
-	ts->ts_slptick = 0;
+	slptick = td->td_slptick;
+	td->td_slptick = 0;
 	if (slptick && slptick != ticks) {
 		u_int hzticks;
 
@@ -2435,7 +2434,6 @@ sched_pctcpu(struct thread *td)
 		rtick = min(SCHED_TICK_HZ(ts) / SCHED_TICK_SECS, hz);
 		pctcpu = (FSCALE * ((FSCALE * rtick)/hz)) >> FSHIFT;
 	}
-	td->td_proc->p_swtime = ts->ts_ltick - ts->ts_ftick;
 	thread_unlock(td);
 
 	return (pctcpu);
Index: sys/sys/proc.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/proc.h,v
retrieving revision 1.490
diff -u -p -r1.490 proc.h
--- sys/sys/proc.h	17 Sep 2007 05:27:21 -0000	1.490
+++ sys/sys/proc.h	17 Sep 2007 06:00:50 -0000
@@ -242,7 +242,7 @@ struct thread {
 	struct thread	*td_standin;	/* (k + a) Use this for an upcall. */
 	struct kse_upcall *td_upcall;	/* (k + t) Upcall structure. */
 	u_int		td_estcpu;	/* (t) estimated cpu utilization */
-	u_int		td_slptime;	/* (t) How long completely blocked. */
+	u_int		td_slptick;	/* (t) Time at sleep. */
 	struct rusage	td_ru;		/* (t) rusage information */
 	uint64_t	td_runtime;	/* (t) How many cpu ticks we've run. */
 	u_int 		td_pticks;	/* (t) Statclock hits for profiling */
@@ -520,7 +520,7 @@ struct proc {
 #define	p_startzero	p_oppid
 	pid_t		p_oppid;	/* (c + e) Save ppid in ptrace. XXX */
 	struct vmspace	*p_vmspace;	/* (b) Address space. */
-	u_int		p_swtime;	/* (j) Time swapped in or out. */
+	u_int		p_swtick;	/* (j) Tick when swapped in or out. */
 	struct itimerval p_realtimer;	/* (c) Alarm timer. */
 	struct rusage	p_ru;		/* (a) Exit information. */
 	struct rusage_ext p_rux;	/* (cj) Internal resource usage. */
Index: sys/vm/vm_glue.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vm_glue.c,v
retrieving revision 1.224
diff -u -p -r1.224 vm_glue.c
--- sys/vm/vm_glue.c	17 Sep 2007 05:27:21 -0000	1.224
+++ sys/vm/vm_glue.c	17 Sep 2007 06:05:07 -0000
@@ -636,7 +636,7 @@ faultin(p)
 		PROC_LOCK(p);
 		PROC_SLOCK(p);
 		swapclear(p);
-		p->p_swtime = 0;
+		p->p_swtick = ticks;
 		PROC_SUNLOCK(p);
 
 		wakeup(&p->p_flag);
@@ -663,9 +663,11 @@ scheduler(dummy)
 {
 	struct proc *p;
 	struct thread *td;
-	int pri;
 	struct proc *pp;
+	int slptime;
+	int swtime;
 	int ppri;
+	int pri;
 
 	mtx_assert(&Giant, MA_OWNED | MA_NOTRECURSED);
 	mtx_unlock(&Giant);
@@ -688,6 +690,7 @@ loop:
 			PROC_UNLOCK(p);
 			continue;
 		}
+		swtime = (ticks - p->p_swtick) / hz;
 		PROC_SLOCK(p);
 		FOREACH_THREAD_IN_PROC(p, td) {
 			/*
@@ -697,7 +700,8 @@ loop:
 			 */
 			thread_lock(td);
 			if (td->td_inhibitors == TDI_SWAPPED) {
-				pri = p->p_swtime + td->td_slptime;
+				slptime = (ticks - td->td_slptick) / hz;
+				pri = swtime + slptime;
 				if ((td->td_flags & TDF_SWAPINREQ) == 0)
 					pri -= p->p_nice * 8;
 				/*
@@ -816,6 +820,7 @@ retry:
 	FOREACH_PROC_IN_SYSTEM(p) {
 		struct vmspace *vm;
 		int minslptime = 100000;
+		int slptime;
 		
 		/*
 		 * Watch out for a process in
@@ -882,12 +887,12 @@ retry:
 					thread_unlock(td);
 					goto nextproc;
 				}
-
+				slptime = (ticks - td->td_slptick) / hz;
 				/*
 				 * Guarantee swap_idle_threshold1
 				 * time in memory.
 				 */
-				if (td->td_slptime < swap_idle_threshold1) {
+				if (slptime < swap_idle_threshold1) {
 					thread_unlock(td);
 					goto nextproc;
 				}
@@ -914,13 +919,13 @@ retry:
 				 */
 				if (((action & VM_SWAP_NORMAL) == 0) &&
 				    (((action & VM_SWAP_IDLE) == 0) ||
-				    (td->td_slptime < swap_idle_threshold2))) {
+				    (slptime < swap_idle_threshold2))) {
 					thread_unlock(td);
 					goto nextproc;
 				}
 
-				if (minslptime > td->td_slptime)
-					minslptime = td->td_slptime;
+				if (minslptime > slptime)
+					minslptime = slptime;
 				thread_unlock(td);
 			}
 
@@ -1038,7 +1043,7 @@ swapout(p)
 	PROC_LOCK(p);
 	p->p_flag &= ~P_SWAPPINGOUT;
 	PROC_SLOCK(p);
-	p->p_swtime = 0;
+	p->p_swtick = ticks;
 	return (0);
 }
 #endif /* !NO_SWAPPING */
help

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