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>