Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Jul 2006 19:51:51 +0100 (BST)
From:      Gareth McCaughan <gmccaughan@synaptics-uk.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/100683: syscons screen savers can eat up to 75% of CPU
Message-ID:  <20060721185151.0F67C22E26@dogbert.synaptics-uk.com>
Resent-Message-ID: <200607211900.k6LJ0W70064659@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         100683
>Category:       kern
>Synopsis:       syscons screen savers can eat up to 75% of CPU
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jul 21 19:00:31 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Gareth McCaughan
>Release:        FreeBSD 6.1-STABLE i386
>Organization:
International Pedant Conspiracy
>Environment:
	System: FreeBSD 6-STABLE as of 2006-07-21
>Description:
	The "fire", "logo", "rain" and "warp" syscons screen savers
	make many calls to set_origin on each update. On some systems
	each such call involves two very slow BIOS calls, which can
	result in lots of CPU time being wasted. (On one of my machines,
	the figure for "warp" is about 75%.) The most visible symptoms
	are a very slow-running machine, and a "ps" entry for a
	kernel ithread with a name like "[swi4: clock sio]" taking up
	a lot of cycles.
>How-To-Repeat:
	Have a machine on which the graphics card is handled using VESA VBE
	and int 10h 4f/05 (bank switch) is slow.
	Choose one of the savers listed above as your syscons screen saver,
	either by setting "saver" in rc.conf or by kldload-ing it. Wait for
	the screen saver to kick in. Observe, remotely, that everything
	runs slower and that the "clock sio" ithread is eating CPU.
>Fix:
	Apply the following patch (unidiff in /usr/src/sys/dev/syscons).
	It reduces the number of expensive set_origin calls in those
	savers by not bothering to make them when the origin isn't
	actually changing. It *doesn't* (1) make vesa_set_origin always
	perform this check or (2) monitor all syscons screen savers and
	take any sort of remedial action if they use too much CPU; #1
	might be worth doing instead, and #2 might be worth doing as well.

---------- patch begins ----------
diff -u -r fire.ORIG/fire_saver.c fire/fire_saver.c
--- fire.ORIG/fire_saver.c	Fri Jul 21 18:20:05 2006
+++ fire/fire_saver.c	Fri Jul 21 19:12:23 2006
@@ -52,6 +52,8 @@
 #define GREEN(n)	 ((n) * 3 + 1)
 #define BLUE(n)		 ((n) * 3 + 2)
 
+#define SET_ORIGIN(adp, o) do { int oo=o; if (oo != last_origin) set_origin(adp, last_origin=oo); } while (0)
+
 static u_char		*buf;
 static u_char		*vid;
 static int		 banksize, scrmode, bpsl, scrw, scrh;
@@ -63,6 +65,7 @@
 {
 	int x, y;
 	int o, p;
+	int last_origin = -1;
 
 	/* make a new bottom line */
 	for (x = 0, y = scrh; x < scrw; x++)
@@ -87,12 +90,12 @@
 			p -= banksize;
 			o += banksize;
 		}
