PSARC/2009/086 PowerTOP --cpu option
6781152 PowerTOP should be able to report statistics for a specific CPU
6781149 PowerTOP should identify function names when reporting xcalls
6776103 typo in powertop/battery.c battery_stat_snapsho()
6790804 PowerTOP needlessly reports past, zero'ed events
6781580 PowerTOP has global variables declared in header file
6804434 PowerTOP displays the wrong name for idle/freq transitions on sparc
--- a/usr/src/cmd/powertop/Makefile Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/Makefile Fri Apr 10 11:48:42 2009 -0700
@@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# cmd/powertop/Makefile
@@ -28,8 +28,8 @@
include ../Makefile.cmd
-$(64ONLY)SUBDIRS= $(MACH)
-$(BUILD64)SUBDIRS += $(MACH64)
+$(64ONLY)SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
all := TARGET = all
install := TARGET = install
@@ -39,9 +39,7 @@
.KEEP_STATE:
-all: $(SUBDIRS)
-
-clean clobber lint: $(SUBDIRS)
+all clean clobber lint: $(SUBDIRS)
install: $(SUBDIRS)
-$(RM) $(ROOTPROG)
--- a/usr/src/cmd/powertop/Makefile.com Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/Makefile.com Fri Apr 10 11:48:42 2009 -0700
@@ -23,34 +23,36 @@
#
PROG = powertop
-OBJS = $(PROG).o display.o battery.o cpufreq.o cpuidle.o events.o util.o suggestions.o turbo.o
-SRCS = $(OBJS:%.o=../%.c)
+
+COMMON_OBJS = $(PROG).o \
+ display.o \
+ battery.o \
+ cpufreq.o \
+ cpuidle.o \
+ events.o \
+ util.o \
+ suggestions.o \
+ turbo.o
+
+SRCS = $(COMMON_OBJS:%.o=../common/%.c)
include ../../Makefile.cmd
-
-CFLAGS += $(CCVERBOSE)
-CFLAGS64 += $(CCVERBOSE)
-
-LDLIBS += -lcurses -ldtrace -lkstat
-
-FILEMODE = 0555
-GROUP = bin
-
-CLEANFILES += $(OBJS)
-
.KEEP_STATE:
-all: $(PROG)
+CFLAGS += $(CCVERBOSE)
+CFLAGS64 += $(CCVERBOSE)
+LDLIBS += -lcurses -ldtrace -lkstat
-$(PROG): $(OBJS)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
- $(POST_PROCESS)
+FILEMODE = 0555
+GROUP = bin
+
+CLEANFILES += $(COMMON_OBJS)
+
+all: $(PROG)
+
clean:
$(RM) $(CLEANFILES)
lint: lint_SRCS
-%.o: ../%.c
- $(COMPILE.c) $<
-
include ../../Makefile.targ
--- a/usr/src/cmd/powertop/amd64/Makefile Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/amd64/Makefile Fri Apr 10 11:48:42 2009 -0700
@@ -18,11 +18,27 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
include ../Makefile.com
include ../../Makefile.cmd.64
+MACH_OBJS = pt_amd64.o
+SRCS += $(MACH_OBJS:%.o=%.c)
+
+.KEEP_STATE:
+
+CLEANFILES += $(MACH_OBJS)
+
+all: $(PROG)
+
+$(PROG): $(MACH_OBJS) $(COMMON_OBJS)
+ $(LINK.c) -o $@ $(MACH_OBJS) $(COMMON_OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+
install: all $(ROOTPROG64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/amd64/pt_amd64.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+/*
+ * DTrace scripts for observing interrupts, callouts and cyclic events
+ * that cause CPU activity. Such activity prevents the processor from
+ * entering lower power states and reducing power consumption.
+ *
+ * g_dtp_events is the default script
+ */
+const char *g_dtp_events =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+" self->xc_func = 0;"
+"}";
+
+/*
+ * g_dtp_events_v is enabled through the -v option, it includes cyclic events
+ * in the report, allowing a complete view of system activity
+ */
+const char *g_dtp_events_v =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+" self->xc_func = 0;"
+"}";
+
+/*
+ * This script is selected through the -c option, it takes the CPU id as
+ * argument and observes activity generated by that CPU
+ */
+const char *g_dtp_events_c =
+"interrupt-complete"
+"/cpu == $0 &&"
+" arg0 != NULL && arg3 != 0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/cpu == $0 &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu == $0/"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" cpu == $0/"
+"{"
+" @events_x[execname, self->xc_func] = count();"
+"}"
+""
+"fbt::xc_common:return"
+"/cpu == $0 &&"
+" self->xc_func/"
+"{"
+" self->xc_func = 0;"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu != $0/"
+"{"
+" self->xc_func = arg0;"
+" self->xc_cpu = cpu;"
+"}"
+""
+"fbt::send_dirint:entry"
+"/pid != $pid &&"
+" self->xc_func &&"
+" arg0 == $0/"
+"{"
+" @events_xc[execname, self->xc_func, self->xc_cpu] = count();"
+" self->xc_func = 0;"
+" self->xc_cpu = 0;"
+"}";
+
+/*
+ * amd64 platform specific display messages
+ */
+const char *g_msg_idle_state = "C-states (idle power states)";
+const char *g_msg_freq_state = "P-states (frequencies)";
--- a/usr/src/cmd/powertop/battery.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <string.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-typedef struct battery_state {
- uint32_t exist;
- uint32_t power_unit;
- uint32_t bst_state;
- double present_rate;
- double remain_cap;
- double last_cap;
-} battery_state_t;
-
-battery_state_t battery;
-
-static int battery_stat_snapshot(void);
-
-#define mW2W(value) ((value) / 1000)
-
-void
-print_battery(void)
-{
- int err;
-
- (void) memset(&battery, 0, sizeof (battery_state_t));
-
- /*
- * The return value of battery_stat_snapsho() can be used for
- * debug or to show/hide the acpi power line. We currently don't
- * make the distinction of a system that runs only on AC and one
- * that runs on battery but has no kstat battery info.
- *
- * We still display the estimate power usage for systems
- * running on AC with a fully charged battery because some
- * batteries may still consume power.
- *
- * If battery_mod_lookup() didn't find a kstat battery module, don't
- * bother trying to take the snapshot
- */
- if (kstat_batt_idx > 0) {
- if ((err = battery_stat_snapshot()) < 0)
- pt_error("%s : battery kstat not found %d\n", __FILE__,
- err);
- }
-
- show_acpi_power_line(battery.exist, battery.present_rate,
- battery.remain_cap, battery.last_cap, battery.bst_state);
-}
-
-static int
-battery_stat_snapshot(void)
-{
- kstat_ctl_t *kc;
- kstat_t *ksp;
- kstat_named_t *knp;
-
- kc = kstat_open();
-
- /*
- * power unit:
- * 0 - Capacity information is reported in [mWh] and
- * charge/discharge rate information in [mW]
- * 1 - Capacity information is reported in [mAh] and
- * charge/discharge rate information in [mA].
- */
- ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
- "battery BIF0");
-
- if (ksp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- (void) kstat_read(kc, ksp, NULL);
- knp = kstat_data_lookup(ksp, "bif_unit");
-
- if (knp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- battery.power_unit = knp->value.ui32;
-
- /*
- * Present rate:
- * the power or current being supplied or accepted
- * through the battery's terminal
- */
- ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
- "battery BST0");
-
- if (ksp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- (void) kstat_read(kc, ksp, NULL);
- knp = kstat_data_lookup(ksp, "bst_rate");
-
- if (knp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- if (knp->value.ui32 == 0xFFFFFFFF)
- battery.present_rate = 0;
- else {
- battery.exist = 1;
- battery.present_rate = mW2W((double)(knp->value.ui32));
- }
-
- /*
- * Last Full charge capacity:
- * Predicted battery capacity when fully charged.
- */
- ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
- "battery BIF0");
-
- if (ksp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- (void) kstat_read(kc, ksp, NULL);
- knp = kstat_data_lookup(ksp, "bif_last_cap");
-
- if (knp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- battery.last_cap = mW2W((double)(knp->value.ui32));
-
- /*
- * Remaining capacity:
- * the estimated remaining battery capacity
- */
- ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
- "battery BST0");
-
- if (ksp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- (void) kstat_read(kc, ksp, NULL);
- knp = kstat_data_lookup(ksp, "bst_rem_cap");
-
- if (knp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- battery.remain_cap = mW2W((double)(knp->value.ui32));
-
- /*
- * Battery State:
- * Bit0 - 1 : discharging
- * Bit1 - 1 : charging
- * Bit2 - 1 : critical energy state
- */
- ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
- "battery BST0");
-
- if (ksp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- (void) kstat_read(kc, ksp, NULL);
- knp = kstat_data_lookup(ksp, "bst_state");
-
- if (knp == NULL) {
- (void) kstat_close(kc);
- return (-1);
- }
-
- battery.bst_state = knp->value.ui32;
-
- (void) kstat_close(kc);
-
- return (0);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/battery.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <string.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+#define mW2W(value) ((value) / 1000)
+
+typedef struct battery_state {
+ uint32_t exist;
+ uint32_t power_unit;
+ uint32_t bst_state;
+ double present_rate;
+ double remain_cap;
+ double last_cap;
+} battery_state_t;
+
+static char *kstat_batt_mod[3] = {NULL, "battery", "acpi_drv"};
+static uint_t kstat_batt_idx;
+static battery_state_t battery_state;
+
+static int battery_stat_snapshot(void);
+
+/*
+ * Checks if the kstat module for battery information is present and
+ * whether it's called 'battery' or 'acpi_drv'
+ */
+void
+battery_mod_lookup(void)
+{
+ kstat_ctl_t *kc = kstat_open();
+
+ if (kstat_lookup(kc, kstat_batt_mod[1], 0, NULL))
+ kstat_batt_idx = 1;
+ else
+ if (kstat_lookup(kc, kstat_batt_mod[2], 0, NULL))
+ kstat_batt_idx = 2;
+ else
+ kstat_batt_idx = 0;
+
+ (void) kstat_close(kc);
+}
+
+void
+print_battery(void)
+{
+ int err;
+
+ (void) memset(&battery_state, 0, sizeof (battery_state_t));
+
+ /*
+ * The return value of battery_stat_snapshot() can be used for
+ * debug or to show/hide the acpi power line. We currently don't
+ * make the distinction of a system that runs only on AC and one
+ * that runs on battery but has no kstat battery info.
+ *
+ * We still display the estimate power usage for systems
+ * running on AC with a fully charged battery because some
+ * batteries may still consume power.
+ *
+ * If battery_mod_lookup() didn't find a kstat battery module, don't
+ * bother trying to take the snapshot
+ */
+ if (kstat_batt_idx > 0) {
+ if ((err = battery_stat_snapshot()) < 0)
+ pt_error("%s : battery kstat not found %d\n", __FILE__,
+ err);
+ }
+
+ show_acpi_power_line(battery_state.exist, battery_state.present_rate,
+ battery_state.remain_cap, battery_state.last_cap,
+ battery_state.bst_state);
+}
+
+static int
+battery_stat_snapshot(void)
+{
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *knp;
+
+ kc = kstat_open();
+
+ /*
+ * power unit:
+ * 0 - Capacity information is reported in [mWh] and
+ * charge/discharge rate information in [mW]
+ * 1 - Capacity information is reported in [mAh] and
+ * charge/discharge rate information in [mA].
+ */
+ ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+ "battery BIF0");
+
+ if (ksp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+ knp = kstat_data_lookup(ksp, "bif_unit");
+
+ if (knp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ battery_state.power_unit = knp->value.ui32;
+
+ /*
+ * Present rate:
+ * the power or current being supplied or accepted
+ * through the battery's terminal
+ */
+ ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+ "battery BST0");
+
+ if (ksp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+ knp = kstat_data_lookup(ksp, "bst_rate");
+
+ if (knp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ if (knp->value.ui32 == 0xFFFFFFFF)
+ battery_state.present_rate = 0;
+ else {
+ battery_state.exist = 1;
+ battery_state.present_rate = mW2W((double)(knp->value.ui32));
+ }
+
+ /*
+ * Last Full charge capacity:
+ * Predicted battery capacity when fully charged.
+ */
+ ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+ "battery BIF0");
+
+ if (ksp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+ knp = kstat_data_lookup(ksp, "bif_last_cap");
+
+ if (knp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ battery_state.last_cap = mW2W((double)(knp->value.ui32));
+
+ /*
+ * Remaining capacity:
+ * the estimated remaining battery capacity
+ */
+ ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+ "battery BST0");
+
+ if (ksp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+ knp = kstat_data_lookup(ksp, "bst_rem_cap");
+
+ if (knp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ battery_state.remain_cap = mW2W((double)(knp->value.ui32));
+
+ /*
+ * Battery State:
+ * Bit0 - 1 : discharging
+ * Bit1 - 1 : charging
+ * Bit2 - 1 : critical energy state
+ */
+ ksp = kstat_lookup(kc, kstat_batt_mod[kstat_batt_idx], 0,
+ "battery BST0");
+
+ if (ksp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+ knp = kstat_data_lookup(ksp, "bst_state");
+
+ if (knp == NULL) {
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ battery_state.bst_state = knp->value.ui32;
+
+ (void) kstat_close(kc);
+
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/cpufreq.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dtrace.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+#define HZ2MHZ(speed) ((speed) / 1000000)
+#define DTP_ARG_COUNT 2
+#define DTP_ARG_LENGTH 5
+
+static uint64_t max_cpufreq = 0;
+static dtrace_hdl_t *dtp;
+static char **dtp_argv;
+
+/*
+ * Enabling PM through /etc/power.conf
+ * See suggest_p_state()
+ */
+static char default_conf[] = "/etc/power.conf";
+static char default_pmconf[] = "/usr/sbin/pmconfig";
+static char cpupm_enable[] = " echo cpupm enable >> /etc/power.conf";
+static char cpupm_treshold[] = " echo cpu-threshold 1s >> /etc/power.conf";
+
+/*
+ * Buffer containing DTrace program to track CPU frequency transitions
+ */
+static const char *dtp_cpufreq =
+"hrtime_t last[$0];"
+""
+"BEGIN"
+"{"
+" begin = timestamp;"
+"}"
+""
+":::cpu-change-speed"
+"/last[(processorid_t)arg0] != 0/"
+"{"
+" this->cpu = (processorid_t)arg0;"
+" this->oldspeed = (uint32_t)(arg1/1000000);"
+" @times[this->cpu, this->oldspeed] = sum(timestamp - last[this->cpu]);"
+" last[this->cpu] = timestamp;"
+"}"
+":::cpu-change-speed"
+"/last[(processorid_t)arg0] == 0/"
+"{"
+" this->cpu = (processorid_t)arg0;"
+" this->oldspeed = (uint32_t)(arg1/1000000);"
+" @times[this->cpu, this->oldspeed] = sum(timestamp - begin);"
+" last[this->cpu] = timestamp;"
+"}";
+
+/*
+ * Same as above, but only for a specific CPU
+ */
+static const char *dtp_cpufreq_c =
+"hrtime_t last;"
+""
+"BEGIN"
+"{"
+" begin = timestamp;"
+"}"
+""
+":::cpu-change-speed"
+"/(processorid_t)arg0 == $1 &&"
+" last != 0/"
+"{"
+" this->cpu = (processorid_t)arg0;"
+" this->oldspeed = (uint32_t)(arg1/1000000);"
+" @times[this->cpu, this->oldspeed] = sum(timestamp - last);"
+" last = timestamp;"
+"}"
+":::cpu-change-speed"
+"/(processorid_t)arg0 == $1 &&"
+" last == 0/"
+"{"
+" this->cpu = (processorid_t)arg0;"
+" this->oldspeed = (uint32_t)(arg1/1000000);"
+" @times[this->cpu, this->oldspeed] = sum(timestamp - begin);"
+" last = timestamp;"
+"}";
+
+static int pt_cpufreq_setup(void);
+static int pt_cpufreq_snapshot(void);
+static int pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *, void *);
+static void pt_cpufreq_stat_account(double, uint_t);
+static int pt_cpufreq_snapshot_cpu(kstat_ctl_t *,
+ uint_t);
+
+static int
+pt_cpufreq_setup(void)
+{
+ if ((dtp_argv = malloc(sizeof (char *) * DTP_ARG_COUNT)) == NULL)
+ return (EXIT_FAILURE);
+
+ if ((dtp_argv[0] = malloc(sizeof (char) * DTP_ARG_LENGTH)) == NULL) {
+ free(dtp_argv);
+ return (EXIT_FAILURE);
+ }
+
+ (void) snprintf(dtp_argv[0], 5, "%d\0", g_ncpus_observed);
+
+ if (PTOP_ON_CPU) {
+ if ((dtp_argv[1] = malloc(sizeof (char) * DTP_ARG_LENGTH))
+ == NULL) {
+ free(dtp_argv[0]);
+ free(dtp_argv);
+ return (EXIT_FAILURE);
+ }
+ (void) snprintf(dtp_argv[1], 5, "%d\0", g_observed_cpu);
+ }
+
+ return (0);
+}
+
+/*
+ * Perform setup necessary to enumerate and track CPU speed changes
+ */
+int
+pt_cpufreq_stat_prepare(void)
+{
+ dtrace_prog_t *prog;
+ dtrace_proginfo_t info;
+ dtrace_optval_t statustime;
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *knp;
+ freq_state_info_t *state;
+ char *s, *token, *prog_ptr;
+ int err;
+
+ if ((err = pt_cpufreq_setup()) != 0) {
+ pt_error("%s : failed to setup", __FILE__);
+ return (errno);
+ }
+
+ state = g_pstate_info;
+ if ((g_cpu_power_states = calloc((size_t)g_ncpus,
+ sizeof (cpu_power_info_t))) == NULL)
+ return (-1);
+
+ /*
+ * Enumerate the CPU frequencies
+ */
+ if ((kc = kstat_open()) == NULL)
+ return (errno);
+
+ ksp = kstat_lookup(kc, "cpu_info", g_cpu_table[g_observed_cpu], NULL);
+
+ if (ksp == NULL) {
+ err = errno;
+ (void) kstat_close(kc);
+ return (err);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+
+ knp = kstat_data_lookup(ksp, "supported_frequencies_Hz");
+ s = knp->value.str.addr.ptr;
+
+ g_npstates = 0;
+
+ for (token = strtok(s, ":"), s = NULL;
+ NULL != token && g_npstates < NSTATES;
+ token = strtok(NULL, ":")) {
+
+ state->speed = HZ2MHZ(atoll(token));
+
+ if (state->speed > max_cpufreq)
+ max_cpufreq = state->speed;
+
+ state->total_time = (uint64_t)0;
+
+ g_npstates++;
+ state++;
+ }
+
+ if (token != NULL)
+ pt_error("%s : exceeded NSTATES\n", __FILE__);
+
+ (void) kstat_close(kc);
+
+ /*
+ * Return if speed transition is not supported
+ */
+ if (g_npstates < 2)
+ return (-1);
+
+ /*
+ * Setup DTrace to look for CPU frequency changes
+ */
+ if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
+ pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
+ dtrace_errmsg(NULL, err));
+ return (-2);
+ }
+
+ /*
+ * Execute different scripts (defined above) depending on
+ * user specified options. Default mode uses dtp_cpufreq.
+ */
+ if (PTOP_ON_CPU)
+ prog_ptr = (char *)dtp_cpufreq_c;
+ else
+ prog_ptr = (char *)dtp_cpufreq;
+
+ if ((prog = dtrace_program_strcompile(dtp, prog_ptr,
+ DTRACE_PROBESPEC_NAME, 0, (1 + g_argc), dtp_argv)) == NULL) {
+ pt_error("%s : cpu-change-speed probe unavailable\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_program_exec(dtp, prog, &info) == -1) {
+ pt_error("%s : failed to enable speed probe\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_setopt(dtp, "aggsize", "128k") == -1) {
+ pt_error("%s : failed to set speed 'aggsize'\n", __FILE__);
+ }
+
+ if (dtrace_setopt(dtp, "aggrate", "0") == -1) {
+ pt_error("%s : failed to set speed 'aggrate'\n", __FILE__);
+ }
+
+ if (dtrace_setopt(dtp, "aggpercpu", 0) == -1) {
+ pt_error("%s : failed to set speed 'aggpercpu'\n", __FILE__);
+ }
+
+ if (dtrace_go(dtp) != 0) {
+ pt_error("%s : failed to start speed observation", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_getopt(dtp, "statusrate", &statustime) == -1) {
+ pt_error("%s : failed to get speed 'statusrate'\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ return (0);
+}
+
+/*
+ * The DTrace probes have already been enabled, and are tracking
+ * CPU speed transitions. Take a snapshot of the aggregations, and
+ * look for any CPUs that have made a speed transition over the last
+ * sampling interval. Note that the aggregations may be empty if no
+ * speed transitions took place over the last interval. In that case,
+ * notate that we have already accounted for the time, so that when
+ * we do encounter a speed transition in a future sampling interval
+ * we can subtract that time back out.
+ */
+int
+pt_cpufreq_stat_collect(double interval)
+{
+ int i, ret;
+
+ /*
+ * Zero out the interval time reported by DTrace for
+ * this interval
+ */
+ for (i = 0; i < g_npstates; i++)
+ g_pstate_info[i].total_time = 0;
+
+ for (i = 0; i < g_ncpus; i++)
+ g_cpu_power_states[i].dtrace_time = 0;
+
+ if (dtrace_status(dtp) == -1)
+ return (-1);
+
+ if (dtrace_aggregate_snap(dtp) != 0)
+ pt_error("%s : failed to add to stats aggregation", __FILE__);
+
+ if (dtrace_aggregate_walk_keyvarsorted(dtp, pt_cpufreq_dtrace_walk,
+ NULL) != 0)
+ pt_error("%s : failed to sort stats aggregation", __FILE__);
+
+ dtrace_aggregate_clear(dtp);
+
+ if ((ret = pt_cpufreq_snapshot()) != 0) {
+ pt_error("%s : failed to add to stats aggregation", __FILE__);
+ return (ret);
+ }
+
+ switch (g_op_mode) {
+ case PTOP_MODE_CPU:
+ pt_cpufreq_stat_account(interval, g_observed_cpu);
+ break;
+ case PTOP_MODE_DEFAULT:
+ default:
+ for (i = 0; i < g_ncpus_observed; i++)
+ pt_cpufreq_stat_account(interval, i);
+ break;
+ }
+
+ return (0);
+}
+
+static void
+pt_cpufreq_stat_account(double interval, uint_t cpu)
+{
+ uint64_t speed;
+ hrtime_t duration;
+ cpu_power_info_t *cpu_pow;
+ int i;
+
+ cpu_pow = &g_cpu_power_states[cpu];
+ speed = cpu_pow->current_pstate;
+
+ duration = (hrtime_t)((interval * NANOSEC)) - cpu_pow->dtrace_time;
+
+ for (i = 0; i < g_npstates; i++) {
+ if (g_pstate_info[i].speed == speed) {
+ g_pstate_info[i].total_time += duration;
+ cpu_pow->time_accounted += duration;
+ }
+ }
+}
+
+/*
+ * Take a snapshot of each CPU's speed by looking through the cpu_info kstats.
+ */
+static int
+pt_cpufreq_snapshot(void)
+{
+ kstat_ctl_t *kc;
+ int ret;
+ uint_t i;
+
+ if ((kc = kstat_open()) == NULL)
+ return (errno);
+
+ switch (g_op_mode) {
+ case PTOP_MODE_CPU:
+ ret = pt_cpufreq_snapshot_cpu(kc, g_observed_cpu);
+ break;
+ case PTOP_MODE_DEFAULT:
+ default:
+ for (i = 0; i < g_ncpus_observed; i++)
+ if ((ret = pt_cpufreq_snapshot_cpu(kc, i)) != 0)
+ break;
+ break;
+ }
+
+ if (kstat_close(kc) != 0)
+ pt_error("%s : couldn't close kstat\n", __FILE__);
+
+ return (ret);
+}
+
+static int
+pt_cpufreq_snapshot_cpu(kstat_ctl_t *kc, uint_t cpu)
+{
+ kstat_t *ksp;
+ kstat_named_t *knp;
+
+ ksp = kstat_lookup(kc, "cpu_info", g_cpu_table[cpu], NULL);
+ if (ksp == NULL) {
+ pt_error("%s : couldn't find cpu_info kstat for CPU "
+ "%d\n", __FILE__, cpu);
+ return (1);
+ }
+
+ if (kstat_read(kc, ksp, NULL) == -1) {
+ pt_error("%s : couldn't read cpu_info kstat for "
+ "CPU %d\n", __FILE__, cpu);
+ return (2);
+ }
+
+ knp = kstat_data_lookup(ksp, "current_clock_Hz");
+ if (knp == NULL) {
+ pt_error("%s : couldn't find current_clock_Hz "
+ "kstat for CPU %d\n", __FILE__, cpu);
+ return (3);
+ }
+
+ g_cpu_power_states[cpu].current_pstate = HZ2MHZ(knp->value.ui64);
+
+ return (0);
+}
+
+/*
+ * DTrace aggregation walker that sorts through a snapshot of the
+ * aggregation data collected during firings of the cpu-change-speed
+ * probe.
+ */
+/*ARGSUSED*/
+static int
+pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
+{
+ dtrace_aggdesc_t *aggdesc = data->dtada_desc;
+ dtrace_recdesc_t *cpu_rec, *speed_rec;
+ cpu_power_info_t *cpu_pow;
+ int32_t cpu;
+ uint64_t speed;
+ hrtime_t dt_state_time = 0;
+ int i;
+
+ if (strcmp(aggdesc->dtagd_name, "times") == 0) {
+ cpu_rec = &aggdesc->dtagd_rec[1];
+ speed_rec = &aggdesc->dtagd_rec[2];
+
+ for (i = 0; i < g_ncpus; i++) {
+ /* LINTED - alignment */
+ dt_state_time += *((hrtime_t *)(data->dtada_percpu[i]));
+ }
+
+ /* LINTED - alignment */
+ cpu = *(int32_t *)(data->dtada_data + cpu_rec->dtrd_offset);
+ /* LINTED - alignment */
+ speed = *(uint64_t *)(data->dtada_data +
+ speed_rec->dtrd_offset);
+
+ if (speed == 0) {
+ speed = max_cpufreq;
+ }
+
+ /*
+ * We have an aggregation record for "cpu" being at "speed"
+ * for an interval of "n" nanoseconds. The reported interval
+ * may exceed the powertop sampling interval, since we only
+ * notice during potentially infrequent firings of the
+ * "speed change" DTrace probe. In this case powertop would
+ * have already accounted for the portions of the interval
+ * that happened during prior powertop samplings, so subtract
+ * out time already accounted.
+ */
+ cpu_pow = &g_cpu_power_states[cpu];
+
+ for (i = 0; i < g_npstates; i++) {
+ if (g_pstate_info[i].speed == speed) {
+ if (cpu_pow->time_accounted > 0) {
+ if (dt_state_time == 0)
+ continue;
+ if (dt_state_time >
+ cpu_pow->time_accounted) {
+ dt_state_time -=
+ cpu_pow->time_accounted;
+ cpu_pow->time_accounted = 0;
+ }
+ }
+ g_pstate_info[i].total_time += dt_state_time;
+ cpu_pow->dtrace_time += dt_state_time;
+ }
+ }
+ }
+ return (DTRACE_AGGWALK_NEXT);
+}
+
+/*
+ * Used as a suggestion, sets PM in /etc/power.conf and
+ * a 1sec threshold, then calls /usr/sbin/pmconfig
+ */
+void
+enable_p_state(void)
+{
+ (void) system(cpupm_enable);
+ (void) system(cpupm_treshold);
+ (void) system(default_pmconf);
+}
+
+/*
+ * Checks if PM is enabled in /etc/power.conf, enabling if not
+ */
+void
+suggest_p_state(void)
+{
+ char line[1024];
+ FILE *file;
+
+ /*
+ * Return if speed transition is not supported
+ */
+ if (g_npstates < 2)
+ return;
+
+ file = fopen(default_conf, "r");
+
+ if (!file)
+ return;
+
+ (void) memset(line, 0, 1024);
+
+ while (fgets(line, 1023, file)) {
+ if (strstr(line, "cpupm")) {
+ if (strstr(line, "enable")) {
+ (void) fclose(file);
+ return;
+ }
+ }
+ }
+
+ add_suggestion("Suggestion: enable CPU power management by "
+ "pressing the P key", 40, 'P', "P - Enable p-state",
+ enable_p_state);
+
+ (void) fclose(file);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/cpuidle.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <string.h>
+#include <dtrace.h>
+#include "powertop.h"
+
+static dtrace_hdl_t *dtp;
+
+/*
+ * Buffer containing DTrace program to track CPU idle state transitions
+ */
+static const char *dtp_cpuidle =
+":::idle-state-transition"
+"/arg0 != 0/"
+"{"
+" self->start = timestamp;"
+" self->state = arg0;"
+"}"
+""
+":::idle-state-transition"
+"/arg0 == 0 && self->start/"
+"{"
+" @number[self->state] = count();"
+" @times[self->state] = sum((timestamp - self->start)/1000000);"
+" self->start = 0;"
+" self->state = 0;"
+"}";
+
+/*
+ * Same as above but only for a specific CPU
+ */
+static const char *dtp_cpuidle_c =
+":::idle-state-transition"
+"/cpu == $0 &&"
+" arg0 != 0/"
+"{"
+" self->start = timestamp;"
+" self->state = arg0;"
+"}"
+""
+":::idle-state-transition"
+"/cpu == $0 &&"
+" arg0 == 0 && self->start/"
+"{"
+" @number[self->state] = count();"
+" @times[self->state] = sum((timestamp - self->start)/1000000);"
+" self->start = 0;"
+" self->state = 0;"
+"}";
+
+static int pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *, void *);
+
+/*
+ * Perform setup necessary to track CPU idle state transitions
+ */
+int
+pt_cpuidle_stat_prepare(void)
+{
+ dtrace_prog_t *prog;
+ dtrace_proginfo_t info;
+ dtrace_optval_t statustime;
+ int err;
+ char *prog_ptr;
+
+ if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
+ pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
+ dtrace_errmsg(NULL, err));
+ return (-1);
+ }
+
+ /*
+ * Execute different scripts (defined above) depending on
+ * user specified options.
+ */
+ if (PTOP_ON_CPU)
+ prog_ptr = (char *)dtp_cpuidle_c;
+ else
+ prog_ptr = (char *)dtp_cpuidle;
+
+ if ((prog = dtrace_program_strcompile(dtp, prog_ptr,
+ DTRACE_PROBESPEC_NAME, 0, g_argc, g_argv)) == NULL) {
+ pt_error("%s : C-State DTrace probes unavailable\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_program_exec(dtp, prog, &info) == -1) {
+ pt_error("%s : failed to enable C State probes\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_setopt(dtp, "aggsize", "128k") == -1) {
+ pt_error("%s : failed to set C-state 'aggsize'\n", __FILE__);
+ }
+
+ if (dtrace_setopt(dtp, "aggrate", "0") == -1) {
+ pt_error("%s : failed to set C-state'aggrate'\n", __FILE__);
+ }
+
+ if (dtrace_setopt(dtp, "aggpercpu", 0) == -1) {
+ pt_error("%s : failed to set C-state 'aggpercpu'\n", __FILE__);
+ }
+
+ if (dtrace_go(dtp) != 0) {
+ pt_error("%s : failed to start C-state observation", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_getopt(dtp, "statusrate", &statustime) == -1) {
+ pt_error("%s : failed to get C-state 'statusrate'\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ return (0);
+}
+
+/*
+ * The DTrace probes have been enabled, and are tracking CPU idle state
+ * transitions. Take a snapshot of the aggregations, and invoke the aggregation
+ * walker to process any records. The walker does most of the accounting work
+ * chalking up time spent into the g_cstate_info structure.
+ */
+int
+pt_cpuidle_stat_collect(double interval)
+{
+ int i;
+ hrtime_t t = 0;
+
+ /*
+ * Zero out the interval time reported by DTrace for
+ * this interval
+ */
+ for (i = 0; i < NSTATES; i++) {
+ g_cstate_info[i].total_time = 0;
+ g_cstate_info[i].events = 0;
+ }
+
+ /*
+ * Assume that all the time spent in this interval will
+ * be the default "0" state. The DTrace walker will reallocate
+ * time out of the default bucket as it processes aggregation
+ * records for time spent in other states.
+ */
+ g_cstate_info[0].total_time = (long)(interval * g_ncpus_observed *
+ 1000);
+
+ if (dtrace_status(dtp) == -1)
+ return (-1);
+
+ if (dtrace_aggregate_snap(dtp) != 0)
+ pt_error("%s : failed to add to aggregation", __FILE__);
+
+ if (dtrace_aggregate_walk_keyvarsorted(dtp, pt_cpuidle_dtrace_walk,
+ NULL) != 0)
+ pt_error("%s : failed to sort aggregation", __FILE__);
+
+ dtrace_aggregate_clear(dtp);
+
+ /*
+ * Populate g_cstate_info with the correct amount of time spent
+ * in each C state and update the number of C states in g_max_cstate
+ */
+ g_total_c_time = 0;
+ for (i = 0; i < NSTATES; i++) {
+ if (g_cstate_info[i].total_time > 0) {
+ g_total_c_time += g_cstate_info[i].total_time;
+ if (i > g_max_cstate)
+ g_max_cstate = i;
+ if (g_cstate_info[i].last_time > t) {
+ t = g_cstate_info[i].last_time;
+ g_longest_cstate = i;
+ }
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * DTrace aggregation walker that sorts through a snapshot of data records
+ * collected during firings of the idle-state-transition probe.
+ *
+ * XXX A way of querying the current idle state for a CPU is needed in addition
+ * to logic similar to that in cpufreq.c
+ */
+/*ARGSUSED*/
+static int
+pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
+{
+ dtrace_aggdesc_t *aggdesc = data->dtada_desc;
+ dtrace_recdesc_t *rec;
+ uint64_t n = 0;
+ int32_t state;
+ int i;
+
+ rec = &aggdesc->dtagd_rec[1];
+ /* LINTED - alignment */
+ state = *(int32_t *)(data->dtada_data + rec->dtrd_offset);
+
+ if (strcmp(aggdesc->dtagd_name, "number") == 0) {
+ for (i = 0; i < g_ncpus; i++) {
+ /* LINTED - alignment */
+ n += *((uint64_t *)(data->dtada_percpu[i]));
+ }
+ g_total_events += n;
+ g_cstate_info[state].events += n;
+ }
+ else
+ if (strcmp(aggdesc->dtagd_name, "times") == 0) {
+ for (i = 0; i < g_ncpus; i++) {
+ /* LINTED - alignment */
+ n += *((uint64_t *)(data->dtada_percpu[i]));
+ }
+ g_cstate_info[state].last_time = n;
+ g_cstate_info[state].total_time += n;
+ if (g_cstate_info[0].total_time >= n)
+ g_cstate_info[0].total_time -= n;
+ }
+
+ return (DTRACE_AGGWALK_NEXT);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/display.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,477 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <curses.h>
+#include "powertop.h"
+
+static WINDOW *title_bar_window;
+static WINDOW *cstate_window;
+static WINDOW *wakeup_window;
+static WINDOW *acpi_power_window;
+static WINDOW *eventstat_window;
+static WINDOW *suggestion_window;
+static WINDOW *status_bar_window;
+
+#define print(win, y, x, fmt, args...) \
+ if (PTOP_ON_DUMP) \
+ (void) printf(fmt, ## args); \
+ else \
+ (void) mvwprintw(win, y, x, fmt, ## args);
+
+char g_status_bar_slots[PTOP_BAR_NSLOTS][PTOP_BAR_LENGTH];
+char g_suggestion_key;
+
+static int maxx, maxy;
+
+static void
+zap_windows(void)
+{
+ if (title_bar_window) {
+ (void) delwin(title_bar_window);
+ title_bar_window = NULL;
+ }
+ if (cstate_window) {
+ (void) delwin(cstate_window);
+ cstate_window = NULL;
+ }
+ if (wakeup_window) {
+ (void) delwin(wakeup_window);
+ wakeup_window = NULL;
+ }
+ if (acpi_power_window) {
+ (void) delwin(acpi_power_window);
+ acpi_power_window = NULL;
+ }
+ if (eventstat_window) {
+ (void) delwin(eventstat_window);
+ eventstat_window = NULL;
+ }
+ if (suggestion_window) {
+ (void) delwin(suggestion_window);
+ suggestion_window = NULL;
+ }
+ if (status_bar_window) {
+ (void) delwin(status_bar_window);
+ status_bar_window = NULL;
+ }
+}
+
+void
+cleanup_curses(void)
+{
+ (void) endwin();
+}
+
+/*
+ * This part was re-written to be human readable and easy to modify. Please
+ * try to keep it that way and help us save some time.
+ *
+ * Friendly reminder:
+ * subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x)
+ */
+void
+setup_windows(void)
+{
+ /*
+ * These variables are used to properly set the initial y position and
+ * number of lines in each subwindow, as the number of supported CPU
+ * states affects their placement.
+ */
+ int cstate_lines, event_lines, pos_y;
+
+ getmaxyx(stdscr, maxy, maxx);
+
+ zap_windows();
+
+ cstate_lines = TITLE_LINE + max((g_max_cstate+1), g_npstates);
+
+ pos_y = 0;
+ title_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+ pos_y += NEXT_LINE + BLANK_LINE;
+ cstate_window = subwin(stdscr, cstate_lines, maxx, pos_y, 0);
+
+ pos_y += cstate_lines + BLANK_LINE;
+ wakeup_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+ pos_y += NEXT_LINE;
+ acpi_power_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+ pos_y += NEXT_LINE + BLANK_LINE;
+ event_lines = maxy - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW -
+ pos_y;
+ eventstat_window = subwin(stdscr, event_lines, maxx, pos_y, 0);
+
+ pos_y += event_lines + NEXT_LINE;
+ suggestion_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+ pos_y += BLANK_LINE + NEXT_LINE;
+ status_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
+
+ (void) strcpy(g_status_bar_slots[0], _(" Q - Quit "));
+ (void) strcpy(g_status_bar_slots[1], _(" R - Refresh "));
+
+ (void) werase(stdscr);
+ (void) wrefresh(status_bar_window);
+}
+
+void
+initialize_curses(void)
+{
+ (void) initscr();
+ (void) start_color();
+
+ /*
+ * Enable keyboard mapping
+ */
+ (void) keypad(stdscr, TRUE);
+
+ /*
+ * Tell curses not to do NL->CR/NL on output
+ */
+ (void) nonl();
+
+ /*
+ * Take input chars one at a time, no wait for \n
+ */
+ (void) cbreak();
+
+ /*
+ * Dont echo input
+ */
+ (void) noecho();
+
+ /*
+ * Turn off cursor
+ */
+ (void) curs_set(0);
+
+ (void) init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
+ (void) init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
+ (void) init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
+ (void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
+ (void) init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
+ (void) init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
+ (void) init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
+ (void) init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
+
+ (void) atexit(cleanup_curses);
+}
+
+void
+show_title_bar(void)
+{
+ int i, x = 0, y = 0;
+ char title_pad[10];
+
+ (void) wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
+ (void) wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
+ (void) werase(title_bar_window);
+
+ (void) snprintf(title_pad, 10, "%%%ds",
+ (maxx - strlen(TITLE))/2 + strlen(TITLE));
+ /* LINTED: E_SEC_PRINTF_VAR_FMT */
+ print(title_bar_window, y, x, title_pad, TITLE);
+
+ (void) wrefresh(title_bar_window);
+ (void) werase(status_bar_window);
+
+ for (i = 0; i < PTOP_BAR_NSLOTS; i++) {
+ if (strlen(g_status_bar_slots[i]) == 0)
+ continue;
+ (void) wattron(status_bar_window, A_REVERSE);
+ print(status_bar_window, y, x, "%s", g_status_bar_slots[i]);
+ (void) wattroff(status_bar_window, A_REVERSE);
+ x += strlen(g_status_bar_slots[i]) + 1;
+ }
+ (void) wnoutrefresh(status_bar_window);
+}
+
+void
+show_cstates(void)
+{
+ char c[100];
+ int i;
+ double total_pstates = 0.0, avg, res;
+ uint64_t p0_speed, p1_speed;
+
+ if (!PTOP_ON_DUMP) {
+ (void) werase(cstate_window);
+ (void) wattrset(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+ (void) wbkgd(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+ }
+
+ print(cstate_window, 0, 0, "%s\tAvg residency\n", g_msg_idle_state);
+ res = (((double)g_cstate_info[0].total_time / g_total_c_time)) * 100;
+ (void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res);
+ print(cstate_window, 1, 0, "%s", c);
+
+ for (i = 1; i <= g_max_cstate; i++) {
+ /*
+ * In situations where the load is too intensive, the system
+ * might not transition at all.
+ */
+ if (g_cstate_info[i].events > 0)
+ avg = (((double)g_cstate_info[i].total_time/
+ g_ncpus_observed)/g_cstate_info[i].events);
+ else
+ avg = 0;
+
+ res = ((double)g_cstate_info[i].total_time/g_total_c_time)
+ * 100;
+
+ (void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", i, (float)avg,
+ (float)res);
+ print(cstate_window, i + 1, 0, "%s", c);
+ }
+
+ print(cstate_window, 0, 48, "%s", g_msg_freq_state);
+
+ if (g_npstates < 2) {
+ (void) sprintf(c, "%4lu Mhz\t%.1f%%",
+ (long)g_pstate_info[0].speed, 100.0);
+ print(cstate_window, 1, 48, "%s\n", c);
+ } else {
+ for (i = 0; i < g_npstates; i++) {
+ total_pstates += (double)(g_pstate_info[i].total_time/
+ g_ncpus_observed/1000000);
+ }
+
+ /*
+ * display ACPI_PSTATE from P(n) to P(1)
+ */
+ for (i = 0; i < g_npstates - 1; i++) {
+ (void) sprintf(c, "%4lu Mhz\t%.1f%%",
+ (long)g_pstate_info[i].speed,
+ 100 * (g_pstate_info[i].total_time/g_ncpus_observed/
+ 1000000/total_pstates));
+ print(cstate_window, i+1, 48, "%s\n", c);
+ }
+
+ /*
+ * Display ACPI_PSTATE P0 according to if turbo
+ * mode is supported
+ */
+ if (g_turbo_supported) {
+ p1_speed = g_pstate_info[g_npstates - 2].speed;
+
+ /*
+ * If g_turbo_ratio <= 1.0, it will be ignored.
+ * we display P(0) as P(1) + 1.
+ */
+ if (g_turbo_ratio <= 1.0) {
+ p0_speed = p1_speed + 1;
+ } else {
+ /*
+ * If g_turbo_ratio > 1.0, that means turbo
+ * mode works. So, P(0) = ratio * P(1);
+ */
+ p0_speed = (uint64_t)(p1_speed * g_turbo_ratio);
+ if (p0_speed < (p1_speed + 1))
+ p0_speed = p1_speed + 1;
+ }
+ /*
+ * Reset the ratio for the next round
+ */
+ g_turbo_ratio = 0.0;
+
+ /*
+ * Setup the string for the display
+ */
+ (void) sprintf(c, "%4lu Mhz(turbo)\t%.1f%%",
+ (long)p0_speed,
+ 100 * (g_pstate_info[i].total_time/
+ g_ncpus_observed/1000000/total_pstates));
+ } else {
+ (void) sprintf(c, "%4lu Mhz\t%.1f%%",
+ (long)g_pstate_info[i].speed,
+ 100 * (g_pstate_info[i].total_time/
+ g_ncpus_observed/1000000/total_pstates));
+ }
+ print(cstate_window, i+1, 48, "%s\n", c);
+ }
+
+ if (!PTOP_ON_DUMP)
+ (void) wnoutrefresh(cstate_window);
+}
+
+void
+show_acpi_power_line(uint32_t flag, double rate, double rem_cap, double cap,
+ uint32_t state)
+{
+ char buffer[1024];
+
+ (void) sprintf(buffer, _("no ACPI power usage estimate available"));
+
+ if (!PTOP_ON_DUMP)
+ (void) werase(acpi_power_window);
+ if (flag) {
+ char *c;
+ (void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW",
+ rate);
+ (void) strcat(buffer, " ");
+ c = &buffer[strlen(buffer)];
+ switch (state) {
+ case 0:
+ (void) sprintf(c, "(running on AC power, fully "
+ "charged)");
+ break;
+ case 1:
+ (void) sprintf(c, "(discharging: %3.1f hours)",
+ (uint32_t)rem_cap/rate);
+ break;
+ case 2:
+ (void) sprintf(c, "(charging: %3.1f hours)",
+ (uint32_t)(cap - rem_cap)/rate);
+ break;
+ case 4:
+ (void) sprintf(c, "(##critically low battery power##)");
+ break;
+ }
+
+ }
+ print(acpi_power_window, 0, 0, "%s\n", buffer);
+ if (!PTOP_ON_DUMP)
+ (void) wnoutrefresh(acpi_power_window);
+}
+
+void
+show_wakeups(double interval)
+{
+ char c[100];
+ int i, event_sum = 0;
+ event_info_t *g_p_event = g_event_info;
+
+ if (!PTOP_ON_DUMP) {
+ (void) werase(wakeup_window);
+ (void) wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
+ (void) wattron(wakeup_window, A_BOLD);
+ }
+
+ /*
+ * calculate the actual total event number
+ */
+ for (i = 0; i < g_tog_p_events; i++, g_p_event++)
+ event_sum += g_p_event->total_count;
+
+ /*
+ * g_total_events is the sum of the number of Cx->C0 transition,
+ * So when the system is very busy, the idle thread will have no
+ * chance or very seldom to be scheduled, this could cause >100%
+ * event report. Re-assign g_total_events to the actual event
+ * number is a way to avoid this issue.
+ */
+ if (event_sum > g_total_events)
+ g_total_events = event_sum;
+
+ (void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: "
+ "%.1fs", (double)(g_total_events/interval), interval);
+ print(wakeup_window, 0, 0, "%s\n", c);
+
+ if (!PTOP_ON_DUMP)
+ (void) wnoutrefresh(wakeup_window);
+}
+
+void
+show_eventstats(double interval)
+{
+ char c[100];
+ int i;
+ double events;
+ event_info_t *g_p_event = g_event_info;
+
+ if (!PTOP_ON_DUMP) {
+ (void) werase(eventstat_window);
+ (void) wattrset(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+ (void) wbkgd(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
+ }
+
+ /*
+ * Sort the event report list
+ */
+ if (g_tog_p_events > EVENT_NUM_MAX)
+ g_tog_p_events = EVENT_NUM_MAX;
+
+ qsort((void *)g_event_info, g_tog_p_events, sizeof (event_info_t),
+ event_compare);
+
+ if (PTOP_ON_CPU)
+ (void) sprintf(c, "Top causes for wakeups on CPU %d:\n",
+ g_observed_cpu);
+ else
+ (void) sprintf(c, "Top causes for wakeups:\n");
+
+ print(eventstat_window, 0, 0, "%s", c);
+
+ for (i = 0; i < g_tog_p_events; i++, g_p_event++) {
+
+ if (g_total_events > 0 && g_p_event->total_count > 0)
+ events = (double)g_p_event->total_count/
+ (double)g_total_events;
+ else
+ continue;
+
+ (void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events,
+ (double)g_p_event->total_count/interval);
+ print(eventstat_window, i+1, 0, "%s", c);
+ print(eventstat_window, i+1, 16, "%20s :",
+ g_p_event->offender_name);
+ print(eventstat_window, i+1, 40, "%-64s\n",
+ g_p_event->offense_name);
+ }
+
+ if (!PTOP_ON_DUMP)
+ (void) wnoutrefresh(eventstat_window);
+}
+
+void
+show_suggestion(char *sug)
+{
+ (void) werase(suggestion_window);
+ print(suggestion_window, 0, 0, "%s", sug);
+ (void) wnoutrefresh(suggestion_window);
+}
+
+void
+update_windows(void)
+{
+ (void) doupdate();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/events.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <dtrace.h>
+#include "powertop.h"
+
+static dtrace_hdl_t *dtp;
+
+/*ARGSUSED*/
+static int
+walk(const dtrace_aggdata_t *data, void *arg)
+{
+ dtrace_aggdesc_t *aggdesc = data->dtada_desc;
+ dtrace_recdesc_t *rec1, *rec2, *rec3;
+ dtrace_syminfo_t dts;
+ char *offense_name;
+ uint64_t offender_addr;
+ int32_t *instance, *offender_cpu;
+ int i;
+ uint64_t n = 0;
+ GElf_Sym sym;
+
+ if (g_tog_p_events >= EVENT_NUM_MAX)
+ return (0);
+
+ rec1 = &aggdesc->dtagd_rec[1];
+ rec2 = &aggdesc->dtagd_rec[2];
+
+ /*
+ * Report interrupts
+ */
+ if (strcmp(aggdesc->dtagd_name, "interrupts") == 0) {
+ offense_name = data->dtada_data + rec1->dtrd_offset;
+
+ /* LINTED - alignment */
+ instance = (int32_t *)(data->dtada_data + rec2->dtrd_offset);
+ (void) snprintf((char *)(g_p_event->offender_name),
+ EVENT_NAME_MAX, "%s", "<interrupt>");
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "%s#%d", offense_name, *instance);
+ /*
+ * Report kernel events
+ */
+ } else if (strcmp(aggdesc->dtagd_name, "events_k") == 0) {
+
+ (void) snprintf((char *)(g_p_event->offender_name),
+ EVENT_NAME_MAX, "%s", "<kernel>");
+
+ /*
+ * Casting offender_addr to the wrong type will cause
+ * dtrace_lookup_by_addr to return 0 and the report
+ * to show an address instead of a name.
+ */
+ switch (g_bit_depth) {
+ case 32:
+ /* LINTED - alignment */
+ offender_addr = *(uint32_t *)(data->dtada_data +
+ rec1->dtrd_offset);
+ break;
+ case 64:
+ /* LINTED - alignment */
+ offender_addr = *(uint64_t *)(data->dtada_data +
+ rec1->dtrd_offset);
+ break;
+ }
+
+ /*
+ * We have the address of the kernel callout.
+ * Try to resolve it into a meaningful symbol
+ */
+ if (offender_addr != NULL && dtrace_lookup_by_addr(dtp,
+ offender_addr, &sym, &dts) == 0) {
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "%s`%s", dts.dts_object,
+ dts.dts_name);
+ } else {
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "0x%llx", offender_addr);
+ }
+ /*
+ * Report user events
+ */
+ } else if (strcmp(aggdesc->dtagd_name, "events_u") == 0) {
+ offense_name = data->dtada_data + rec1->dtrd_offset;
+
+ (void) snprintf((char *)(g_p_event->offender_name),
+ EVENT_NAME_MAX, "%s", offense_name);
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "<scheduled timeout expiration>");
+ /*
+ * Report cross calls
+ */
+ } else if (strcmp(aggdesc->dtagd_name, "events_x") == 0) {
+ offense_name = data->dtada_data + rec1->dtrd_offset;
+
+ (void) snprintf((char *)(g_p_event->offender_name),
+ EVENT_NAME_MAX, "%s", offense_name);
+
+ switch (g_bit_depth) {
+ case 32:
+ /* LINTED - alignment */
+ offender_addr = *(uint32_t *)(data->dtada_data +
+ rec2->dtrd_offset);
+ break;
+ case 64:
+ /* LINTED - alignment */
+ offender_addr = *(uint64_t *)(data->dtada_data +
+ rec2->dtrd_offset);
+ break;
+ }
+
+ /*
+ * Try to resolve the address of the cross call function.
+ */
+ if (offender_addr != NULL && dtrace_lookup_by_addr(dtp,
+ offender_addr, &sym, &dts) == 0) {
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "<xcalls> %s`%s",
+ dts.dts_object, dts.dts_name);
+ } else {
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "<xcalls>");
+ }
+ /*
+ * Report cross calls from other CPUs than the one we're observing
+ * with the -C option
+ */
+ } else if (strcmp(aggdesc->dtagd_name, "events_xc") == 0) {
+ rec3 = &aggdesc->dtagd_rec[3];
+ offense_name = data->dtada_data + rec1->dtrd_offset;
+
+ (void) snprintf((char *)(g_p_event->offender_name),
+ EVENT_NAME_MAX, "%s", offense_name);
+
+ switch (g_bit_depth) {
+ case 32:
+ /* LINTED - alignment */
+ offender_addr = *(uint32_t *)(data->dtada_data +
+ rec2->dtrd_offset);
+ break;
+ case 64:
+ /* LINTED - alignment */
+ offender_addr = *(uint64_t *)(data->dtada_data +
+ rec2->dtrd_offset);
+ break;
+ }
+ /* LINTED - alignment */
+ offender_cpu = (int32_t *)(data->dtada_data +
+ rec3->dtrd_offset);
+
+ /*
+ * Try to resolve the address of the cross call function.
+ */
+ if (offender_addr != NULL && dtrace_lookup_by_addr(dtp,
+ offender_addr, &sym, &dts) == 0) {
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "<xcalls> %s`%s (CPU %d)",
+ dts.dts_object, dts.dts_name, *offender_cpu);
+ } else {
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "<xcalls> (CPU %d)",
+ *offender_cpu);
+ }
+ /*
+ * Report unknown events
+ */
+ } else {
+ (void) snprintf((char *)(g_p_event->offender_name),
+ EVENT_NAME_MAX, "%s", "<unknown>");
+ (void) snprintf((char *)(g_p_event->offense_name),
+ EVENT_NAME_MAX, "%s", "<unknown>");
+ }
+
+ for (i = 0; i < g_ncpus; i++)
+ /* LINTED - alignment */
+ n += *((uint64_t *)(data->dtada_percpu[i]));
+
+ g_p_event->total_count = n;
+
+ g_p_event++;
+ g_tog_p_events++;
+
+ return (DTRACE_AGGWALK_NEXT);
+}
+
+int
+pt_events_stat_prepare(void)
+{
+ dtrace_prog_t *prog;
+ dtrace_proginfo_t info;
+ int err;
+ dtrace_optval_t statustime;
+ char *prog_ptr;
+
+ g_p_event = g_event_info;
+
+ if ((dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
+ pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
+ dtrace_errmsg(NULL, err));
+ return (-1);
+ }
+
+ /*
+ * Execute different scripts (defined in the platform specific file)
+ * depending on user specified options.
+ */
+ if (PTOP_ON_VERBOSE) {
+ prog_ptr = (char *)g_dtp_events_v;
+ } else {
+ if (PTOP_ON_CPU)
+ prog_ptr = (char *)g_dtp_events_c;
+ else
+ prog_ptr = (char *)g_dtp_events;
+ }
+
+ if ((prog = dtrace_program_strcompile(dtp, prog_ptr,
+ DTRACE_PROBESPEC_NAME, 0, g_argc, g_argv)) == NULL) {
+ pt_error("%s : failed to compile DTrace program\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_program_exec(dtp, prog, &info) == -1) {
+ pt_error("%s : failed to enable probes\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_setopt(dtp, "aggsize", "128k") == -1) {
+ pt_error("%s : failed to set 'aggsize'\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_setopt(dtp, "aggrate", "0") == -1) {
+ pt_error("%s : failed to set 'aggrate'\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_setopt(dtp, "aggpercpu", 0) == -1) {
+ pt_error("%s : failed to set 'aggpercpu'\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_go(dtp) != 0) {
+ pt_error("%s : dtrace_go() failed\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ if (dtrace_getopt(dtp, "statusrate", &statustime) == -1) {
+ pt_error("%s : failed to get 'statusrate'\n", __FILE__);
+ return (dtrace_errno(dtp));
+ }
+
+ return (0);
+}
+
+int
+pt_events_stat_collect(void)
+{
+ g_p_event = g_event_info;
+ g_tog_p_events = 0;
+
+ if (dtrace_status(dtp) == -1)
+ return (-1);
+
+ if (dtrace_aggregate_snap(dtp) != 0)
+ pt_error("%s : failed to add to aggregate", __FILE__);
+
+ if (dtrace_aggregate_walk_keyvarsorted(dtp, walk, NULL) != 0)
+ pt_error("%s : failed to sort aggregate", __FILE__);
+
+ dtrace_aggregate_clear(dtp);
+
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/powertop.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
+#include "powertop.h"
+
+/*
+ * Global variables, see powertop.h for comments and extern declarations.
+ * These are ordered by type, grouped by usage.
+ */
+double g_ticktime, g_ticktime_usr;
+double g_interval;
+double g_displaytime;
+
+int g_bit_depth;
+int g_total_events, g_tog_p_events;
+int g_npstates, g_max_cstate, g_longest_cstate;
+uint_t g_ncpus;
+uint_t g_ncpus_observed;
+
+processorid_t *g_cpu_table;
+
+hrtime_t g_total_c_time;
+
+uchar_t g_op_mode;
+boolean_t g_gui;
+uint_t g_observed_cpu;
+
+event_info_t g_event_info[EVENT_NUM_MAX];
+event_info_t *g_p_event;
+state_info_t g_cstate_info[NSTATES];
+freq_state_info_t g_pstate_info[NSTATES];
+cpu_power_info_t *g_cpu_power_states;
+suggestion_func *g_suggestion_activate;
+
+boolean_t g_turbo_supported;
+
+uint_t g_argc;
+char **g_argv;
+
+char *optarg;
+
+static const int true = 1;
+
+int
+main(int argc, char **argv)
+{
+ hrtime_t last, now;
+ uint_t features = 0, user_interval = 0;
+ int ncursesinited = 0, index2 = 0, c, ret, dump_count = 0;
+ double last_time;
+ char *endptr;
+
+ static struct option opts[] = {
+ { "dump", 1, NULL, 'd' },
+ { "time", 1, NULL, 't' },
+ { "help", 0, NULL, 'h' },
+ { "cpu", 1, NULL, 'c' },
+ { "verbose", 0, NULL, 'v' },
+ { 0, 0, NULL, 0 }
+ };
+
+ (void) setlocale(LC_ALL, "");
+ (void) bindtextdomain("powertop", "/usr/share/locale");
+ (void) textdomain("powertop");
+
+ pt_set_progname(argv[0]);
+
+ /*
+ * Enumerate the system's CPUs
+ * Populate cpu_table, g_ncpus
+ */
+ if ((g_ncpus = g_ncpus_observed = enumerate_cpus()) == 0)
+ exit(EXIT_FAILURE);
+
+ if ((g_bit_depth = get_bit_depth()) < 0)
+ exit(EXIT_FAILURE);
+
+ g_ticktime = g_ticktime_usr = INTERVAL_DEFAULT;
+ g_displaytime = 0.0;
+ g_op_mode = PTOP_MODE_DEFAULT;
+ g_gui = B_FALSE;
+ g_max_cstate = 0;
+ g_argv = NULL;
+ g_argc = 0;
+ g_observed_cpu = 0;
+ g_turbo_supported = B_FALSE;
+
+ while ((c = getopt_long(argc, argv, "d:t:h:vc:", opts, &index2))
+ != EOF) {
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'd':
+ if (PTOP_ON_DUMP)
+ usage();
+
+ g_op_mode |= PTOP_MODE_DUMP;
+ dump_count = (int)strtod(optarg, &endptr);
+
+ if (dump_count <= 0 || *endptr != NULL)
+ usage();
+ break;
+ case 't':
+ if (user_interval)
+ usage();
+
+ user_interval = 1;
+ g_ticktime = g_ticktime_usr = (double)strtod(optarg,
+ &endptr);
+
+ if (*endptr != NULL || g_ticktime < 1 ||
+ g_ticktime > INTERVAL_MAX)
+ usage();
+ break;
+ case 'v':
+ if (PTOP_ON_CPU || PTOP_ON_VERBOSE)
+ usage();
+
+ g_op_mode |= PTOP_MODE_VERBOSE;
+ break;
+ case 'c':
+ if (PTOP_ON_CPU || PTOP_ON_VERBOSE)
+ usage();
+
+ g_op_mode |= PTOP_MODE_CPU;
+ g_observed_cpu = (uint_t)strtod(optarg, &endptr);
+
+ if (g_observed_cpu >= g_ncpus)
+ usage();
+
+ g_argc = 1;
+ g_ncpus_observed = 1;
+
+ if ((g_argv = malloc(sizeof (char *))) == NULL)
+ return (EXIT_FAILURE);
+
+ if ((*g_argv = malloc(sizeof (char) * 5)) == NULL)
+ return (EXIT_FAILURE);
+
+ (void) snprintf(*g_argv, 5, "%d\0", g_observed_cpu);
+ break;
+ case 'h':
+ default:
+ usage();
+ return (EXIT_USAGE);
+ }
+ }
+
+ if (optind < argc) {
+ usage();
+ }
+
+ (void) printf("%s %s\n\n", TITLE, COPYRIGHT_INTEL);
+
+ /*
+ * If the system is running on battery, find out what's
+ * the kstat module for it
+ */
+ battery_mod_lookup();
+
+ /* Prepare C-state statistics */
+ ret = pt_cpuidle_stat_prepare();
+ if (ret == 0)
+ features |= FEATURE_CSTATE;
+ else
+ /*
+ * PowerTop was unable to run a DTrace program,
+ * most likely for lack of permissions.
+ */
+ exit(EXIT_FAILURE);
+
+ /* Prepare P-state statistics */
+ if (pt_cpufreq_stat_prepare() == 0)
+ features |= FEATURE_PSTATE;
+
+ /* Prepare event statistics */
+ if (pt_events_stat_prepare() != -1)
+ features |= FEATURE_EVENTS;
+
+ /* Prepare turbo statistics */
+ if (pt_turbo_stat_prepare() == 0) {
+ features |= FEATURE_TURBO;
+ }
+
+ (void) printf(_("Collecting data for %.2f second(s) \n"),
+ (float)g_ticktime);
+
+ if (!PTOP_ON_DUMP)
+ g_gui = B_TRUE;
+
+ last = gethrtime();
+
+ while (true) {
+ fd_set rfds;
+ struct timeval tv;
+ int key, reinit = 0;
+ char keychar;
+
+ /*
+ * Sleep for a while waiting either for input (if we're not
+ * in dump mode) or for the timeout to elapse
+ */
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+
+ tv.tv_sec = (long)g_ticktime;
+ tv.tv_usec = (long)((g_ticktime - tv.tv_sec) * 1000000);
+
+ if (!PTOP_ON_DUMP)
+ key = select(1, &rfds, NULL, NULL, &tv);
+ else
+ key = select(1, NULL, NULL, NULL, &tv);
+
+ now = gethrtime();
+
+ g_interval = (double)(now - last)/NANOSEC;
+ last = now;
+
+ g_tog_p_events = 0;
+ g_total_events = 0;
+
+ (void) memset(g_event_info,
+ EVENT_NUM_MAX * sizeof (event_info_t), 0);
+ (void) memset(g_cstate_info, 2 * sizeof (state_info_t), 0);
+
+ /* Collect idle state transition stats */
+ if (features & FEATURE_CSTATE &&
+ pt_cpuidle_stat_collect(g_interval) < 0) {
+ /* Reinitialize C-state statistics */
+ if (pt_cpuidle_stat_prepare() != 0)
+ exit(EXIT_FAILURE);
+
+ reinit = 1;
+ }
+
+ /* Collect frequency change stats */
+ if (features & FEATURE_PSTATE &&
+ pt_cpufreq_stat_collect(g_interval) < 0) {
+ /* Reinitialize P-state statistics */
+ if (pt_cpufreq_stat_prepare() != 0)
+ exit(EXIT_FAILURE);
+
+ reinit = 1;
+ }
+
+ /* Collect event statistics */
+ if (features & FEATURE_EVENTS &&
+ pt_events_stat_collect() < 0) {
+ /* Reinitialize event statistics */
+ if (pt_events_stat_prepare() != 0)
+ exit(EXIT_FAILURE);
+
+ reinit = 1;
+ }
+
+ if (reinit)
+ continue;
+
+ /* Collect turbo statistics */
+ if (features & FEATURE_TURBO &&
+ pt_turbo_stat_collect() < 0) {
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Initialize curses if we're not dumping and
+ * haven't already done it
+ */
+ if (!PTOP_ON_DUMP) {
+ if (!ncursesinited) {
+ initialize_curses();
+ ncursesinited++;
+ }
+ setup_windows();
+ show_title_bar();
+ }
+
+ /* Show CPU power states */
+ if (features & FEATURE_CSTATE)
+ show_cstates();
+
+ /* Show wakeups events affecting PM */
+ if (features & FEATURE_EVENTS) {
+ show_wakeups(g_interval);
+ show_eventstats(g_interval);
+ }
+
+ print_battery();
+
+ g_displaytime = g_displaytime - g_ticktime;
+
+ if (key && !PTOP_ON_DUMP) {
+ keychar = toupper(fgetc(stdin));
+
+ switch (keychar) {
+ case 'Q':
+ cleanup_curses();
+ exit(EXIT_SUCCESS);
+ break;
+ case 'R':
+ g_ticktime = 3;
+ break;
+ }
+ if (keychar == g_suggestion_key &&
+ g_suggestion_activate) {
+ g_suggestion_activate();
+ g_displaytime = -1.0;
+ }
+ }
+ reset_suggestions();
+
+ /* suggests PM */
+ if (geteuid() == 0) {
+ suggest_p_state();
+ } else {
+ suggest_as_root();
+ }
+
+ if (dump_count)
+ dump_count--;
+
+ /* Exits if user requested a dump */
+ if (PTOP_ON_DUMP && !dump_count) {
+ print_all_suggestions();
+ exit(EXIT_SUCCESS);
+ }
+
+ /* No key pressed, will suggest something */
+ if (!key && !dump_count)
+ pick_suggestion();
+
+ /* Refresh display */
+ if (!PTOP_ON_DUMP) {
+ show_title_bar();
+ update_windows();
+ }
+
+ /*
+ * Update the interval based on how long the CPU was in the
+ * longest c-state during the last snapshot. If the user
+ * specified an interval we skip this bit and keep it fixed.
+ */
+ last_time = (((double)g_cstate_info[g_longest_cstate].total_time
+ /g_ncpus)/g_cstate_info[g_longest_cstate].events);
+
+ if (!user_interval)
+ if (last_time < INTERVAL_DEFAULT ||
+ (g_total_events/g_ticktime) < 1)
+ g_ticktime = INTERVAL_DEFAULT;
+ else
+ g_ticktime = INTERVAL_UPDATE(last_time);
+
+ /*
+ * Restore user specified interval after a refresh
+ */
+ if (keychar == 'R' && user_interval)
+ g_ticktime = g_ticktime_usr;
+ }
+ return (EXIT_SUCCESS);
+}
+
+void
+suggest_as_root(void)
+{
+ add_suggestion("Suggestion: run as root to get suggestions"
+ " for reducing system power consumption", 40, NULL, NULL,
+ NULL);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/powertop.h Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#ifndef __INCLUDE_GUARD_POWERTOP_H_
+#define __INCLUDE_GUARD_POWERTOP_H_
+
+#include <sys/types.h>
+#include <libintl.h>
+#include <sys/processor.h>
+
+#define max(A, B) (((A) < (B)) ? (B) : (A))
+
+#define _(STRING) gettext(STRING)
+
+#define TITLE "OpenSolaris PowerTOP version 1.1"
+#define COPYRIGHT_INTEL "(C) 2009 Intel Corporation"
+
+/*
+ * Exit values. stdlib.h defines EXIT_SUCCESS as 0 and
+ * EXIT_FAILURE as 1
+ */
+#define EXIT_USAGE 2
+
+/*
+ * PowerTOP Features
+ * These may not be available everywhere
+ */
+#define FEATURE_CSTATE 0x01
+#define FEATURE_PSTATE 0x02
+#define FEATURE_EVENTS 0x04
+#define FEATURE_TURBO 0x08
+
+#define BIT_DEPTH_BUF 10
+
+#define INTERVAL_DEFAULT 5.0
+#define INTERVAL_MAX 100.0
+#define INTERVAL_UPDATE(l) \
+ ((l/INTERVAL_DEFAULT) * INTERVAL_DEFAULT + INTERVAL_DEFAULT)
+
+#define STATE_NAME_MAX 16
+#define EVENT_NAME_MAX 64
+#define EVENT_NUM_MAX 100
+#define NSTATES 32
+
+/*
+ * Display colors
+ */
+#define PT_COLOR_DEFAULT 1
+#define PT_COLOR_HEADER_BAR 2
+#define PT_COLOR_ERROR 3
+#define PT_COLOR_RED 4
+#define PT_COLOR_YELLOW 5
+#define PT_COLOR_GREEN 6
+#define PT_COLOR_BRIGHT 7
+#define PT_COLOR_BLUE 8
+
+/*
+ * Constants for setup_windows()
+ */
+#define SINGLE_LINE_SW 1
+#define LENGTH_SUGG_SW 2
+#define TITLE_LINE 1
+#define BLANK_LINE 1
+#define NEXT_LINE 1
+#define PTOP_BAR_NSLOTS 10
+#define PTOP_BAR_LENGTH 40
+
+/*
+ * Available op modes
+ */
+#define PTOP_MODE_DEFAULT 0x01
+#define PTOP_MODE_DUMP 0x02
+#define PTOP_MODE_VERBOSE 0x04
+#define PTOP_MODE_CPU 0x08
+
+#define PTOP_ON_DEFAULT (g_op_mode & PTOP_MODE_DEFAULT)
+#define PTOP_ON_DUMP (g_op_mode & PTOP_MODE_DUMP)
+#define PTOP_ON_VERBOSE (g_op_mode & PTOP_MODE_VERBOSE)
+#define PTOP_ON_CPU (g_op_mode & PTOP_MODE_CPU)
+
+/*
+ * Structures and typedefs
+ */
+struct line {
+ char *string;
+ int count;
+};
+
+typedef struct event_info {
+ char offender_name[EVENT_NAME_MAX];
+ char offense_name[EVENT_NAME_MAX];
+ uint64_t total_count;
+} event_info_t;
+
+/*
+ * P/C state information
+ */
+typedef struct state_info {
+ char name[STATE_NAME_MAX];
+ hrtime_t total_time;
+ hrtime_t last_time;
+ double events;
+} state_info_t;
+
+typedef struct freq_state_info {
+ uint64_t speed;
+ hrtime_t total_time;
+} freq_state_info_t;
+
+typedef struct cpu_power_info {
+ uint64_t current_pstate;
+ hrtime_t time_accounted;
+ hrtime_t dtrace_time;
+} cpu_power_info_t;
+
+/*
+ * Turbo mode information
+ */
+typedef struct turbo_info {
+ uint64_t t_mcnt;
+ uint64_t t_acnt;
+} turbo_info_t;
+
+typedef void (suggestion_func)(void);
+
+/*
+ * Global variables
+ */
+extern double g_displaytime;
+
+extern int g_bit_depth;
+
+/*
+ * Event accounting
+ */
+extern int g_total_events;
+extern int g_tog_p_events;
+
+/*
+ * Interval
+ */
+extern double g_ticktime, g_ticktime_usr;
+extern double g_interval;
+
+/*
+ * Command line arguments
+ */
+extern uchar_t g_op_mode;
+extern uint_t g_observed_cpu;
+extern boolean_t g_gui;
+/*
+ * Event info array
+ */
+extern event_info_t g_event_info[EVENT_NUM_MAX];
+extern event_info_t *g_p_event;
+
+/*
+ * Lookup table, sequential CPU id to Solaris CPU id
+ */
+extern processorid_t *g_cpu_table;
+
+/*
+ * Number of idle/frequency states
+ */
+extern int g_npstates;
+extern int g_max_cstate;
+extern int g_longest_cstate;
+
+/*
+ * Total time, used to display different idle states
+ */
+extern hrtime_t g_total_c_time;
+
+/*
+ * P/C state info arrays
+ */
+extern state_info_t g_cstate_info[NSTATES];
+extern freq_state_info_t g_pstate_info[NSTATES];
+
+extern uint_t g_ncpus;
+extern uint_t g_ncpus_observed;
+
+extern char g_status_bar_slots[PTOP_BAR_NSLOTS]
+ [PTOP_BAR_LENGTH];
+
+extern cpu_power_info_t *g_cpu_power_states;
+
+/*
+ * Turbo mode related information
+ */
+extern boolean_t g_turbo_supported;
+extern double g_turbo_ratio;
+
+extern char g_suggestion_key;
+extern suggestion_func *g_suggestion_activate;
+
+/*
+ * DTrace scripts for the events report
+ */
+extern const char *g_dtp_events;
+extern const char *g_dtp_events_v;
+extern const char *g_dtp_events_c;
+
+/*
+ * Arguments for dtrace_program_strcompile(). Contents vary according to
+ * the specified operation mode.
+ */
+extern uint_t g_argc;
+extern char **g_argv;
+
+/*
+ * Platform specific messages
+ */
+extern const char *g_msg_idle_state;
+extern const char *g_msg_freq_state;
+/*
+ * Suggestions related
+ */
+extern void suggest_p_state(void);
+extern void suggest_as_root(void);
+
+/*
+ * See util.c
+ */
+extern void pt_error(char *, ...);
+extern void pt_set_progname(char *);
+extern uint_t enumerate_cpus(void);
+extern void usage(void);
+extern int get_bit_depth(void);
+extern void battery_mod_lookup(void);
+extern int event_compare(const void *, const void *);
+
+/*
+ * Display/curses related
+ */
+extern void show_title_bar(void);
+extern void setup_windows(void);
+extern void initialize_curses(void);
+extern void show_acpi_power_line(uint32_t flag, double rate,
+ double rem_cap, double cap, uint32_t state);
+extern void show_cstates();
+extern void show_wakeups(double interval);
+extern void show_eventstats(double interval);
+extern void show_suggestion(char *sug);
+extern void cleanup_curses(void);
+extern void update_windows(void);
+
+/*
+ * Suggestions
+ */
+extern void pick_suggestion(void);
+extern void add_suggestion(char *text, int weight, char key,
+ char *keystring, suggestion_func *func);
+extern void reset_suggestions(void);
+extern void print_all_suggestions(void);
+extern void print_battery(void);
+
+/*
+ * DTrace stats
+ */
+extern int pt_cpufreq_stat_prepare(void);
+extern int pt_cpufreq_stat_collect(double interval);
+extern int pt_cpuidle_stat_prepare(void);
+extern int pt_cpuidle_stat_collect(double interval);
+extern int pt_events_stat_prepare(void);
+extern int pt_events_stat_collect(void);
+
+/*
+ * Turbo mode related routines
+ */
+extern int pt_turbo_stat_prepare(void);
+extern int pt_turbo_stat_collect(void);
+
+#endif /* __INCLUDE_GUARD_POWERTOP_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/suggestions.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "powertop.h"
+
+struct suggestion;
+
+struct suggestion {
+ struct suggestion *next;
+
+ char *string;
+ int weight;
+ char key;
+ char *keystring;
+
+ suggestion_func *func;
+};
+
+static struct suggestion *suggestions;
+static int total_weight;
+
+static char previous[1024];
+
+void
+reset_suggestions(void)
+{
+ struct suggestion *ptr;
+
+ ptr = suggestions;
+
+ while (ptr) {
+ struct suggestion *next;
+
+ next = ptr->next;
+ free(ptr->string);
+ free(ptr->keystring);
+ free(ptr);
+ ptr = next;
+ }
+
+ suggestions = NULL;
+ (void) strcpy(g_status_bar_slots[8], "");
+
+ g_suggestion_key = -1;
+ g_suggestion_activate = NULL;
+ total_weight = 0;
+}
+
+void
+add_suggestion(char *text, int weight, char key, char *keystring,
+ suggestion_func *func)
+{
+ struct suggestion *new;
+
+ if (!text)
+ return;
+
+ new = malloc(sizeof (struct suggestion));
+
+ if (!new)
+ return;
+
+ (void) memset(new, 0, sizeof (struct suggestion));
+
+ new->string = strdup(text);
+ new->weight = weight;
+ new->key = key;
+
+ if (keystring)
+ new->keystring = strdup(keystring);
+
+ new->next = suggestions;
+ new->func = func;
+ suggestions = new;
+ total_weight += weight;
+}
+
+void
+pick_suggestion(void)
+{
+ int weight, value, running = 0;
+ struct suggestion *ptr;
+
+ (void) strcpy(g_status_bar_slots[8], "");
+ g_suggestion_key = -1;
+ g_suggestion_activate = NULL;
+
+ if (total_weight == 0 || suggestions == NULL) {
+ show_suggestion("");
+ return;
+ }
+
+ weight = total_weight;
+
+ if (strlen(previous) && g_displaytime > 0.0)
+ weight += 50;
+
+ value = rand() % weight;
+ ptr = suggestions;
+
+ while (ptr) {
+ running += ptr->weight;
+
+ if (strcmp(ptr->string, previous) == 0 && g_displaytime > 0.0)
+ running += 50;
+
+ if (running > value) {
+ if (ptr->keystring)
+ (void) strncpy(g_status_bar_slots[8],
+ ptr->keystring, PTOP_BAR_LENGTH);
+
+ g_suggestion_key = ptr->key;
+ g_suggestion_activate = ptr->func;
+
+ show_suggestion(ptr->string);
+
+ if (strcmp(ptr->string, previous)) {
+ g_displaytime = 30.0;
+ (void) strcpy(previous, ptr->string);
+ }
+ return;
+ }
+ ptr = ptr->next;
+ }
+
+ show_suggestion("");
+ (void) memset(previous, 0, sizeof (previous));
+ g_displaytime = -1.0;
+}
+
+void
+print_all_suggestions(void)
+{
+ struct suggestion *ptr;
+
+ for (ptr = suggestions; ptr; ptr = ptr->next)
+ (void) printf("\n%s\n", ptr->string);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/turbo.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dtrace.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+/*
+ * Global turbo related variables definitions
+ */
+boolean_t g_turbo_supported;
+double g_turbo_ratio;
+
+/*
+ * The variables to store kstat snapshot
+ */
+static turbo_info_t *cpu_turbo_info = NULL;
+static turbo_info_t *t_new = NULL;
+
+/*
+ * Perform setup necessary to enumerate and track CPU turbo information
+ */
+static int
+pt_turbo_init(void)
+{
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *knp;
+
+ /*
+ * check if the CPU turbo is supported
+ */
+ if ((kc = kstat_open()) == NULL) {
+ g_turbo_supported = B_FALSE;
+ return (errno);
+ }
+
+ ksp = kstat_lookup(kc, "turbo", 0, NULL);
+ if (ksp == NULL) {
+ g_turbo_supported = B_FALSE;
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ (void) kstat_read(kc, ksp, NULL);
+
+ knp = kstat_data_lookup(ksp, "turbo_supported");
+ if (knp == NULL) {
+ pt_error("%s : couldn't find item turbo_supported\n", __FILE__);
+ g_turbo_supported = B_FALSE;
+ (void) kstat_close(kc);
+ return (-2);
+ }
+
+ /*
+ * Initialize turbo information structure if turbo mode is supported
+ */
+ if (knp->value.ui32) {
+ g_turbo_supported = B_TRUE;
+ cpu_turbo_info = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
+ t_new = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
+ }
+
+ (void) kstat_close(kc);
+ return (0);
+}
+
+/*
+ * Take a snapshot of each CPU's turbo information
+ * by looking through the turbo kstats.
+ */
+static int
+pt_turbo_snapshot(turbo_info_t *turbo_snapshot)
+{
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *knp;
+ int cpu;
+ turbo_info_t *turbo_info;
+
+ if ((kc = kstat_open()) == NULL)
+ return (errno);
+
+ for (cpu = 0; cpu < g_ncpus; cpu++) {
+ turbo_info = &turbo_snapshot[cpu];
+ ksp = kstat_lookup(kc, "turbo", g_cpu_table[cpu], NULL);
+ if (ksp == NULL) {
+ pt_error("%s : couldn't find turbo kstat for CPU "
+ "%d\n", __FILE__, cpu);
+ (void) kstat_close(kc);
+ return (-1);
+ }
+
+ if (kstat_read(kc, ksp, NULL) == -1) {
+ pt_error("%s : couldn't read turbo kstat for "
+ "CPU %d\n", __FILE__, cpu);
+ (void) kstat_close(kc);
+ return (-2);
+ }
+
+ knp = kstat_data_lookup(ksp, "turbo_mcnt");
+ if (knp == NULL) {
+ pt_error("%s : couldn't find turbo mcnt "
+ "kstat for CPU %d\n", __FILE__, cpu);
+ (void) kstat_close(kc);
+ return (-3);
+ }
+
+ /*
+ * snapshot IA32_MPERF_MSR
+ */
+ turbo_info->t_mcnt = knp->value.ui64;
+
+ knp = kstat_data_lookup(ksp, "turbo_acnt");
+ if (knp == NULL) {
+ pt_error("%s : couldn't find turbo acnt "
+ "kstat for CPU %d\n", __FILE__, cpu);
+ (void) kstat_close(kc);
+ return (-4);
+ }
+
+ /*
+ * snapshot IA32_APERF_MSR
+ */
+ turbo_info->t_acnt = knp->value.ui64;
+ }
+
+ if (kstat_close(kc) != 0)
+ pt_error("%s : couldn't close kstat\n", __FILE__);
+
+ return (0);
+}
+
+/*
+ * Turbo support checking and information initialization
+ */
+int
+pt_turbo_stat_prepare(void)
+{
+ int ret;
+
+ ret = pt_turbo_init();
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ ret = pt_turbo_snapshot(cpu_turbo_info);
+
+ if (ret != 0) {
+ pt_error("%s : turbo snapshot failed\n", __FILE__);
+ }
+
+ return (ret);
+}
+
+/*
+ * When doing the statistics collection, we compare two kstat snapshot
+ * and get a delta. the final ratio of performance boost will be worked
+ * out according to the kstat delta
+ */
+int
+pt_turbo_stat_collect(void)
+{
+ int cpu;
+ uint64_t delta_mcnt, delta_acnt;
+ double ratio;
+ int ret;
+
+ /*
+ * Take a snapshot of turbo information to setup turbo_info_t
+ * structure
+ */
+ ret = pt_turbo_snapshot(t_new);
+ if (ret != 0) {
+ pt_error("%s : turbo stat collection failed\n", __FILE__);
+ return (ret);
+ }
+
+ /*
+ * Calculate the kstat delta and work out the performance boost ratio
+ */
+ for (cpu = 0; cpu < g_ncpus; cpu++) {
+ delta_mcnt = t_new[cpu].t_mcnt - cpu_turbo_info[cpu].t_mcnt;
+ delta_acnt = t_new[cpu].t_acnt - cpu_turbo_info[cpu].t_acnt;
+
+ if ((delta_mcnt > delta_acnt) || (delta_mcnt == 0))
+ ratio = 1.0;
+ else
+ ratio = (double)delta_acnt / (double)delta_mcnt;
+ g_turbo_ratio += ratio;
+ }
+
+ g_turbo_ratio = g_turbo_ratio / (double)g_ncpus;
+
+ /*
+ * Update the structure of the kstat for the next time calculation
+ */
+ (void) memcpy(cpu_turbo_info, t_new, g_ncpus * (sizeof (turbo_info_t)));
+
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/common/util.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/systeminfo.h>
+#include <kstat.h>
+#include <errno.h>
+#include "powertop.h"
+
+static char PROG_FMT[] = "%s: ";
+static char ERR_FMT[] = ": %s";
+static char *progname;
+
+void
+pt_set_progname(char *name)
+{
+ progname = basename(name);
+}
+
+/*PRINTFLIKE1*/
+void
+pt_error(char *format, ...)
+{
+ int err = errno;
+ va_list alist;
+
+ if (g_gui)
+ return;
+
+ if (progname != NULL)
+ (void) fprintf(stderr, PROG_FMT, progname);
+
+ va_start(alist, format);
+ (void) vfprintf(stderr, format, alist);
+ va_end(alist);
+
+ if (strchr(format, '\n') == NULL)
+ (void) fprintf(stderr, gettext(ERR_FMT), strerror(err));
+}
+
+/*
+ * Returns the number of online CPUs.
+ */
+uint_t
+enumerate_cpus(void)
+{
+ int cpuid;
+ int max, cpus_conf;
+ uint_t ncpus = 0;
+
+ max = sysconf(_SC_CPUID_MAX);
+ cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
+
+ /* Fall back to one CPU if any of the sysconf calls above failed */
+ if (max == -1 || cpus_conf == -1) {
+ max = cpus_conf = 1;
+ }
+
+ if ((g_cpu_table = malloc(cpus_conf * sizeof (processorid_t))) == NULL)
+ return (0);
+
+ for (cpuid = 0; cpuid < max; cpuid++) {
+ if (p_online(cpuid, P_STATUS) != -1) {
+ g_cpu_table[ncpus] = cpuid;
+ ncpus++;
+ }
+ }
+ return (ncpus);
+}
+
+void
+usage(void)
+{
+ (void) fprintf(stderr, "%s %s\n\n", TITLE, COPYRIGHT_INTEL);
+ (void) fprintf(stderr, "Usage: powertop [option]\n");
+ (void) fprintf(stderr, " -d, --dump [count] Read wakeups count "
+ "times and print list of top offenders\n");
+ (void) fprintf(stderr, " -t, --time [interval] Default time to gather "
+ "data in seconds [1-100s]\n");
+ (void) fprintf(stderr, " -v, --verbose Verbose mode, reports "
+ "kernel cyclic activity\n");
+ (void) fprintf(stderr, " -c, --cpu [CPU] Only observe a specific"
+ " CPU\n");
+ (void) fprintf(stderr, " -h, --help Show this help "
+ "message\n");
+
+ exit(EXIT_USAGE);
+}
+
+int
+get_bit_depth(void)
+{
+ /*
+ * This little routine was derived from isainfo.c to look up
+ * the system's bit depth. It feeds a 10 byte long buffer to
+ * sysinfo (we only need the first word, sysinfo truncates and
+ * \0 terminates the rest) from which we figure out which isa
+ * we're running on.
+ */
+ char buf[BIT_DEPTH_BUF];
+
+ if (sysinfo(SI_ARCHITECTURE_64, buf, BIT_DEPTH_BUF) == -1)
+ if (sysinfo(SI_ARCHITECTURE_32, buf, BIT_DEPTH_BUF) == -1)
+ return (-2);
+
+ if (strcmp(buf, "sparc") == 0 || strcmp(buf, "i386") == 0)
+ return (32);
+
+ if (strcmp(buf, "sparcv9") == 0 || strcmp(buf, "amd64") == 0)
+ return (64);
+
+ return (-3);
+}
+
+/*
+ * Simple integer comparison routine for the event report qsort(3C).
+ */
+int
+event_compare(const void *p1, const void *p2)
+{
+ event_info_t i = *((event_info_t *)p1);
+ event_info_t j = *((event_info_t *)p2);
+
+ if (i.total_count > j.total_count)
+ return (-1);
+
+ if (i.total_count < j.total_count)
+ return (1);
+
+ return (0);
+}
--- a/usr/src/cmd/powertop/cpufreq.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,425 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <dtrace.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-#define HZ2MHZ(speed) ((speed) / 1000000)
-
-static uint64_t max_cpufreq = 0;
-static dtrace_hdl_t *g_dtp;
-
-/*
- * Enabling PM through /etc/power.conf
- * See suggest_p_state()
- */
-static char default_conf[] = "/etc/power.conf";
-static char default_pmconf[] = "/usr/sbin/pmconfig";
-static char cpupm_enable[] = " echo cpupm enable >> /etc/power.conf";
-static char cpupm_treshold[] = " echo cpu-threshold 1s >> /etc/power.conf";
-
-/*
- * Buffer containing DTrace program to track CPU frequency transitions
- */
-static const char *pt_cpufreq_dtrace_prog =
-""
-"hrtime_t last[int];"
-""
-"BEGIN"
-"{"
-" begin = timestamp;"
-"}"
-""
-":::cpu-change-speed"
-"/last[(processorid_t)arg0] != 0/"
-"{"
-" this->cpu = (processorid_t)arg0;"
-" this->oldspeed = (uint32_t)(arg1/1000000);"
-" @times[this->cpu, this->oldspeed] = sum(timestamp - last[this->cpu]);"
-" last[this->cpu] = timestamp;"
-"}"
-":::cpu-change-speed"
-"/last[(processorid_t)arg0] == 0/"
-"{"
-" this->cpu = (processorid_t)arg0;"
-" this->oldspeed = (uint32_t)(arg1/1000000);"
-" @times[this->cpu, this->oldspeed] = sum(timestamp - begin);"
-" last[this->cpu] = timestamp;"
-"}";
-
-static int pt_cpufreq_snapshot(void);
-static int pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *, void *);
-
-/*
- * Perform setup necessary to enumerate and track CPU speed changes
- */
-int
-pt_cpufreq_stat_prepare(void)
-{
- dtrace_prog_t *prog;
- dtrace_proginfo_t info;
- dtrace_optval_t statustime;
-
- kstat_ctl_t *kc;
- kstat_t *ksp;
- kstat_named_t *knp;
-
- pstate_info_t *state;
- char *s, *token;
- int err;
-
- state = pstate_info;
- cpu_power_states = calloc((size_t)g_ncpus, sizeof (cpu_power_info_t));
-
- /*
- * Enumerate the CPU frequencies
- */
- if ((kc = kstat_open()) == NULL)
- return (errno);
-
- ksp = kstat_lookup(kc, "cpu_info", cpu_table[0], NULL);
-
- if (ksp == NULL)
- return (errno);
-
- (void) kstat_read(kc, ksp, NULL);
-
- knp = kstat_data_lookup(ksp, "supported_frequencies_Hz");
- s = knp->value.str.addr.ptr;
-
- npstates = 0;
-
- for (token = strtok(s, ":"), s = NULL;
- NULL != token && npstates < NSTATES;
- token = strtok(NULL, ":")) {
-
- state->speed = HZ2MHZ(atoll(token));
-
- if (state->speed > max_cpufreq)
- max_cpufreq = state->speed;
-
- state->total_time = (uint64_t)0;
-
- npstates++;
- state++;
- }
-
- if (token != NULL)
- pt_error("%s : exceeded NSTATES\n", __FILE__);
-
- (void) kstat_close(kc);
-
- /*
- * Return if speed transition is not supported
- */
- if (npstates < 2)
- return (-1);
-
- /*
- * Setup DTrace to look for CPU frequency changes
- */
- if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
- pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
- dtrace_errmsg(NULL, err));
- return (-2);
- }
- if ((prog = dtrace_program_strcompile(g_dtp, pt_cpufreq_dtrace_prog,
- DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
- pt_error("%s : cpu-change-speed probe unavailable\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
- pt_error("%s : failed to enable speed probe\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) {
- pt_error("%s : failed to set speed 'aggsize'\n", __FILE__);
- }
- if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) {
- pt_error("%s : failed to set speed 'aggrate'\n", __FILE__);
- }
- if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) {
- pt_error("%s : failed to set speed 'aggpercpu'\n", __FILE__);
- }
- if (dtrace_go(g_dtp) != 0) {
- pt_error("%s : failed to start speed observation", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) {
- pt_error("%s : failed to get speed 'statusrate'\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
-
- return (0);
-}
-
-/*
- * The DTrace probes have already been enabled, and are tracking
- * CPU speed transitions. Take a snapshot of the aggregations, and
- * look for any CPUs that have made a speed transition over the last
- * sampling interval. Note that the aggregations may be empty if no
- * speed transitions took place over the last interval. In that case,
- * notate that we have already accounted for the time, so that when
- * we do encounter a speed transition in a future sampling interval
- * we can subtract that time back out.
- */
-int
-pt_cpufreq_stat_collect(double interval)
-{
- int cpu, i, ret;
- uint64_t speed;
- hrtime_t duration;
- cpu_power_info_t *cpu_pow;
-
- /*
- * Zero out the interval time reported by DTrace for
- * this interval
- */
- for (i = 0; i < npstates; i++)
- pstate_info[i].total_time = 0;
-
- for (i = 0; i < g_ncpus; i++)
- cpu_power_states[i].dtrace_time = 0;
-
- if (dtrace_status(g_dtp) == -1)
- return (-1);
-
- if (dtrace_aggregate_snap(g_dtp) != 0)
- pt_error("%s : failed to add to stats aggregation", __FILE__);
-
- if (dtrace_aggregate_walk_keyvarsorted(g_dtp, pt_cpufreq_dtrace_walk,
- NULL) != 0)
- pt_error("%s : failed to sort stats aggregation", __FILE__);
-
- dtrace_aggregate_clear(g_dtp);
-
- if ((ret = pt_cpufreq_snapshot()) != 0) {
- pt_error("%s : failed to add to stats aggregation", __FILE__);
- return (ret);
- }
-
- for (cpu = 0; cpu < g_ncpus; cpu++) {
- cpu_pow = &cpu_power_states[cpu];
-
- speed = cpu_pow->current_pstate;
-
- duration = (hrtime_t)((interval * NANOSEC)) -
- cpu_pow->dtrace_time;
-
- for (i = 0; i < npstates; i++) {
- if (pstate_info[i].speed == speed) {
- pstate_info[i].total_time += duration;
- cpu_pow->time_accounted += duration;
- }
- }
- }
-
- return (0);
-}
-
-/*
- * Take a snapshot of each CPU's speed by looking through the cpu_info kstats.
- */
-static int
-pt_cpufreq_snapshot(void)
-{
- kstat_ctl_t *kc;
- kstat_t *ksp;
- kstat_named_t *knp;
- int cpu;
- cpu_power_info_t *state;
-
- if ((kc = kstat_open()) == NULL)
- return (errno);
-
- for (cpu = 0; cpu < g_ncpus; cpu++) {
- ksp = kstat_lookup(kc, "cpu_info", cpu_table[cpu], NULL);
- if (ksp == NULL) {
- pt_error("%s : couldn't find cpu_info kstat for CPU "
- "%d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (1);
- }
-
- if (kstat_read(kc, ksp, NULL) == -1) {
- pt_error("%s : couldn't read cpu_info kstat for "
- "CPU %d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (2);
- }
-
- knp = kstat_data_lookup(ksp, "current_clock_Hz");
- if (knp == NULL) {
- pt_error("%s : couldn't find current_clock_Hz "
- "kstat for CPU %d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (3);
- }
-
- state = &cpu_power_states[cpu];
- state->current_pstate = HZ2MHZ(knp->value.ui64);
- }
-
- if (kstat_close(kc) != 0)
- pt_error("%s : couldn't close kstat\n", __FILE__);
-
- return (0);
-}
-
-/*
- * DTrace aggregation walker that sorts through a snapshot of the
- * aggregation data collected during firings of the cpu-change-speed
- * probe.
- */
-/*ARGSUSED*/
-static int
-pt_cpufreq_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
-{
- dtrace_aggdesc_t *aggdesc = data->dtada_desc;
- dtrace_recdesc_t *cpu_rec, *speed_rec;
- cpu_power_info_t *cpu_pow;
- int32_t cpu;
- uint64_t speed;
- hrtime_t dt_state_time = 0;
- int i;
-
- if (strcmp(aggdesc->dtagd_name, "times") == 0) {
- cpu_rec = &aggdesc->dtagd_rec[1];
- speed_rec = &aggdesc->dtagd_rec[2];
-
- for (i = 0; i < g_ncpus; i++) {
- /* LINTED - alignment */
- dt_state_time += *((hrtime_t *)(data->dtada_percpu[i]));
- }
-
- /* LINTED - alignment */
- cpu = *(int32_t *)(data->dtada_data + cpu_rec->dtrd_offset);
- /* LINTED - alignment */
- speed = *(uint64_t *)(data->dtada_data +
- speed_rec->dtrd_offset);
-
- if (speed == 0) {
- speed = max_cpufreq;
- }
-
- /*
- * We have an aggregation record for "cpu" being at "speed"
- * for an interval of "n" nanoseconds. The reported interval
- * may exceed the powertop sampling interval, since we only
- * notice during potentially infrequent firings of the
- * "speed change" DTrace probe. In this case powertop would
- * have already accounted for the portions of the interval
- * that happened during prior powertop sampings, so subtract
- * out time already accounted.
- */
- cpu_pow = &cpu_power_states[cpu];
-
- for (i = 0; i < npstates; i++) {
- if (pstate_info[i].speed == speed) {
- if (cpu_pow->time_accounted > 0) {
- if (dt_state_time == 0)
- continue;
- if (dt_state_time >
- cpu_pow->time_accounted) {
- dt_state_time -=
- cpu_pow->time_accounted;
- cpu_pow->time_accounted = 0;
- }
- }
- pstate_info[i].total_time += dt_state_time;
- cpu_pow->dtrace_time += dt_state_time;
- }
- }
- }
- return (DTRACE_AGGWALK_NEXT);
-}
-
-/*
- * Used as a suggestion, sets PM in /etc/power.conf and
- * a 1sec threshold, then calls /usr/sbin/pmconfig
- */
-void
-enable_p_state(void)
-{
- (void) system(cpupm_enable);
- (void) system(cpupm_treshold);
- (void) system(default_pmconf);
-}
-
-/*
- * Checks if PM is enabled in /etc/power.conf, enabling if not
- */
-void
-suggest_p_state(void)
-{
- char line[1024];
- FILE *file;
-
- /*
- * Return if speed transition is not supported
- */
- if (npstates < 2)
- return;
-
- file = fopen(default_conf, "r");
-
- if (!file)
- return;
-
- (void) memset(line, 0, 1024);
-
- while (fgets(line, 1023, file)) {
- if (strstr(line, "cpupm")) {
- if (strstr(line, "enable")) {
- (void) fclose(file);
- return;
- }
- }
- }
-
- add_suggestion("Suggestion: enable CPU power management by "
- "pressing the P key", 40, 'P', "P - Enable p-state",
- enable_p_state);
-
- (void) fclose(file);
-}
--- a/usr/src/cmd/powertop/cpuidle.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <string.h>
-#include <dtrace.h>
-#include "powertop.h"
-
-static dtrace_hdl_t *g_dtp;
-
-/*
- * Buffer containing DTrace program to track CPU idle state transitions
- */
-static const char *pt_cpuidle_dtrace_prog =
-":::idle-state-transition"
-"/arg0 != 0/"
-"{"
-" self->start = timestamp;"
-" self->state = arg0;"
-"}"
-""
-":::idle-state-transition"
-"/arg0 == 0 && self->start/"
-"{"
-" @number[self->state] = count();"
-" @times[self->state] = sum((timestamp - self->start)/1000000);"
-" self->start = 0;"
-" self->state = 0;"
-"}";
-
-static int pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *, void *);
-
-/*
- * Perform setup necessary to track CPU idle state transitions
- */
-int
-pt_cpuidle_stat_prepare(void)
-{
- dtrace_prog_t *prog;
- dtrace_proginfo_t info;
- dtrace_optval_t statustime;
- int err;
-
- if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
- pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
- dtrace_errmsg(NULL, err));
- return (-1);
- }
- if ((prog = dtrace_program_strcompile(g_dtp, pt_cpuidle_dtrace_prog,
- DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
- pt_error("%s : C-State DTrace probes unavailable\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
- pt_error("%s : failed to enable C State probes\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) {
- pt_error("%s : failed to set C-state 'aggsize'\n", __FILE__);
- }
- if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) {
- pt_error("%s : failed to set C-state'aggrate'\n", __FILE__);
- }
- if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) {
- pt_error("%s : failed to set C-state 'aggpercpu'\n", __FILE__);
- }
- if (dtrace_go(g_dtp) != 0) {
- pt_error("%s : failed to start C-state observation", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) {
- pt_error("%s : failed to get C-state 'statusrate'\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- return (0);
-}
-
-/*
- * The DTrace probes have been enabled, and are tracking CPU idle state
- * transitions. Take a snapshot of the aggregations, and invoke the aggregation
- * walker to process any records. The walker does most of the accounting work
- * chalking up time spent into the cstate_info structure.
- */
-int
-pt_cpuidle_stat_collect(double interval)
-{
- int i;
- hrtime_t t = 0;
-
- /*
- * Zero out the interval time reported by DTrace for
- * this interval
- */
- for (i = 0; i < NSTATES; i++) {
- cstate_info[i].total_time = 0;
- cstate_info[i].events = 0;
- }
-
- /*
- * Assume that all the time spent in this interval will
- * be the default "0" state. The DTrace walker will reallocate
- * time out of the default bucket as it processes aggregation
- * records for time spent in other states.
- */
- cstate_info[0].total_time = (long)(interval * g_ncpus * 1000);
-
- if (dtrace_status(g_dtp) == -1)
- return (-1);
-
- if (dtrace_aggregate_snap(g_dtp) != 0)
- pt_error("%s : failed to add to aggregation", __FILE__);
-
- if (dtrace_aggregate_walk_keyvarsorted(g_dtp, pt_cpuidle_dtrace_walk,
- NULL) != 0)
- pt_error("%s : failed to sort aggregation", __FILE__);
-
- dtrace_aggregate_clear(g_dtp);
-
- /*
- * Populate cstate_info with the correct amount of time spent
- * in each C state and update the number of C states in max_cstate
- */
- total_c_time = 0;
- for (i = 0; i < NSTATES; i++) {
- if (cstate_info[i].total_time > 0) {
- total_c_time += cstate_info[i].total_time;
- if (i > max_cstate)
- max_cstate = i;
- if (cstate_info[i].last_time > t) {
- t = cstate_info[i].last_time;
- longest_cstate = i;
- }
- }
- }
-
- return (0);
-}
-
-/*
- * DTrace aggregation walker that sorts through a snapshot of data records
- * collected during firings of the idle-state-transition probe.
- *
- * XXX A way of querying the current idle state for a CPU is needed in addition
- * to logic similar to that in cpufreq.c
- */
-/*ARGSUSED*/
-static int
-pt_cpuidle_dtrace_walk(const dtrace_aggdata_t *data, void *arg)
-{
- dtrace_aggdesc_t *aggdesc = data->dtada_desc;
- dtrace_recdesc_t *rec;
- uint64_t n = 0;
- int32_t state;
- int i;
-
- rec = &aggdesc->dtagd_rec[1];
- /* LINTED - alignment */
- state = *(int32_t *)(data->dtada_data + rec->dtrd_offset);
-
- if (strcmp(aggdesc->dtagd_name, "number") == 0) {
- for (i = 0; i < g_ncpus; i++) {
- /* LINTED - alignment */
- n += *((uint64_t *)(data->dtada_percpu[i]));
- }
- total_events += n;
- cstate_info[state].events += n;
- }
- else
- if (strcmp(aggdesc->dtagd_name, "times") == 0) {
- for (i = 0; i < g_ncpus; i++) {
- /* LINTED - alignment */
- n += *((uint64_t *)(data->dtada_percpu[i]));
- }
- cstate_info[state].last_time = n;
- cstate_info[state].total_time += n;
- if (cstate_info[0].total_time >= n)
- cstate_info[0].total_time -= n;
- }
-
- return (DTRACE_AGGWALK_NEXT);
-}
--- a/usr/src/cmd/powertop/display.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <curses.h>
-#include "powertop.h"
-
-static WINDOW *title_bar_window;
-static WINDOW *cstate_window;
-static WINDOW *wakeup_window;
-static WINDOW *acpi_power_window;
-static WINDOW *eventstat_window;
-static WINDOW *suggestion_window;
-static WINDOW *status_bar_window;
-
-#define print(win, y, x, fmt, args...) \
- if (dump) \
- (void) printf(fmt, ## args); \
- else \
- (void) mvwprintw(win, y, x, fmt, ## args);
-
-char status_bar_slots[10][40];
-int maxx, maxy;
-
-static void
-zap_windows(void)
-{
- if (title_bar_window) {
- (void) delwin(title_bar_window);
- title_bar_window = NULL;
- }
- if (cstate_window) {
- (void) delwin(cstate_window);
- cstate_window = NULL;
- }
- if (wakeup_window) {
- (void) delwin(wakeup_window);
- wakeup_window = NULL;
- }
- if (acpi_power_window) {
- (void) delwin(acpi_power_window);
- acpi_power_window = NULL;
- }
- if (eventstat_window) {
- (void) delwin(eventstat_window);
- eventstat_window = NULL;
- }
- if (suggestion_window) {
- (void) delwin(suggestion_window);
- suggestion_window = NULL;
- }
- if (status_bar_window) {
- (void) delwin(status_bar_window);
- status_bar_window = NULL;
- }
-}
-
-void
-cleanup_curses(void)
-{
- (void) endwin();
-}
-
-/*
- * This part was re-written to be human readable and easy to modify. Please
- * try to keep it that way and help us save some time.
- *
- * Friendly reminder:
- * subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x)
- */
-void
-setup_windows(void)
-{
- /*
- * These variables are used to properly set the initial y position and
- * number of lines in each subwindow, as the number of supported CPU
- * states affects their placement.
- */
- int cstate_lines, event_lines, pos_y;
-
- getmaxyx(stdscr, maxy, maxx);
-
- zap_windows();
-
- cstate_lines = TITLE_LINE + max((max_cstate+1), npstates);
-
- pos_y = 0;
- title_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
- pos_y += NEXT_LINE + BLANK_LINE;
- cstate_window = subwin(stdscr, cstate_lines, maxx, pos_y, 0);
-
- pos_y += cstate_lines + BLANK_LINE;
- wakeup_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
- pos_y += NEXT_LINE;
- acpi_power_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
- pos_y += NEXT_LINE + BLANK_LINE;
- event_lines = maxy - SINGLE_LINE_SW - NEXT_LINE - LENGTH_SUGG_SW -
- pos_y;
- eventstat_window = subwin(stdscr, event_lines, maxx, pos_y, 0);
-
- pos_y += event_lines + NEXT_LINE;
- suggestion_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
- pos_y += BLANK_LINE + NEXT_LINE;
- status_bar_window = subwin(stdscr, SINGLE_LINE_SW, maxx, pos_y, 0);
-
- (void) strcpy(status_bar_slots[0], _(" Q - Quit "));
- (void) strcpy(status_bar_slots[1], _(" R - Refresh "));
-
- (void) werase(stdscr);
- (void) wrefresh(status_bar_window);
-}
-
-void
-initialize_curses(void)
-{
- (void) initscr();
- (void) start_color();
-
- /*
- * Enable keyboard mapping
- */
- (void) keypad(stdscr, TRUE);
-
- /*
- * Tell curses not to do NL->CR/NL on output
- */
- (void) nonl();
-
- /*
- * Take input chars one at a time, no wait for \n
- */
- (void) cbreak();
-
- /*
- * Dont echo input
- */
- (void) noecho();
-
- /*
- * Turn off cursor
- */
- (void) curs_set(0);
-
- (void) init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
- (void) init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
- (void) init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
- (void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
- (void) init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
- (void) init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
- (void) init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
- (void) init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
-
- (void) atexit(cleanup_curses);
-}
-
-void
-show_title_bar(void)
-{
- int i, x = 0, y = 0;
- char title_pad[10];
-
- (void) wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
- (void) wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
- (void) werase(title_bar_window);
-
- (void) snprintf(title_pad, 10, "%%%ds",
- (maxx - strlen(TITLE))/2 + strlen(TITLE));
- /* LINTED: E_SEC_PRINTF_VAR_FMT */
- print(title_bar_window, y, x, title_pad, TITLE);
-
- (void) wrefresh(title_bar_window);
- (void) werase(status_bar_window);
-
- for (i = 0; i < 10; i++) {
- if (strlen(status_bar_slots[i]) == 0)
- continue;
- (void) wattron(status_bar_window, A_REVERSE);
- print(status_bar_window, y, x, "%s", status_bar_slots[i]);
- (void) wattroff(status_bar_window, A_REVERSE);
- x += strlen(status_bar_slots[i]) + 1;
- }
- (void) wnoutrefresh(status_bar_window);
-}
-
-void
-show_cstates(void)
-{
- char c[100];
- int i;
- double total_pstates = 0.0, avg, res;
- uint64_t p0_speed, p1_speed;
-
- if (!dump) {
- (void) werase(cstate_window);
- (void) wattrset(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
- (void) wbkgd(cstate_window, COLOR_PAIR(PT_COLOR_DEFAULT));
- }
-
- print(cstate_window, 0, 0, "%s", "Cn\t\t\tAvg residency\n");
-
- res = (((double)cstate_info[0].total_time / total_c_time)) * 100;
- (void) sprintf(c, "C0 (cpu running)\t\t(%.1f%%)\n", (float)res);
- print(cstate_window, 1, 0, "%s", c);
-
- for (i = 1; i <= max_cstate; i++) {
- /*
- * In situations where the load is too intensive, the system
- * might not transition at all.
- */
- if (cstate_info[i].events > 0)
- avg = (((double)cstate_info[i].total_time/g_ncpus)/
- cstate_info[i].events);
- else
- avg = 0;
-
- res = ((double)cstate_info[i].total_time/total_c_time) * 100;
-
- (void) sprintf(c, "C%d\t\t\t%.1fms\t(%.1f%%)\n", i, (float)avg,
- (float)res);
- print(cstate_window, i + 1, 0, "%s", c);
- }
-
- print(cstate_window, 0, 48, "%s", "P-states (frequencies)\n");
-
- if (npstates < 2) {
- (void) sprintf(c, "%4lu Mhz\t%.1f%%",
- (long)pstate_info[0].speed, 100.0);
- print(cstate_window, 1, 48, "%s\n", c);
- } else {
- for (i = 0; i < npstates; i++) {
- total_pstates += (double)(pstate_info[i].total_time/
- g_ncpus/1000000);
- }
-
- /*
- * display ACPI_PSTATE from P(n) to P(1)
- */
- for (i = 0; i < npstates - 1; i++) {
- (void) sprintf(c, "%4lu Mhz\t%.1f%%",
- (long)pstate_info[i].speed,
- 100 * (pstate_info[i].total_time/g_ncpus/1000000
- /total_pstates));
- print(cstate_window, i+1, 48, "%s\n", c);
- }
-
- /*
- * display ACPI_PSTATE P0 according to if turbo
- * mode is supported
- */
- if (g_turbo_supported) {
- p1_speed = pstate_info[npstates - 2].speed;
- /*
- * if g_turbo_ratio <= 1.0, it will be ignored.
- * we display P(0) as P(1) + 1.
- */
- if (g_turbo_ratio <= 1.0) {
- p0_speed = p1_speed + 1;
- }
- /*
- * if g_turbo_ratio > 1.0, that means turbo mode works.
- * So, P(0) = ratio * P(1);
- */
- else {
- p0_speed = (uint64_t)(p1_speed * g_turbo_ratio);
- if (p0_speed < (p1_speed + 1))
- p0_speed = p1_speed + 1;
- }
- /*
- * reset the ratio for the next round
- */
- g_turbo_ratio = 0.0;
-
- /*
- * setup the string for the display
- */
- (void) sprintf(c, "%4lu Mhz(turbo)\t%.1f%%",
- (long)p0_speed,
- 100 * (pstate_info[i].total_time/g_ncpus/1000000
- /total_pstates));
- } else {
- (void) sprintf(c, "%4lu Mhz\t%.1f%%",
- (long)pstate_info[i].speed,
- 100 * (pstate_info[i].total_time/g_ncpus/1000000
- /total_pstates));
- }
- print(cstate_window, i+1, 48, "%s\n", c);
-
- }
- if (!dump)
- (void) wnoutrefresh(cstate_window);
-}
-
-void
-show_acpi_power_line(uint32_t flag, double rate, double rem_cap, double cap,
- uint32_t state)
-{
- char buffer[1024];
-
- (void) sprintf(buffer, _("no ACPI power usage estimate available"));
-
- if (!dump)
- (void) werase(acpi_power_window);
- if (flag) {
- char *c;
- (void) sprintf(buffer, "Power usage (ACPI estimate): %.3fW",
- rate);
- (void) strcat(buffer, " ");
- c = &buffer[strlen(buffer)];
- switch (state) {
- case 0:
- (void) sprintf(c, "(running on AC power, fully "
- "charged)");
- break;
- case 1:
- (void) sprintf(c, "(discharging: %3.1f hours)",
- rem_cap/rate);
- break;
- case 2:
- (void) sprintf(c, "(charging: %3.1f hours)",
- (cap - rem_cap)/rate);
- break;
- case 4:
- (void) sprintf(c, "(##critically low battery power##)");
- break;
- }
-
- }
- print(acpi_power_window, 0, 0, "%s\n", buffer);
- if (!dump)
- (void) wnoutrefresh(acpi_power_window);
-}
-
-void
-show_wakeups(double interval)
-{
- char c[100];
-
- if (!dump) {
- (void) werase(wakeup_window);
- (void) wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
- (void) wattron(wakeup_window, A_BOLD);
- }
- (void) sprintf(c, "Wakeups-from-idle per second: %4.1f\tinterval: "
- "%.1fs", (double)(total_events/interval), interval);
- print(wakeup_window, 0, 0, "%s\n", c);
- if (!dump)
- (void) wnoutrefresh(wakeup_window);
-}
-
-void
-show_eventstats(double interval)
-{
- char c[100];
- int i;
- double events;
- event_info_t *p_event = event_info;
-
- if (!dump) {
- (void) werase(eventstat_window);
- (void) wattrset(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
- (void) wbkgd(eventstat_window, COLOR_PAIR(PT_COLOR_DEFAULT));
- }
-
- /*
- * Sort the event report list
- */
- if (top_events > EVENT_NUM_MAX)
- top_events = EVENT_NUM_MAX;
-
- qsort((void *)event_info, top_events, sizeof (event_info_t),
- event_compare);
-
- print(eventstat_window, 0, 0, "%s", "Top causes for wakeups:\n");
-
- for (i = 0; i < top_events; i++, p_event++) {
-
- if (total_events > 0)
- events = (double)p_event->total_count/
- (double)total_events;
- else
- events = 0;
-
- (void) sprintf(c, "%4.1f%% (%5.1f)", 100 * events,
- (double)p_event->total_count/interval);
- print(eventstat_window, i+1, 0, "%s", c);
- print(eventstat_window, i+1, 16, "%20s :",
- p_event->offender_name);
- print(eventstat_window, i+1, 40, "%-64s\n",
- p_event->offense_name);
- }
- if (!dump)
- (void) wnoutrefresh(eventstat_window);
-}
-
-void
-show_suggestion(char *sug)
-{
- (void) werase(suggestion_window);
- print(suggestion_window, 0, 0, "%s", sug);
- (void) wnoutrefresh(suggestion_window);
-}
-
-void
-update_windows(void)
-{
- (void) doupdate();
-}
--- a/usr/src/cmd/powertop/events.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <dtrace.h>
-#include "powertop.h"
-
-static dtrace_hdl_t *g_dtp;
-/*
- * DTrace scripts for observing interrupts, callouts and cyclic events
- * that cause CPU activity. Such activity prevents the processor from
- * entering lower power states and reducing power consumption.
- *
- * g_prog is the default script
- */
-static const char *g_prog =
-"interrupt-complete"
-"/arg0 != NULL && arg3 !=0/"
-"{"
-" this->devi = (struct dev_info *)arg0;"
-" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
-" this->devi->devi_instance] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
-"{"
-" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
-" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
-"{"
-" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
-"}"
-""
-"sdt:::cyclic-start"
-"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
-"{"
-" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
-"}"
-""
-"sysinfo:::xcalls"
-"/pid != $pid/"
-"{"
-" @events_x[execname] = sum(arg0);"
-"}";
-
-/*
- * g_prog_V is enabled through the -v option, it includes cyclic events
- * in the report, allowing a complete view of system activity
- */
-static const char *g_prog_v =
-"interrupt-complete"
-"/arg0 != NULL && arg3 !=0/"
-"{"
-" this->devi = (struct dev_info *)arg0;"
-" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
-" this->devi->devi_instance] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
-"{"
-" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
-" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
-"}"
-""
-"sdt:::callout-start"
-"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
-"{"
-" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
-"}"
-""
-"sdt:::cyclic-start"
-"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
-" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
-"{"
-" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
-"}"
-""
-"sysinfo:::xcalls"
-"/pid != $pid/"
-"{"
-" @events_x[execname] = sum(arg0);"
-"}";
-
-/*ARGSUSED*/
-static int
-walk(const dtrace_aggdata_t *data, void *arg)
-{
- dtrace_aggdesc_t *aggdesc = data->dtada_desc;
- dtrace_recdesc_t *rec1, *rec2;
- dtrace_syminfo_t dts;
- char *offense_name;
- uint64_t offender_addr;
- int32_t *instance;
- int i;
- uint64_t n = 0;
- GElf_Sym sym;
-
- if (top_events >= EVENT_NUM_MAX)
- return (0);
-
- rec1 = &aggdesc->dtagd_rec[1];
- rec2 = &aggdesc->dtagd_rec[2];
-
- /*
- * Report interrupts
- */
- if (strcmp(aggdesc->dtagd_name, "interrupts") == 0) {
- offense_name = data->dtada_data + rec1->dtrd_offset;
-
- /* LINTED - alignment */
- instance = (int32_t *)(data->dtada_data + rec2->dtrd_offset);
- (void) snprintf((char *)(p_event->offender_name),
- EVENT_NAME_MAX, "%s", "<interrupt>");
- (void) snprintf((char *)(p_event->offense_name), EVENT_NAME_MAX,
- "%s#%d", offense_name, *instance);
- /*
- * Report kernel events
- */
- } else if (strcmp(aggdesc->dtagd_name, "events_k") == 0) {
-
- (void) snprintf((char *)(p_event->offender_name),
- EVENT_NAME_MAX, "%s", "<kernel>");
-
- /*
- * Casting offender_addr to the wrong type will cause
- * dtrace_lookup_by_addr to return 0 and the report
- * to show an address instead of a name.
- */
- switch (bit_depth) {
- case 32:
- /* LINTED - alignment */
- offender_addr = *(uint32_t *)(data->dtada_data +
- rec1->dtrd_offset);
- break;
- case 64:
- /* LINTED - alignment */
- offender_addr = *(uint64_t *)(data->dtada_data +
- rec1->dtrd_offset);
- break;
- }
-
- /*
- * We have the address of the kernel callout.
- * Try to resolve it into a meaningful symbol
- */
- if (dtrace_lookup_by_addr(g_dtp, offender_addr,
- &sym, &dts) == 0) {
- (void) snprintf((char *)(p_event->offense_name),
- EVENT_NAME_MAX, "%s`%s", dts.dts_object,
- dts.dts_name);
- } else {
- (void) snprintf((char *)(p_event->offense_name),
- EVENT_NAME_MAX, "0x%llx", offender_addr);
- }
- /*
- * Report user events
- */
- } else if (strcmp(aggdesc->dtagd_name, "events_u") == 0) {
- offense_name = data->dtada_data + rec1->dtrd_offset;
-
- (void) snprintf((char *)(p_event->offender_name),
- EVENT_NAME_MAX, "%s", offense_name);
- (void) snprintf((char *)(p_event->offense_name),
- EVENT_NAME_MAX, "<scheduled timeout expiration>");
- /*
- * Report cross calls
- */
- } else if (strcmp(aggdesc->dtagd_name, "events_x") == 0) {
- offense_name = data->dtada_data + rec1->dtrd_offset;
-
- (void) snprintf((char *)(p_event->offender_name),
- EVENT_NAME_MAX, "%s", offense_name);
- (void) snprintf((char *)(p_event->offense_name),
- EVENT_NAME_MAX, "<cross calls>");
- /*
- * Report unknown events
- */
- } else {
- (void) snprintf((char *)(p_event->offender_name),
- EVENT_NAME_MAX, "%s", "<unknown>");
- (void) snprintf((char *)(p_event->offense_name),
- EVENT_NAME_MAX, "%s", "<unknown>");
- }
-
- for (i = 0; i < g_ncpus; i++)
- /* LINTED - alignment */
- n += *((uint64_t *)(data->dtada_percpu[i]));
-
- p_event->total_count = n;
-
- p_event++;
- top_events++;
-
- return (DTRACE_AGGWALK_NEXT);
-}
-
-int
-pt_events_stat_prepare(void)
-{
- dtrace_prog_t *prog;
- dtrace_proginfo_t info;
- int err;
- dtrace_optval_t statustime;
-
- p_event = event_info;
-
- if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
- pt_error("%s : cannot open dtrace library: %s\n", __FILE__,
- dtrace_errmsg(NULL, err));
- return (-1);
- }
-
- /*
- * Execute different scripts (defined above) depending on
- * user specified options. Default mode has event_mode empty
- */
- switch (event_mode) {
- default:
- if ((prog = dtrace_program_strcompile(g_dtp, g_prog,
- DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
- pt_error("%s : failed to compile g_prog\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- break;
- case 'v':
- if ((prog = dtrace_program_strcompile(g_dtp, g_prog_v,
- DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
- pt_error("%s : failed to compile g_prog_v\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- break;
- }
-
- if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
- pt_error("%s : failed to enable probes\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) {
- pt_error("%s : failed to set 'aggsize'\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) {
- pt_error("%s : failed to set 'aggrate'\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) {
- pt_error("%s : failed to set 'aggpercpu'\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_go(g_dtp) != 0) {
- pt_error("%s : dtrace_go() failed\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) {
- pt_error("%s : failed to get 'statusrate'\n", __FILE__);
- return (dtrace_errno(g_dtp));
- }
- return (0);
-}
-
-int
-pt_events_stat_collect(void)
-{
- p_event = event_info;
- top_events = 0;
-
- if (dtrace_status(g_dtp) == -1)
- return (-1);
-
- if (dtrace_aggregate_snap(g_dtp) != 0)
- pt_error("%s : failed to add to aggregate", __FILE__);
-
- if (dtrace_aggregate_walk_keyvarsorted(g_dtp, walk, NULL) != 0)
- pt_error("%s : failed to sort aggregate", __FILE__);
-
- dtrace_aggregate_clear(g_dtp);
-
- return (0);
-}
--- a/usr/src/cmd/powertop/i386/Makefile Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/i386/Makefile Fri Apr 10 11:48:42 2009 -0700
@@ -18,10 +18,26 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
include ../Makefile.com
+MACH_OBJS = pt_i386.o
+SRCS += $(MACH_OBJS:%.o=%.c)
+
+.KEEP_STATE:
+
+CLEANFILES += $(MACH_OBJS)
+
+all: $(PROG)
+
+$(PROG): $(MACH_OBJS) $(COMMON_OBJS)
+ $(LINK.c) -o $@ $(MACH_OBJS) $(COMMON_OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+
install: all $(ROOTPROG32)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/i386/pt_i386.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+/*
+ * DTrace scripts for observing interrupts, callouts and cyclic events
+ * that cause CPU activity. Such activity prevents the processor from
+ * entering lower power states and reducing power consumption.
+ *
+ * g_dtp_events is the default script
+ */
+const char *g_dtp_events =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+" self->xc_func = 0;"
+"}";
+
+/*
+ * g_dtp_events_v is enabled through the -v option, it includes cyclic events
+ * in the report, allowing a complete view of system activity
+ */
+const char *g_dtp_events_v =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+"}"
+""
+"fbt::xc_common:return"
+"/self->xc_func/"
+"{"
+" self->xc_func = 0;"
+"}";
+
+/*
+ * This script is selected through the -c option, it takes the CPU id as
+ * argument and observes activity generated by that CPU
+ */
+const char *g_dtp_events_c =
+"interrupt-complete"
+"/cpu == $0 &&"
+" arg0 != NULL && arg3 != 0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/cpu == $0 &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu == $0/"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" cpu == $0/"
+"{"
+" @events_x[execname, self->xc_func] = count();"
+"}"
+""
+"fbt::xc_common:return"
+"/cpu == $0 &&"
+" self->xc_func/"
+"{"
+" self->xc_func = 0;"
+"}"
+""
+"fbt::xc_common:entry"
+"/cpu != $0/"
+"{"
+" self->xc_func = arg0;"
+" self->xc_cpu = cpu;"
+"}"
+""
+"fbt::send_dirint:entry"
+"/pid != $pid &&"
+" self->xc_func &&"
+" arg0 == $0/"
+"{"
+" @events_xc[execname, self->xc_func, self->xc_cpu] = count();"
+" self->xc_func = 0;"
+" self->xc_cpu = 0;"
+"}";
+
+/*
+ * i386 platform specific display messages
+ */
+const char *g_msg_idle_state = "C-states (idle power states)";
+const char *g_msg_freq_state = "P-states (frequencies)";
--- a/usr/src/cmd/powertop/powertop.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <getopt.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <locale.h>
-#include "powertop.h"
-
-int g_ncpus;
-processorid_t *cpu_table;
-const int true = 1;
-boolean_t gui;
-
-int
-main(int argc, char **argv)
-{
- hrtime_t last, now;
- uint_t features = 0, user_interval = 0;
- int ncursesinited = 0, index2 = 0, c, ret, dump_count = 0;
- double last_time;
- char *endptr;
-
- static struct option opts[] = {
- { "dump", 1, NULL, 'd' },
- { "time", 1, NULL, 't' },
- { "help", 0, NULL, 'h' },
- { "verbose", 0, NULL, 'v' },
- { 0, 0, NULL, 0 }
- };
-
- (void) setlocale(LC_ALL, "");
- (void) bindtextdomain("powertop", "/usr/share/locale");
- (void) textdomain("powertop");
-
- pt_set_progname(argv[0]);
-
- if ((bit_depth = get_bit_depth()) < 0)
- exit(EXIT_FAILURE);
-
- ticktime = ticktime_usr = INTERVAL_DEFAULT;
- displaytime = 0.0;
- dump = 0;
- gui = B_FALSE;
- event_mode = ' ';
- max_cstate = 0;
- g_turbo_supported = B_FALSE;
-
- while ((c = getopt_long(argc, argv, "d:vt:h", opts, &index2)) != EOF) {
- if (c == -1)
- break;
-
- switch (c) {
- case 'd':
- if (dump)
- usage();
-
- dump = 1;
- dump_count = (int)strtod(optarg, &endptr);
-
- if (dump_count <= 0 || *endptr != NULL)
- usage();
- break;
- case 't':
- if (user_interval)
- usage();
-
- user_interval = 1;
- ticktime = ticktime_usr = (double)strtod(optarg,
- &endptr);
-
- if (*endptr != NULL || ticktime < 1 ||
- ticktime > INTERVAL_MAX)
- usage();
- break;
- case 'v':
- if (event_mode == 'v')
- usage();
-
- event_mode = 'v';
- break;
- case 'h':
- default:
- usage();
- return (EXIT_USAGE);
- }
- }
-
- if (optind < argc) {
- usage();
- }
-
- (void) printf("%s (C) 2009 Intel Corporation\n\n", TITLE);
-
- /*
- * Enumerate the system's CPUs
- * Populate cpu_table, g_ncpus
- */
- enumerate_cpus();
-
- /*
- * If the system is running on battery, find out what's
- * the kstat module for it
- */
- battery_mod_lookup();
-
- /* Prepare C-state statistics */
- ret = pt_cpuidle_stat_prepare();
- if (ret == 0)
- features |= FEATURE_CSTATE;
- else
- /*
- * PowerTop was unable to run a DTrace program,
- * most likely for lack of permissions.
- */
- exit(EXIT_FAILURE);
-
- /* Prepare P-state statistics */
- if (pt_cpufreq_stat_prepare() == 0)
- features |= FEATURE_PSTATE;
-
- /* Prepare event statistics */
- if (pt_events_stat_prepare() != -1)
- features |= FEATURE_EVENTS;
-
- /* Prepare turbo statistics */
- if (pt_turbo_stat_prepare() == 0) {
- features |= FEATURE_TURBO;
- }
-
- (void) printf(_("Collecting data for %.2f second(s) \n"),
- (float)ticktime);
-
- if (!dump)
- gui = B_TRUE;
-
- last = gethrtime();
-
- while (true) {
- fd_set rfds;
- struct timeval tv;
- int key, reinit = 0;
- char keychar;
-
- /*
- * Sleep for a while waiting either for input (if we're not
- * in dump mode) or for the timeout to elapse
- */
- FD_ZERO(&rfds);
- FD_SET(0, &rfds);
-
- tv.tv_sec = (long)ticktime;
- tv.tv_usec = (long)((ticktime - tv.tv_sec) * 1000000);
-
- if (!dump)
- key = select(1, &rfds, NULL, NULL, &tv);
- else
- key = select(1, NULL, NULL, NULL, &tv);
-
- now = gethrtime();
-
- g_interval = (double)(now - last)/NANOSEC;
- last = now;
-
- top_events = 0;
- total_events = 0;
-
- (void) memset(event_info, EVENT_NUM_MAX * sizeof (event_info_t),
- 0);
- (void) memset(cstate_info, 2 * sizeof (state_info_t), 0);
-
- /* Collect idle state transition stats */
- if (features & FEATURE_CSTATE &&
- pt_cpuidle_stat_collect(g_interval) < 0) {
- /* Reinitialize C-state statistics */
- if (pt_cpuidle_stat_prepare() != 0)
- exit(EXIT_FAILURE);
-
- reinit = 1;
- }
-
- /* Collect frequency change stats */
- if (features & FEATURE_PSTATE &&
- pt_cpufreq_stat_collect(g_interval) < 0) {
- /* Reinitialize P-state statistics */
- if (pt_cpufreq_stat_prepare() != 0)
- exit(EXIT_FAILURE);
-
- reinit = 1;
- }
-
- /* Collect event statistics */
- if (features & FEATURE_EVENTS &&
- pt_events_stat_collect() < 0) {
- /* Reinitialize event statistics */
- if (pt_events_stat_prepare() != 0)
- exit(EXIT_FAILURE);
-
- reinit = 1;
- }
-
- if (reinit)
- continue;
-
- /* Collect turbo statistics */
- if (features & FEATURE_TURBO &&
- pt_turbo_stat_collect() < 0) {
- exit(EXIT_FAILURE);
- }
-
- /*
- * Initialize curses if we're not dumping and
- * haven't already done it
- */
- if (!dump) {
- if (!ncursesinited) {
- initialize_curses();
- ncursesinited++;
- }
- setup_windows();
- show_title_bar();
- }
-
- /* Show CPU power states */
- if (features & FEATURE_CSTATE)
- show_cstates();
-
- /* Show wakeups events affecting PM */
- if (features & FEATURE_EVENTS) {
- show_wakeups(g_interval);
- show_eventstats(g_interval);
- }
-
- print_battery();
-
- displaytime = displaytime - ticktime;
-
- if (key && !dump) {
- keychar = toupper(fgetc(stdin));
-
- switch (keychar) {
- case 'Q':
- cleanup_curses();
- exit(EXIT_SUCCESS);
- break;
- case 'R':
- ticktime = 3;
- break;
- }
- if (keychar == suggestion_key && suggestion_activate) {
- suggestion_activate();
- displaytime = -1.0;
- }
- }
- reset_suggestions();
-
- /* suggests PM */
- if (geteuid() == 0) {
- suggest_p_state();
- } else {
- suggest_as_root();
- }
-
- if (dump_count)
- dump_count--;
-
- /* Exits if user requested a dump */
- if (dump && !dump_count) {
- print_all_suggestions();
- exit(EXIT_SUCCESS);
- }
-
- /* No key pressed, will suggest something */
- if (!key && !dump_count)
- pick_suggestion();
-
- /* Refresh display */
- if (!dump) {
- show_title_bar();
- update_windows();
- }
-
- /*
- * Update the interval based on how long the CPU was in the
- * longest c-state during the last snapshot. If the user
- * specified an interval we skip this bit and keep it fixed.
- */
- last_time = (((double)cstate_info[longest_cstate].total_time/
- g_ncpus)/cstate_info[longest_cstate].events);
-
- if (!user_interval)
- if (last_time < INTERVAL_DEFAULT ||
- (total_events/ticktime) < 1)
- ticktime = INTERVAL_DEFAULT;
- else
- ticktime = INTERVAL_UPDATE(last_time);
-
- /*
- * Restore user specified interval after a refresh
- */
- if (keychar == 'R' && user_interval)
- ticktime = ticktime_usr;
- }
- return (EXIT_SUCCESS);
-}
-
-void
-suggest_as_root(void)
-{
- add_suggestion("Suggestion: run as root to get suggestions"
- " for reducing system power consumption", 40, NULL, NULL,
- NULL);
-}
--- a/usr/src/cmd/powertop/powertop.h Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,300 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#ifndef __INCLUDE_GUARD_POWERTOP_H_
-#define __INCLUDE_GUARD_POWERTOP_H_
-
-#include <sys/types.h>
-#include <libintl.h>
-#include <sys/processor.h>
-
-#define max(A, B) (((A) < (B)) ? (B) : (A))
-
-#define _(STRING) gettext(STRING)
-
-#define TITLE "OpenSolaris PowerTOP version 1.1"
-
-/*
- * Exit values. stdlib.h defines EXIT_SUCCESS as 0 and
- * EXIT_FAILURE as 1
- */
-#define EXIT_USAGE 2
-
-/*
- * PowerTop Features
- * These may not be available everywhere
- */
-#define FEATURE_CSTATE 0x1
-#define FEATURE_PSTATE 0x2
-#define FEATURE_EVENTS 0x4
-#define FEATURE_TURBO 0x8
-
-#define BIT_DEPTH_BUF 10
-
-#define INTERVAL_DEFAULT 5.0
-#define INTERVAL_MAX 100.0
-#define INTERVAL_UPDATE(l) \
- ((l/INTERVAL_DEFAULT) * INTERVAL_DEFAULT + INTERVAL_DEFAULT)
-
-#define STATE_NAME_MAX 16
-#define EVENT_NAME_MAX 64
-#define EVENT_NUM_MAX 100
-#define NSTATES 32
-
-/*
- * Display colors
- */
-#define PT_COLOR_DEFAULT 1
-#define PT_COLOR_HEADER_BAR 2
-#define PT_COLOR_ERROR 3
-#define PT_COLOR_RED 4
-#define PT_COLOR_YELLOW 5
-#define PT_COLOR_GREEN 6
-#define PT_COLOR_BRIGHT 7
-#define PT_COLOR_BLUE 8
-
-/*
- * Constants for setup_windows()
- */
-#define SINGLE_LINE_SW 1
-#define LENGTH_SUGG_SW 2
-#define TITLE_LINE 1
-#define BLANK_LINE 1
-#define NEXT_LINE 1
-
-/*
- * Structures and typedefs
- */
-struct line {
- char *string;
- int count;
-};
-
-typedef struct event_info {
- char offender_name[EVENT_NAME_MAX];
- char offense_name[EVENT_NAME_MAX];
- uint64_t total_count;
-} event_info_t;
-
-/*
- * P/C state information
- */
-typedef struct state_info {
- char name[STATE_NAME_MAX];
- hrtime_t total_time;
- hrtime_t last_time;
- double events;
-} state_info_t;
-
-typedef struct pstate_info {
- uint64_t speed;
- hrtime_t total_time;
-} pstate_info_t;
-
-typedef struct cpu_power_info {
- uint64_t current_pstate;
- hrtime_t time_accounted;
- hrtime_t dtrace_time;
-} cpu_power_info_t;
-
-/*
- * turbo information
- */
-typedef struct turbo_info {
- uint64_t t_mcnt;
- uint64_t t_acnt;
-} turbo_info_t;
-
-
-typedef void (suggestion_func)(void);
-
-/*
- * Global variables
- */
-double displaytime;
-
-int bit_depth;
-
-/*
- * Event accounting
- */
-int total_events;
-int top_events;
-
-/*
- * Interval
- */
-double ticktime, ticktime_usr;
-double g_interval;
-
-/*
- * Command line arguments
- */
-int dump;
-char event_mode;
-extern boolean_t gui;
-
-/*
- * Event info array
- */
-event_info_t event_info[EVENT_NUM_MAX];
-event_info_t *p_event;
-
-/*
- * Lookup table, sequential CPU id to Solaris CPU id
- */
-processorid_t *cpu_table;
-
-/*
- * Number of idle/frequency states
- */
-int npstates;
-int max_cstate;
-int longest_cstate;
-
-/*
- * Total time, used to display different idle states
- */
-hrtime_t total_c_time;
-
-/*
- * P/C state info arrays
- */
-state_info_t cstate_info[NSTATES];
-pstate_info_t pstate_info[NSTATES];
-
-/*
- * Per CPU power state information
- */
-cpu_power_info_t *cpu_power_states;
-
-/*
- * Turbo mode related information
- */
-extern boolean_t g_turbo_supported;
-extern double g_turbo_ratio;
-
-/*
- * Extern declarations
- */
-extern struct line *lines;
-extern int linehead;
-extern int linesize;
-extern int linectotal;
-
-extern int g_ncpus;
-
-/*
- * kstat's battery module
- */
-extern char *kstat_batt_mod[3];
-extern uint_t kstat_batt_idx;
-
-extern int topcstate;
-extern int topfreq;
-extern int dump;
-
-extern char *prog;
-
-extern char status_bar_slots[10][40];
-
-extern const int true, false;
-
-extern char suggestion_key;
-extern suggestion_func *suggestion_activate;
-
-/*
- * Suggestions related
- */
-extern void suggest_p_state(void);
-extern void suggest_as_root(void);
-
-/*
- * See util.c
- */
-extern void pt_error(char *, ...);
-extern void pt_set_progname(char *);
-extern void enumerate_cpus(void);
-extern void usage(void);
-extern int get_bit_depth(void);
-extern void battery_mod_lookup(void);
-extern int event_compare(const void *, const void *);
-
-/*
- * Display/curses related
- */
-extern void show_title_bar(void);
-extern void setup_windows(void);
-extern void initialize_curses(void);
-extern void show_acpi_power_line(uint32_t flag, double rate,
- double rem_cap, double cap, uint32_t state);
-extern void show_cstates();
-extern void show_wakeups(double interval);
-extern void show_eventstats(double interval);
-extern void show_suggestion(char *sug);
-extern void cleanup_curses(void);
-extern void update_windows(void);
-
-/*
- * Suggestions
- */
-extern void pick_suggestion(void);
-extern void add_suggestion(char *text, int weight, char key,
- char *keystring, suggestion_func *func);
-extern void reset_suggestions(void);
-extern void print_all_suggestions(void);
-extern void print_battery(void);
-
-/*
- * DTrace stats
- */
-extern int pt_cpufreq_stat_prepare(void);
-extern int pt_cpufreq_stat_collect(double interval);
-extern int pt_cpuidle_stat_prepare(void);
-extern int pt_cpuidle_stat_collect(double interval);
-extern int pt_events_stat_prepare(void);
-extern int pt_events_stat_collect(void);
-
-/*
- * turbo related
- */
-extern int pt_turbo_stat_prepare(void);
-extern int pt_turbo_stat_collect(void);
-
-#endif /* __INCLUDE_GUARD_POWERTOP_H_ */
--- a/usr/src/cmd/powertop/sparcv9/Makefile Fri Apr 10 11:27:35 2009 -0700
+++ b/usr/src/cmd/powertop/sparcv9/Makefile Fri Apr 10 11:48:42 2009 -0700
@@ -18,11 +18,27 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
include ../Makefile.com
include ../../Makefile.cmd.64
+MACH_OBJS = pt_sparcv9.o
+SRCS += $(MACH_OBJS:%.o=%.c)
+
+.KEEP_STATE:
+
+CLEANFILES += $(MACH_OBJS)
+
+all: $(PROG)
+
+$(PROG): $(MACH_OBJS) $(COMMON_OBJS)
+ $(LINK.c) -o $@ $(MACH_OBJS) $(COMMON_OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+
install: all $(ROOTPROG64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/powertop/sparcv9/pt_sparcv9.c Fri Apr 10 11:48:42 2009 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2009, Intel Corporation
+ * Copyright 2009, Sun Microsystems, Inc
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Arjan van de Ven <[email protected]>
+ * Eric C Saxe <[email protected]>
+ * Aubrey Li <[email protected]>
+ */
+
+/*
+ * GPL Disclaimer
+ *
+ * For the avoidance of doubt, except that if any license choice other
+ * than GPL or LGPL is available it will apply instead, Sun elects to
+ * use only the General Public License version 2 (GPLv2) at this time
+ * for any software where a choice of GPL license versions is made
+ * available with the language indicating that GPLv2 or any later
+ * version may be used, or where a choice of which version of the GPL
+ * is applied is otherwise unspecified.
+ */
+
+/*
+ * DTrace scripts for observing interrupts, callouts and cyclic events
+ * that cause CPU activity. Such activity prevents the processor from
+ * entering lower power states and reducing power consumption.
+ *
+ * g_dtp_events is the default script
+ */
+const char *g_dtp_events =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xt_all:entry,"
+"fbt::xc_all:entry"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"fbt::xt_one_unchecked:entry,"
+"fbt::xt_some:entry,"
+"fbt::xc_one:entry,"
+"fbt::xc_some:entry"
+"{"
+" self->xc_func = arg1;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+" self->xc_func = 0;"
+"}";
+
+/*
+ * g_dtp_events_v is enabled through the -v option, it includes cyclic events
+ * in the report, allowing a complete view of system activity
+ */
+const char *g_dtp_events_v =
+"interrupt-complete"
+"/arg0 != NULL && arg3 !=0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/(caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_deadman &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler != (caddr_t)&`dtrace_state_clean/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+"fbt::xt_all:entry,"
+"fbt::xc_all:entry"
+"{"
+" self->xc_func = arg0;"
+"}"
+""
+"fbt::xt_one_unchecked:entry,"
+"fbt::xt_some:entry,"
+"fbt::xc_one:entry,"
+"fbt::xc_some:entry"
+"{"
+" self->xc_func = arg1;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+" self->xc_func = 0;"
+"}";
+
+/*
+ * This script is selected through the -c option, it takes the CPU id as
+ * argument and observes activity generated by that CPU
+ */
+const char *g_dtp_events_c =
+"interrupt-complete"
+"/cpu == $0 &&"
+" arg0 != NULL && arg3 != 0/"
+"{"
+" this->devi = (struct dev_info *)arg0;"
+" @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),"
+" this->devi->devi_instance] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun/"
+"{"
+" this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);"
+" @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();"
+"}"
+""
+"sdt:::callout-start"
+"/cpu == $0 &&"
+" (caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun/"
+"{"
+" @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();"
+"}"
+""
+"sdt:::cyclic-start"
+"/cpu == $0 &&"
+" (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/"
+"{"
+" @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();"
+"}"
+""
+/*
+ * xcalls to all CPUs. We're only interested in firings from other CPUs since
+ * the system doesn't xcall itself
+ */
+"fbt::xt_all:entry,"
+"fbt::xc_all:entry"
+"/pid != $pid &&"
+" cpu != $0/"
+"{"
+" self->xc_func = arg0;"
+" self->xc_cpu = cpu;"
+" self->cpu_known = 1;"
+"}"
+""
+/*
+ * xcalls to a subset of CPUs. No way of knowing if the observed CPU is in
+ * it, so account it in the generic @events_x aggregation. Again, we don't
+ * xcall the current CPU.
+ */
+"fbt::xt_some:entry,"
+"fbt::xc_some:entry"
+"/pid != $pid &&"
+" cpu != $0/"
+"{"
+" self->xc_func = arg1;"
+"}"
+""
+/*
+ * xcalls to a specific CPU, with all the necessary information
+ */
+"fbt::xt_one_unchecked:entry,"
+"fbt::xc_one:entry"
+"/arg0 == $0/"
+"{"
+" self->xc_func = arg1;"
+" self->xc_cpu = arg0;"
+" self->cpu_known = 1;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" self->xc_func &&"
+" !self->cpu_known/"
+"{"
+" @events_x[execname, self->xc_func] = sum(arg0);"
+" self->xc_func = 0;"
+"}"
+""
+"sysinfo:::xcalls"
+"/pid != $pid &&"
+" self->xc_func &&"
+" self->cpu_known/"
+"{"
+" @events_xc[execname, self->xc_func, self->xc_cpu] = sum(arg0);"
+" self->xc_func = 0;"
+" self->xc_cpu = 0;"
+" self->cpu_known = 0;"
+"}";
+
+/*
+ * sparcv9 platform specific display messages
+ */
+const char *g_msg_idle_state = "Idle Power States\t";
+const char *g_msg_freq_state = "Frequency Levels";
--- a/usr/src/cmd/powertop/suggestions.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright 2008, Intel Corporation
- * Copyright 2008, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "powertop.h"
-
-char suggestion_key;
-suggestion_func *suggestion_activate;
-
-struct suggestion;
-
-struct suggestion {
- struct suggestion *next;
-
- char *string;
- int weight;
- char key;
- char *keystring;
-
- suggestion_func *func;
-};
-
-static struct suggestion *suggestions;
-static int total_weight;
-
-static char previous[1024];
-
-void
-reset_suggestions(void)
-{
- struct suggestion *ptr;
-
- ptr = suggestions;
-
- while (ptr) {
- struct suggestion *next;
-
- next = ptr->next;
- free(ptr->string);
- free(ptr->keystring);
- free(ptr);
- ptr = next;
- }
-
- suggestions = NULL;
- (void) strcpy(status_bar_slots[8], "");
-
- suggestion_key = -1;
- suggestion_activate = NULL;
- total_weight = 0;
-}
-
-void
-add_suggestion(char *text, int weight, char key, char *keystring,
- suggestion_func *func)
-{
- struct suggestion *new;
-
- if (!text)
- return;
-
- new = malloc(sizeof (struct suggestion));
-
- if (!new)
- return;
-
- (void) memset(new, 0, sizeof (struct suggestion));
-
- new->string = strdup(text);
- new->weight = weight;
- new->key = key;
-
- if (keystring)
- new->keystring = strdup(keystring);
-
- new->next = suggestions;
- new->func = func;
- suggestions = new;
- total_weight += weight;
-}
-
-void
-pick_suggestion(void)
-{
- int weight, value, running = 0;
- struct suggestion *ptr;
-
- (void) strcpy(status_bar_slots[8], "");
- suggestion_key = -1;
- suggestion_activate = NULL;
-
- if (total_weight == 0 || suggestions == NULL) {
- show_suggestion("");
- return;
- }
-
- weight = total_weight;
-
- if (strlen(previous) && displaytime > 0.0)
- weight += 50;
-
- value = rand() % weight;
- ptr = suggestions;
-
- while (ptr) {
- running += ptr->weight;
-
- if (strcmp(ptr->string, previous) == 0 && displaytime > 0.0)
- running += 50;
-
- if (running > value) {
- if (ptr->keystring)
- (void) strncpy(status_bar_slots[8],
- ptr->keystring, 40);
-
- suggestion_key = ptr->key;
- suggestion_activate = ptr->func;
-
- show_suggestion(ptr->string);
-
- if (strcmp(ptr->string, previous)) {
- displaytime = 30.0;
- (void) strcpy(previous, ptr->string);
- }
- return;
- }
- ptr = ptr->next;
- }
-
- show_suggestion("");
- (void) memset(previous, 0, sizeof (previous));
- displaytime = -1.0;
-}
-
-void
-print_all_suggestions(void)
-{
- struct suggestion *ptr;
-
- for (ptr = suggestions; ptr; ptr = ptr->next)
- (void) printf("\n%s\n", ptr->string);
-}
--- a/usr/src/cmd/powertop/turbo.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <dtrace.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-/*
- * global turbo related variables definitions
- */
-boolean_t g_turbo_supported;
-double g_turbo_ratio;
-
-/*
- * the variables to store kstat snapshot
- */
-static turbo_info_t *cpu_turbo_info = NULL;
-static turbo_info_t *t_new = NULL;
-
-/*
- * Perform setup necessary to enumerate and track CPU turbo information
- */
-static int
-pt_turbo_init(void)
-{
- kstat_ctl_t *kc;
- kstat_t *ksp;
- kstat_named_t *knp;
-
- /*
- * check if the CPU turbo is supported
- */
- if ((kc = kstat_open()) == NULL) {
- g_turbo_supported = B_FALSE;
- return (errno);
- }
-
- ksp = kstat_lookup(kc, "turbo", 0, NULL);
- if (ksp == NULL) {
- g_turbo_supported = B_FALSE;
- (void) kstat_close(kc);
- return (-1);
- }
-
- (void) kstat_read(kc, ksp, NULL);
-
- knp = kstat_data_lookup(ksp, "turbo_supported");
- if (knp == NULL) {
- pt_error("%s : couldn't find item turbo_supported\n", __FILE__);
- g_turbo_supported = B_FALSE;
- (void) kstat_close(kc);
- return (-2);
- }
-
- /*
- * initialize turbo information structure if turbo mode is supported
- */
- if (knp->value.ui32) {
- g_turbo_supported = B_TRUE;
- cpu_turbo_info = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
- t_new = calloc((size_t)g_ncpus, sizeof (turbo_info_t));
- }
-
- (void) kstat_close(kc);
- return (0);
-}
-
-/*
- * Take a snapshot of each CPU's turbo information
- * by looking through the turbo kstats.
- */
-static int
-pt_turbo_snapshot(turbo_info_t *turbo_snapshot)
-{
- kstat_ctl_t *kc;
- kstat_t *ksp;
- kstat_named_t *knp;
- int cpu;
- turbo_info_t *turbo_info;
-
- if ((kc = kstat_open()) == NULL)
- return (errno);
-
- for (cpu = 0; cpu < g_ncpus; cpu++) {
- turbo_info = &turbo_snapshot[cpu];
- ksp = kstat_lookup(kc, "turbo", cpu_table[cpu], NULL);
- if (ksp == NULL) {
- pt_error("%s : couldn't find turbo kstat for CPU "
- "%d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (-1);
- }
-
- if (kstat_read(kc, ksp, NULL) == -1) {
- pt_error("%s : couldn't read turbo kstat for "
- "CPU %d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (-2);
- }
-
- knp = kstat_data_lookup(ksp, "turbo_mcnt");
- if (knp == NULL) {
- pt_error("%s : couldn't find turbo mcnt "
- "kstat for CPU %d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (-3);
- }
-
- /*
- * snapshot IA32_MPERF_MSR
- */
- turbo_info->t_mcnt = knp->value.ui64;
-
- knp = kstat_data_lookup(ksp, "turbo_acnt");
- if (knp == NULL) {
- pt_error("%s : couldn't find turbo acnt "
- "kstat for CPU %d\n", __FILE__, cpu);
- (void) kstat_close(kc);
- return (-4);
- }
-
- /*
- * snapshot IA32_APERF_MSR
- */
- turbo_info->t_acnt = knp->value.ui64;
- }
-
- if (kstat_close(kc) != 0)
- pt_error("%s : couldn't close kstat\n", __FILE__);
-
- return (0);
-}
-
-/*
- * turbo support checking and information initialization
- */
-int
-pt_turbo_stat_prepare(void)
-{
- int ret;
-
- ret = pt_turbo_init();
-
- if (ret != 0) {
- return (ret);
- }
-
- ret = pt_turbo_snapshot(cpu_turbo_info);
-
- if (ret != 0) {
- pt_error("%s : turbo snapshot failed\n", __FILE__);
- }
-
- return (ret);
-}
-
-/*
- * when doing the statistics collection, we compare two kstat snapshot
- * and get a delta. the final ratio of performance boost will be worked
- * out according to the kstat delta
- */
-int
-pt_turbo_stat_collect(void)
-{
- int cpu;
- uint64_t delta_mcnt, delta_acnt;
- double ratio;
- int ret;
-
- /*
- * take a snapshot of turbo information to setup turbo_info_t
- * structure
- */
- ret = pt_turbo_snapshot(t_new);
- if (ret != 0) {
- pt_error("%s : turbo stat collect failed\n", __FILE__);
- return (ret);
- }
-
- /*
- * calculate the kstat delta and work out the performance boost ratio
- */
- for (cpu = 0; cpu < g_ncpus; cpu++) {
- delta_mcnt = t_new[cpu].t_mcnt - cpu_turbo_info[cpu].t_mcnt;
- delta_acnt = t_new[cpu].t_acnt - cpu_turbo_info[cpu].t_acnt;
-
- if ((delta_mcnt > delta_acnt) || (delta_mcnt == 0))
- ratio = 1.0;
- else
- ratio = (double)delta_acnt / (double)delta_mcnt;
- g_turbo_ratio += ratio;
- }
-
- g_turbo_ratio = g_turbo_ratio / (double)g_ncpus;
-
- /*
- * update the structure of the kstat for the next time calculation
- */
- (void) memcpy(cpu_turbo_info, t_new, g_ncpus * (sizeof (turbo_info_t)));
-
- return (0);
-}
--- a/usr/src/cmd/powertop/util.c Fri Apr 10 11:27:35 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright 2009, Intel Corporation
- * Copyright 2009, Sun Microsystems, Inc
- *
- * This file is part of PowerTOP
- *
- * This program file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- *
- * Authors:
- * Arjan van de Ven <[email protected]>
- * Eric C Saxe <[email protected]>
- * Aubrey Li <[email protected]>
- */
-
-/*
- * GPL Disclaimer
- *
- * For the avoidance of doubt, except that if any license choice other
- * than GPL or LGPL is available it will apply instead, Sun elects to
- * use only the General Public License version 2 (GPLv2) at this time
- * for any software where a choice of GPL license versions is made
- * available with the language indicating that GPLv2 or any later
- * version may be used, or where a choice of which version of the GPL
- * is applied is otherwise unspecified.
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <strings.h>
-#include <sys/systeminfo.h>
-#include <kstat.h>
-#include <errno.h>
-#include "powertop.h"
-
-static char PROG_FMT[] = "%s: ";
-static char ERR_FMT[] = ": %s";
-static char *progname;
-
-char *kstat_batt_mod[3] = {"NULL", "battery", "acpi_drv"};
-uint_t kstat_batt_idx;
-
-void
-pt_set_progname(char *name)
-{
- progname = basename(name);
-}
-
-/*PRINTFLIKE1*/
-void
-pt_error(char *format, ...)
-{
- int err = errno;
- va_list alist;
-
- if (gui)
- return;
-
- if (progname != NULL)
- (void) fprintf(stderr, PROG_FMT, progname);
-
- va_start(alist, format);
- (void) vfprintf(stderr, format, alist);
- va_end(alist);
-
- if (strchr(format, '\n') == NULL)
- (void) fprintf(stderr, gettext(ERR_FMT), strerror(err));
-}
-
-void
-enumerate_cpus(void)
-{
- int cpuid;
- int ncpus = 0;
- int max, cpus_conf;
-
- max = sysconf(_SC_CPUID_MAX);
- cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
- cpu_table = malloc(cpus_conf * sizeof (processorid_t));
-
- for (cpuid = 0; cpuid < max; cpuid++) {
- if (p_online(cpuid, P_STATUS) != -1) {
- cpu_table[ncpus] = cpuid;
- ncpus++;
- }
- }
- g_ncpus = ncpus;
-}
-
-void
-usage(void)
-{
- (void) fprintf(stderr, "%s (C) 2009 Intel Corporation\n\n", TITLE);
- (void) fprintf(stderr, "Usage: powertop [option]\n");
- (void) fprintf(stderr, " -d, --dump [count] Read wakeups count "
- "times and print list of top offenders\n");
- (void) fprintf(stderr, " -t, --time [interval] Default time to gather "
- "data in seconds [1-100s]\n");
- (void) fprintf(stderr, " -v, --verbose Verbose mode, reports "
- "kernel cyclic activity\n");
- (void) fprintf(stderr, " -h, --help Show this help "
- "message\n");
-
- exit(EXIT_USAGE);
-}
-
-int
-get_bit_depth(void)
-{
- /*
- * This little routine was derived from isainfo.c to look up
- * the system's bit depth. It feeds a 10 byte long buffer to
- * sysinfo (we only need the first word, sysinfo truncates and
- * \0 terminates the rest) from which we figure out which isa
- * we're running on.
- */
- char buf[BIT_DEPTH_BUF];
-
- if (sysinfo(SI_ARCHITECTURE_64, buf, BIT_DEPTH_BUF) == -1)
- if (sysinfo(SI_ARCHITECTURE_32, buf, BIT_DEPTH_BUF) == -1)
- return (-2);
-
- if (strcmp(buf, "sparc") == 0 || strcmp(buf, "i386") == 0)
- return (32);
-
- if (strcmp(buf, "sparcv9") == 0 || strcmp(buf, "amd64") == 0)
- return (64);
-
- return (-3);
-}
-
-/*
- * Checks if the kstat module for battery information is present and
- * whether it's called 'battery' or 'acpi_drv'
- */
-void
-battery_mod_lookup(void)
-{
- kstat_ctl_t *kc = kstat_open();
-
- if (kstat_lookup(kc, kstat_batt_mod[1], 0, NULL))
- kstat_batt_idx = 1;
- else
- if (kstat_lookup(kc, kstat_batt_mod[2], 0, NULL))
- kstat_batt_idx = 2;
- else
- kstat_batt_idx = 0;
-
- (void) kstat_close(kc);
-}
-
-/*
- * Simple integer comparison routine for the event report qsort(3C).
- */
-int
-event_compare(const void *p1, const void *p2)
-{
- event_info_t i = *((event_info_t *)p1);
- event_info_t j = *((event_info_t *)p2);
-
- if (i.total_count > j.total_count)
- return (-1);
-
- if (i.total_count < j.total_count)
- return (1);
-
- return (0);
-}