Subject: w cmd on energy saving machines: problem and proposed solution
To: None <tech-userlevel@netbsd.org>
From: Ignatios Souvatzis <is@netbsd.org>
List: tech-userlevel
Date: 06/15/2001 22:28:52
Hi,

w(1) on one of my systems shows:

marie w !% w
 9:57PM  up 7 days, 46 mins, 2 users, load averages: 0.07, 0.14, 0.15
USER TTY FROM              LOGIN@  IDLE WHAT
is    p1 jocelyn.sub-etha  8:08PM  199days w 
is    p2 jocelyn.sub-etha  9:03PM  199days -csh 


I investigated, and noticed that 

- /dev is mounted noatime (I want to make the disk spin down when unused, and
  I was told to set noatime for this)

- w uses current time minus the tty's access time as the idle time.

However, at the time the internally used idle time is used in any way, 
the sleep time of the process is already known to w. Therefore, I propose 
to use that instead:

--- w.c.original	Fri Jun 15 21:40:38 2001
+++ w.c	Fri Jun 15 22:18:40 2001
@@ -232,8 +232,7 @@
 			size = sizeof(dev_t);
 			(void) sysctl(mib, 2, &ep->tdev, &size, NULL, 0);
 		}
-		if ((ep->idle = now - stp->st_atime) < 0)
-			ep->idle = 0;
+		ep->idle = 0;
 	}
 	if (ut)
 		(void)fclose(ut);
@@ -265,6 +264,7 @@
 				 */
 				if (proc_compare(ep->kp, kp)) {
 					ep->kp = kp;
+					ep->idle = kp->p_slptime;
 					lognamelen = max(lognamelen,
 					    strlen(kp->p_login));
 				}
@@ -277,6 +277,7 @@
 			else if (ep->tdev == 0 && kp->p_tdev == NODEV
 				 && ep->ftpd_pid == kp->p_pid) {
 				ep->kp = kp;
+				ep->idle = kp->p_slptime;
 				lognamelen = max(lognamelen,
 					    strlen(kp->p_login));
 			}


marie w !% obj/w
10:18PM  up 7 days,  1:07, 2 users, load averages: 0.12, 0.13, 0.10
USER TTY FROM              LOGIN@  IDLE WHAT
is    p1 jocelyn.sub-etha  8:08PM     0 obj/w 
is    p2 jocelyn.sub-etha  9:03PM    49 -csh 


Note that now processes that use cpu time, but do not a-ccess the tty,
are not counted as idle, contrary to the old behaviour. One example is
tail -f on files that don't change. If we really care, the code could be 
changed like this:

--- w.c.original	Fri Jun 15 21:40:38 2001
+++ w.c	Fri Jun 15 22:13:47 2001
@@ -234,6 +234,8 @@
 		}
 		if ((ep->idle = now - stp->st_atime) < 0)
 			ep->idle = 0;
+		else if (stp->st_atime < ep->utmp.ut_time)
+			ep->idle = -1;
 	}
 	if (ut)
 		(void)fclose(ut);
@@ -265,6 +267,8 @@
 				 */
 				if (proc_compare(ep->kp, kp)) {
 					ep->kp = kp;
+					if (ep->idle < 0)
+						ep->idle = kp->p_slptime;
 					lognamelen = max(lognamelen,
 					    strlen(kp->p_login));
 				}
@@ -277,6 +281,8 @@
 			else if (ep->tdev == 0 && kp->p_tdev == NODEV
 				 && ep->ftpd_pid == kp->p_pid) {
 				ep->kp = kp;
+				if (ep->idle < 0)
+					ep->idle = kp->p_slptime;
 				lognamelen = max(lognamelen,
 					    strlen(kp->p_login));
 			}

to only use sleep time when the tty access time is unreasonable.

Thoughts?

Appendix: finger (actually fingerd) shows the same problem, because the
same definition of idle time is used. Best we can do here is to clip the
idle time to the login time. (Else we'd have to make it a kmem groveler, too.)

Thoughts here?

Regards,

	-is