-		set_origin(adp, o);
+		SET_ORIGIN(adp, o);
 		if (p + scrw < banksize) {
 			bcopy(buf + y * scrw, vid + p, scrw);
 		} else {
 			bcopy(buf + y * scrw, vid + p, banksize - p);
-			set_origin(adp, o + banksize);
+			SET_ORIGIN(adp, o + banksize);
 			bcopy(buf + y * scrw + (banksize - p), vid,
 			      scrw - (banksize - p));
 			p -= banksize;
diff -u -r logo.ORIG/logo_saver.c logo/logo_saver.c
--- logo.ORIG/logo_saver.c	Fri Jul 21 18:20:10 2006
+++ logo/logo_saver.c	Fri Jul 21 19:12:33 2006
@@ -42,6 +42,8 @@
 
 #define SAVER_NAME	 "logo_saver"
 
+#define SET_ORIGIN(adp, o) do { int oo=o; if (oo != last_origin) set_origin(adp, last_origin=oo); } while (0)
+
 extern unsigned int	 logo_w;
 extern unsigned int	 logo_h;
 extern unsigned char	 logo_pal[];
@@ -56,10 +58,11 @@
 logo_blit(video_adapter_t *adp, int x, int y)
 {
 	int d, l, o, p;
+	int last_origin = -1;
 	
 	for (o = 0, p = y * bpsl + x; p > banksize; p -= banksize)
 		o += banksize;
-	set_origin(adp, o);
+	SET_ORIGIN(adp, o);
 	
 	for (d = 0; d < logo_img_size; d += logo_w) {
 		if (p + logo_w < banksize) {
@@ -68,12 +71,12 @@
 		} else if (p < banksize) {
 			l = banksize - p;
 			bcopy(logo_img + d, vid + p, l);
-			set_origin(adp, (o += banksize));
+			SET_ORIGIN(adp, (o += banksize));
 			bcopy(logo_img + d + l, vid, logo_w - l);
 			p += bpsl - banksize;
 		} else {
 			p -= banksize;
-			set_origin(adp, (o += banksize));
+			SET_ORIGIN(adp, (o += banksize));
 			bcopy(logo_img + d, vid + p, logo_w);
 			p += bpsl;
 		}
diff -u -r rain.ORIG/rain_saver.c rain/rain_saver.c
--- rain.ORIG/rain_saver.c	Fri Jul 21 18:20:13 2006
+++ rain/rain_saver.c	Fri Jul 21 19:12:28 2006
@@ -51,6 +51,8 @@
 #define GREEN(n)	 ((n) * 3 + 1)
 #define BLUE(n)		 ((n) * 3 + 2)
 
+#define SET_ORIGIN(adp, o) do { int oo=o; if (oo != last_origin) set_origin(adp, last_origin=oo); } while (0)
+
 static u_char		*vid;
 static int		 banksize, scrmode, bpsl, scrw, scrh;
 static u_char		 rain_pal[768];
@@ -73,6 +75,7 @@
 {
 	int i, j, o, p, pl;
 	u_char temp;
+	int last_origin = -1;
 
 	if (blank) {
 		/* switch to graphics mode */
@@ -87,18 +90,18 @@
 			bpsl = adp->va_line_width;
 			splx(pl);
 			for (i = 0; i < bpsl*scrh; i += banksize) {
-				set_origin(adp, i);
+				SET_ORIGIN(adp, i);
 				if ((bpsl * scrh - i) < banksize)
 					bzero(vid, bpsl * scrh - i);
 				else
 					bzero(vid, banksize);
 			}
-			set_origin(adp, 0);
+			SET_ORIGIN(adp, 0);
 			for (i = 0, o = 0, p = 0; i < scrw; i += 2, p += 2) {
 				if (p > banksize) {
 					p -= banksize;
 					o += banksize;
-					set_origin(adp, o);
+					SET_ORIGIN(adp, o);
 				}
 				vid[p] = 1 + (random() % MAX);
 			}
@@ -109,12 +112,12 @@
 					p -= banksize;
 					o += banksize;
 				}
-				set_origin(adp, o);
+				SET_ORIGIN(adp, o);
 				temp = (vid[p] < MAX) ? 1 + vid[p] : 1;
 				if (p + bpsl < banksize) {
 					vid[p + bpsl] = temp;
 				} else {
-					set_origin(adp, o + banksize);
+					SET_ORIGIN(adp, o + banksize);
 					vid[p + bpsl - banksize] = temp;
 				}
 			  }
diff -u -r warp.ORIG/warp_saver.c warp/warp_saver.c
--- warp.ORIG/warp_saver.c	Fri Jul 21 18:20:17 2006
+++ warp/warp_saver.c	Fri Jul 21 19:12:17 2006
@@ -44,6 +44,8 @@
 #define SPP		 15
 #define STARS		 (SPP * (1 + 2 + 4 + 8))
 
+#define SET_ORIGIN(adp, o) do { int oo=o; if (oo != last_origin) set_origin(adp, last_origin=oo); } while (0)
+
 static u_char		*vid;
 static int		 banksize, scrmode, bpsl, scrw, scrh;
 static int		 blanked;
@@ -61,6 +63,7 @@
 warp_update(video_adapter_t *adp)
 {
 	int i, j, k, n, o, p;
+	int last_origin = -1;
 
 	for (i = 1, k = 0, n = SPP*8; i < 5; i++, n /= 2) {
 		for (j = 0; j < n; j++, k++) {
@@ -70,7 +73,7 @@
 				p -= banksize;
 				o += banksize;
 			}
-			set_origin(adp, o);
+			SET_ORIGIN(adp, o);
 			vid[p] = 0;
 			star[k] += i;
 			if (star[k] > scrw*scrh)
@@ -81,7 +84,7 @@
 				p -= banksize;
 				o += banksize;
 			}
-			set_origin(adp, o);
+			SET_ORIGIN(adp, o);
 			vid[p] = i;
 		}
 	}
---------- patch ends ----------
>Release-Note:
>Audit-Trail:
>Unformatted:



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