From owner-freebsd-bugs@FreeBSD.ORG Fri Jan 18 18:40:03 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B4B9116A417 for ; Fri, 18 Jan 2008 18:40:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 912B513C469 for ; Fri, 18 Jan 2008 18:40:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m0IIe30e086026 for ; Fri, 18 Jan 2008 18:40:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m0IIe3xl086025; Fri, 18 Jan 2008 18:40:03 GMT (envelope-from gnats) Date: Fri, 18 Jan 2008 18:40:03 GMT Message-Id: <200801181840.m0IIe3xl086025@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: KOIE Hidetaka Cc: Subject: Re: bin/119589: powerd(8): default parameter of powerd is unsuitable for multi core system. X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: KOIE Hidetaka List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Jan 2008 18:40:03 -0000 The following reply was made to PR bin/119589; it has been noted by GNATS. From: KOIE Hidetaka To: bug-followup@FreeBSD.org, koie@suri.co.jp Cc: Subject: Re: bin/119589: powerd(8): default parameter of powerd is unsuitable for multi core system. Date: Sat, 19 Jan 2008 03:37:24 +0900 (JST) I write a patch: - If a cpu is busy, increase freq. - If all cpu is idle, decrease freq. --- powerd.c.orig 2008-01-15 12:13:03.130694451 +0900 +++ powerd.c 2008-01-19 03:21:27.279583449 +0900 @@ -50,6 +50,8 @@ __FBSDID("$FreeBSD: src/usr.sbin/powerd/ #include #endif +#define MAX_CPU 32 /*XXX*/ + #define DEFAULT_ACTIVE_PERCENT 65 #define DEFAULT_IDLE_PERCENT 90 #define DEFAULT_POLL_INTERVAL 500 /* Poll interval in milliseconds */ @@ -77,7 +79,7 @@ const char *modes[] = { #define DEVDPIPE "/var/run/devd.pipe" #define DEVCTL_MAXBUF 1024 -static int read_usage_times(long *idle, long *total); +static int read_usage_times(long idle[MAX_CPU], long total[MAX_CPU]); static int read_freqs(int *numfreqs, int **freqs, int **power); static int set_freq(int freq); static void acline_init(void); @@ -89,7 +91,8 @@ static void parse_mode(char *arg, int *m static void usage(void); /* Sysctl data structures. */ -static int cp_time_mib[2]; +static int numcpus; +static int cp_times_mib[2]; static int freq_mib[4]; static int levels_mib[4]; static int acline_mib[3]; @@ -119,27 +122,29 @@ static int devd_pipe = -1; static struct timeval tried_devd; static int -read_usage_times(long *idle, long *total) +read_usage_times(long idle[MAX_CPU], long total[MAX_CPU]) { - static long idle_old, total_old; - long cp_time[CPUSTATES], i, total_new; - size_t cp_time_len; + static long idle_old[MAX_CPU], total_old[MAX_CPU]; + int k; + long cp_times[MAX_CPU][CPUSTATES]; + size_t cp_times_len; int error; - cp_time_len = sizeof(cp_time); - error = sysctl(cp_time_mib, 2, cp_time, &cp_time_len, NULL, 0); + cp_times_len = sizeof(cp_times); + error = sysctl(cp_times_mib, 2, cp_times, &cp_times_len, NULL, 0); if (error) return (error); - for (total_new = 0, i = 0; i < CPUSTATES; i++) - total_new += cp_time[i]; - - if (idle) - *idle = cp_time[CP_IDLE] - idle_old; - if (total) - *total = total_new - total_old; - - idle_old = cp_time[CP_IDLE]; - total_old = total_new; + for (k = 0; k < numcpus; k++) { + double total_new = 0; + int i; + for (i = 0; i < CPUSTATES; i++) + total_new += cp_times[k][i]; + + idle[k] = cp_times[k][CP_IDLE] - idle_old[k]; + idle_old[k] = cp_times[k][CP_IDLE]; + total[k] = total_new - total_old[k]; + total_old[k] = total_new; + } return (0); } @@ -369,11 +374,13 @@ main(int argc, char * argv[]) int nfds; struct pidfh *pfh = NULL; const char *pidfile = NULL; - long idle, total; + long idle[MAX_CPU], total[MAX_CPU]; + int k; int curfreq, *freqs, i, *mwatts, numfreqs; int ch, mode, mode_ac, mode_battery, mode_none; uint64_t mjoules_used; size_t len; + int bumpup, dropdown; /* Default mode for all AC states is adaptive. */ mode_ac = mode_battery = mode_none = MODE_ADAPTIVE; @@ -425,7 +432,7 @@ main(int argc, char * argv[]) } break; case 'v': - vflag = 1; + vflag++; break; default: usage(); @@ -436,10 +443,19 @@ main(int argc, char * argv[]) /* Poll interval is in units of ms. */ poll_ival *= 1000; + /* How many CPU? */ + len = sizeof(numcpus); + if (sysctlbyname("hw.ncpu", &numcpus, &len, NULL, 0)) + err(1, "sysctl hw.ncpu"); + if (vflag) + printf("ncpu=%d\n", numcpus); + if (numcpus > MAX_CPU) + errc(1, 0, "too many CPU are loaded"); + /* Look up various sysctl MIBs. */ len = 2; - if (sysctlnametomib("kern.cp_time", cp_time_mib, &len)) - err(1, "lookup kern.cp_time"); + if (sysctlnametomib("kern.cp_times", cp_times_mib, &len)) + err(1, "lookup kern.cp_times"); len = 4; if (sysctlnametomib("dev.cpu.0.freq", freq_mib, &len)) err(1, "lookup freq"); @@ -448,7 +464,7 @@ main(int argc, char * argv[]) err(1, "lookup freq_levels"); /* Check if we can read the idle time and supported freqs. */ - if (read_usage_times(NULL, NULL)) + if (read_usage_times(idle, total)) err(1, "read_usage_times"); if (read_freqs(&numfreqs, &freqs, &mwatts)) err(1, "error reading supported CPU frequencies"); @@ -578,11 +594,18 @@ main(int argc, char * argv[]) } /* Adaptive mode; get the current CPU usage times. */ - if (read_usage_times(&idle, &total)) { + if (read_usage_times(idle, total)) { if (vflag) warn("read_usage_times() failed"); continue; } +#if 0 + printf("IDLE%%:"); + for (i = 0; i < numcpus; i++) { + printf(" %3ld", 100 * idle[i] / total[i]); + } + printf("\n"); +#endif /* * If we're idle less than the active mark, bump up two levels. @@ -592,8 +615,26 @@ main(int argc, char * argv[]) if (freqs[i] == curfreq) break; } - if (idle < (total * cpu_running_mark) / 100 && - curfreq < freqs[0]) { + bumpup = 0; + if (curfreq < freqs[0]) { + for (k = 0; k < numcpus; k++) { + if (idle[k] * 100 < total[k] * cpu_running_mark) { + bumpup = 1; + break; + } + } + } + dropdown = 0; + if (curfreq > freqs[numfreqs - 1]) { + dropdown = 1; + for (k = 0; k < numcpus; k++) { + if (idle[k] * 100 <= total[k] * cpu_idle_mark) { + dropdown = 0; + break; + } + } + } + if (bumpup) { i -= 2; if (i < 0) i = 0; @@ -605,8 +646,7 @@ main(int argc, char * argv[]) if (set_freq(freqs[i])) warn("error setting CPU frequency %d", freqs[i]); - } else if (idle > (total * cpu_idle_mark) / 100 && - curfreq > freqs[numfreqs - 1]) { + } else if (dropdown) { i++; if (vflag) { printf("idle time > %d%%, decreasing clock"