mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-29 15:28:50 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
36
tools/power/cpupower/bench/Makefile
Normal file
36
tools/power/cpupower/bench/Makefile
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
OUTPUT := ./
|
||||
ifeq ("$(origin O)", "command line")
|
||||
ifneq ($(O),)
|
||||
OUTPUT := $(O)/
|
||||
endif
|
||||
endif
|
||||
|
||||
LIBS = -L../ -L$(OUTPUT) -lm -lcpupower
|
||||
|
||||
OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o
|
||||
CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
|
||||
|
||||
$(OUTPUT)%.o : %.c
|
||||
$(ECHO) " CC " $@
|
||||
$(QUIET) $(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(OUTPUT)cpufreq-bench: $(OBJS)
|
||||
$(ECHO) " CC " $@
|
||||
$(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS)
|
||||
|
||||
all: $(OUTPUT)cpufreq-bench
|
||||
|
||||
install:
|
||||
mkdir -p $(DESTDIR)/$(sbindir)
|
||||
mkdir -p $(DESTDIR)/$(bindir)
|
||||
mkdir -p $(DESTDIR)/$(docdir)
|
||||
mkdir -p $(DESTDIR)/$(confdir)
|
||||
install -m 755 $(OUTPUT)cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
|
||||
install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh
|
||||
install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH
|
||||
install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh
|
||||
install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf
|
||||
|
||||
clean:
|
||||
rm -f $(OUTPUT)*.o
|
||||
rm -f $(OUTPUT)cpufreq-bench
|
||||
124
tools/power/cpupower/bench/README-BENCH
Normal file
124
tools/power/cpupower/bench/README-BENCH
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
This is cpufreq-bench, a microbenchmark for the cpufreq framework.
|
||||
|
||||
Purpose
|
||||
=======
|
||||
|
||||
What is this benchmark for:
|
||||
- Identify worst case performance loss when doing dynamic frequency
|
||||
scaling using Linux kernel governors
|
||||
- Identify average reaction time of a governor to CPU load changes
|
||||
- (Stress) Testing whether a cpufreq low level driver or governor works
|
||||
as expected
|
||||
- Identify cpufreq related performance regressions between kernels
|
||||
- Possibly Real time priority testing? -> what happens if there are
|
||||
processes with a higher prio than the governor's kernel thread
|
||||
- ...
|
||||
|
||||
What this benchmark does *not* cover:
|
||||
- Power saving related regressions (In fact as better the performance
|
||||
throughput is, the worse the power savings will be, but the first should
|
||||
mostly count more...)
|
||||
- Real world (workloads)
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
cpufreq-bench helps to test the condition of a given cpufreq governor.
|
||||
For that purpose, it compares the performance governor to a configured
|
||||
powersave module.
|
||||
|
||||
|
||||
How it works
|
||||
============
|
||||
You can specify load (100% CPU load) and sleep (0% CPU load) times in us which
|
||||
will be run X time in a row (cycles):
|
||||
|
||||
sleep=25000
|
||||
load=25000
|
||||
cycles=20
|
||||
|
||||
This part of the configuration file will create 25ms load/sleep turns,
|
||||
repeated 20 times.
|
||||
|
||||
Adding this:
|
||||
sleep_step=25000
|
||||
load_step=25000
|
||||
rounds=5
|
||||
Will increase load and sleep time by 25ms 5 times.
|
||||
Together you get following test:
|
||||
25ms load/sleep time repeated 20 times (cycles).
|
||||
50ms load/sleep time repeated 20 times (cycles).
|
||||
..
|
||||
100ms load/sleep time repeated 20 times (cycles).
|
||||
|
||||
First it is calibrated how long a specific CPU intensive calculation
|
||||
takes on this machine and needs to be run in a loop using the performance
|
||||
governor.
|
||||
Then the above test runs are processed using the performance governor
|
||||
and the governor to test. The time the calculation really needed
|
||||
with the dynamic freq scaling governor is compared with the time needed
|
||||
on full performance and you get the overall performance loss.
|
||||
|
||||
|
||||
Example of expected results with ondemand governor:
|
||||
|
||||
This shows expected results of the first two test run rounds from
|
||||
above config, you there have:
|
||||
|
||||
100% CPU load (load) | 0 % CPU load (sleep) | round
|
||||
25 ms | 25 ms | 1
|
||||
50 ms | 50 ms | 2
|
||||
|
||||
For example if ondemand governor is configured to have a 50ms
|
||||
sampling rate you get:
|
||||
|
||||
In round 1, ondemand should have rather static 50% load and probably
|
||||
won't ever switch up (as long as up_threshold is above).
|
||||
|
||||
In round 2, if the ondemand sampling times exactly match the load/sleep
|
||||
trigger of the cpufreq-bench, you will see no performance loss (compare with
|
||||
below possible ondemand sample kick ins (1)):
|
||||
|
||||
But if ondemand always kicks in in the middle of the load sleep cycles, it
|
||||
will always see 50% loads and you get worst performance impact never
|
||||
switching up (compare with below possible ondemand sample kick ins (2))::
|
||||
|
||||
50 50 50 50ms ->time
|
||||
load -----| |-----| |-----| |-----|
|
||||
| | | | | | |
|
||||
sleep |-----| |-----| |-----| |----
|
||||
|-----|-----|-----|-----|-----|-----|-----|---- ondemand sampling (1)
|
||||
100 0 100 0 100 0 100 load seen by ondemand(%)
|
||||
|-----|-----|-----|-----|-----|-----|-----|-- ondemand sampling (2)
|
||||
50 50 50 50 50 50 50 load seen by ondemand(%)
|
||||
|
||||
You can easily test all kind of load/sleep times and check whether your
|
||||
governor in average behaves as expected.
|
||||
|
||||
|
||||
ToDo
|
||||
====
|
||||
|
||||
Provide a gnuplot utility script for easy generation of plots to present
|
||||
the outcome nicely.
|
||||
|
||||
|
||||
cpufreq-bench Command Usage
|
||||
===========================
|
||||
-l, --load=<long int> initial load time in us
|
||||
-s, --sleep=<long int> initial sleep time in us
|
||||
-x, --load-step=<long int> time to be added to load time, in us
|
||||
-y, --sleep-step=<long int> time to be added to sleep time, in us
|
||||
-c, --cpu=<unsigned int> CPU Number to use, starting at 0
|
||||
-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT
|
||||
-g, --governor=<governor> cpufreq governor to test
|
||||
-n, --cycles=<int> load/sleep cycles to get an avarage value to compare
|
||||
-r, --rounds<int> load/sleep rounds
|
||||
-f, --file=<configfile> config file to use
|
||||
-o, --output=<dir> output dir, must exist
|
||||
-v, --verbose verbose output on/off
|
||||
|
||||
Due to the high priority, the application may not be responsible for some time.
|
||||
After the benchmark, the logfile is saved in OUTPUTDIR/benchmark_TIMESTAMP.log
|
||||
|
||||
194
tools/power/cpupower/bench/benchmark.c
Normal file
194
tools/power/cpupower/bench/benchmark.c
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "benchmark.h"
|
||||
|
||||
/* Print out progress if we log into a file */
|
||||
#define show_progress(total_time, progress_time) \
|
||||
if (config->output != stdout) { \
|
||||
fprintf(stdout, "Progress: %02lu %%\r", \
|
||||
(progress_time * 100) / total_time); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
/**
|
||||
* compute how many rounds of calculation we should do
|
||||
* to get the given load time
|
||||
*
|
||||
* @param load aimed load time in µs
|
||||
*
|
||||
* @retval rounds of calculation
|
||||
**/
|
||||
|
||||
unsigned int calculate_timespace(long load, struct config *config)
|
||||
{
|
||||
int i;
|
||||
long long now, then;
|
||||
unsigned int estimated = GAUGECOUNT;
|
||||
unsigned int rounds = 0;
|
||||
unsigned int timed = 0;
|
||||
|
||||
if (config->verbose)
|
||||
printf("calibrating load of %lius, please wait...\n", load);
|
||||
|
||||
/* get the initial calculation time for a specific number of rounds */
|
||||
now = get_time();
|
||||
ROUNDS(estimated);
|
||||
then = get_time();
|
||||
|
||||
timed = (unsigned int)(then - now);
|
||||
|
||||
/* approximation of the wanted load time by comparing with the
|
||||
* initial calculation time */
|
||||
for (i = 0; i < 4; i++) {
|
||||
rounds = (unsigned int)(load * estimated / timed);
|
||||
dprintf("calibrating with %u rounds\n", rounds);
|
||||
now = get_time();
|
||||
ROUNDS(rounds);
|
||||
then = get_time();
|
||||
|
||||
timed = (unsigned int)(then - now);
|
||||
estimated = rounds;
|
||||
}
|
||||
if (config->verbose)
|
||||
printf("calibration done\n");
|
||||
|
||||
return estimated;
|
||||
}
|
||||
|
||||
/**
|
||||
* benchmark
|
||||
* generates a specific sleep an load time with the performance
|
||||
* governor and compares the used time for same calculations done
|
||||
* with the configured powersave governor
|
||||
*
|
||||
* @param config config values for the benchmark
|
||||
*
|
||||
**/
|
||||
|
||||
void start_benchmark(struct config *config)
|
||||
{
|
||||
unsigned int _round, cycle;
|
||||
long long now, then;
|
||||
long sleep_time = 0, load_time = 0;
|
||||
long performance_time = 0, powersave_time = 0;
|
||||
unsigned int calculations;
|
||||
unsigned long total_time = 0, progress_time = 0;
|
||||
|
||||
sleep_time = config->sleep;
|
||||
load_time = config->load;
|
||||
|
||||
/* For the progress bar */
|
||||
for (_round = 1; _round <= config->rounds; _round++)
|
||||
total_time += _round * (config->sleep + config->load);
|
||||
total_time *= 2; /* powersave and performance cycles */
|
||||
|
||||
for (_round = 0; _round < config->rounds; _round++) {
|
||||
performance_time = 0LL;
|
||||
powersave_time = 0LL;
|
||||
|
||||
show_progress(total_time, progress_time);
|
||||
|
||||
/* set the cpufreq governor to "performance" which disables
|
||||
* P-State switching. */
|
||||
if (set_cpufreq_governor("performance", config->cpu) != 0)
|
||||
return;
|
||||
|
||||
/* calibrate the calculation time. the resulting calculation
|
||||
* _rounds should produce a load which matches the configured
|
||||
* load time */
|
||||
calculations = calculate_timespace(load_time, config);
|
||||
|
||||
if (config->verbose)
|
||||
printf("_round %i: doing %u cycles with %u calculations"
|
||||
" for %lius\n", _round + 1, config->cycles,
|
||||
calculations, load_time);
|
||||
|
||||
fprintf(config->output, "%u %li %li ",
|
||||
_round, load_time, sleep_time);
|
||||
|
||||
if (config->verbose)
|
||||
printf("avarage: %lius, rps:%li\n",
|
||||
load_time / calculations,
|
||||
1000000 * calculations / load_time);
|
||||
|
||||
/* do some sleep/load cycles with the performance governor */
|
||||
for (cycle = 0; cycle < config->cycles; cycle++) {
|
||||
now = get_time();
|
||||
usleep(sleep_time);
|
||||
ROUNDS(calculations);
|
||||
then = get_time();
|
||||
performance_time += then - now - sleep_time;
|
||||
if (config->verbose)
|
||||
printf("performance cycle took %lius, "
|
||||
"sleep: %lius, "
|
||||
"load: %lius, rounds: %u\n",
|
||||
(long)(then - now), sleep_time,
|
||||
load_time, calculations);
|
||||
}
|
||||
fprintf(config->output, "%li ",
|
||||
performance_time / config->cycles);
|
||||
|
||||
progress_time += sleep_time + load_time;
|
||||
show_progress(total_time, progress_time);
|
||||
|
||||
/* set the powersave governor which activates P-State switching
|
||||
* again */
|
||||
if (set_cpufreq_governor(config->governor, config->cpu) != 0)
|
||||
return;
|
||||
|
||||
/* again, do some sleep/load cycles with the
|
||||
* powersave governor */
|
||||
for (cycle = 0; cycle < config->cycles; cycle++) {
|
||||
now = get_time();
|
||||
usleep(sleep_time);
|
||||
ROUNDS(calculations);
|
||||
then = get_time();
|
||||
powersave_time += then - now - sleep_time;
|
||||
if (config->verbose)
|
||||
printf("powersave cycle took %lius, "
|
||||
"sleep: %lius, "
|
||||
"load: %lius, rounds: %u\n",
|
||||
(long)(then - now), sleep_time,
|
||||
load_time, calculations);
|
||||
}
|
||||
|
||||
progress_time += sleep_time + load_time;
|
||||
|
||||
/* compare the avarage sleep/load cycles */
|
||||
fprintf(config->output, "%li ",
|
||||
powersave_time / config->cycles);
|
||||
fprintf(config->output, "%.3f\n",
|
||||
performance_time * 100.0 / powersave_time);
|
||||
fflush(config->output);
|
||||
|
||||
if (config->verbose)
|
||||
printf("performance is at %.2f%%\n",
|
||||
performance_time * 100.0 / powersave_time);
|
||||
|
||||
sleep_time += config->sleep_step;
|
||||
load_time += config->load_step;
|
||||
}
|
||||
}
|
||||
29
tools/power/cpupower/bench/benchmark.h
Normal file
29
tools/power/cpupower/bench/benchmark.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* load loop, this schould take about 1 to 2ms to complete */
|
||||
#define ROUNDS(x) {unsigned int rcnt; \
|
||||
for (rcnt = 0; rcnt < x*1000; rcnt++) { \
|
||||
(void)(((int)(pow(rcnt, rcnt) * \
|
||||
sqrt(rcnt*7230970)) ^ 7230716) ^ \
|
||||
(int)atan2(rcnt, rcnt)); \
|
||||
} } \
|
||||
|
||||
|
||||
void start_benchmark(struct config *config);
|
||||
36
tools/power/cpupower/bench/config.h
Normal file
36
tools/power/cpupower/bench/config.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* initial loop count for the load calibration */
|
||||
#define GAUGECOUNT 1500
|
||||
|
||||
/* default scheduling policy SCHED_OTHER */
|
||||
#define SCHEDULER SCHED_OTHER
|
||||
|
||||
#define PRIORITY_DEFAULT 0
|
||||
#define PRIORITY_HIGH sched_get_priority_max(SCHEDULER)
|
||||
#define PRIORITY_LOW sched_get_priority_min(SCHEDULER)
|
||||
|
||||
/* enable further debug messages */
|
||||
#ifdef DEBUG
|
||||
#define dprintf printf
|
||||
#else
|
||||
#define dprintf(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
104
tools/power/cpupower/bench/cpufreq-bench_plot.sh
Normal file
104
tools/power/cpupower/bench/cpufreq-bench_plot.sh
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This program 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; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# 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; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
|
||||
|
||||
# Helper script to easily create nice plots of your cpufreq-bench results
|
||||
|
||||
dir=`mktemp -d`
|
||||
output_file="cpufreq-bench.png"
|
||||
global_title="cpufreq-bench plot"
|
||||
picture_type="jpeg"
|
||||
file[0]=""
|
||||
|
||||
function usage()
|
||||
{
|
||||
echo "cpufreq-bench_plot.sh [OPTIONS] logfile [measure_title] [logfile [measure_title]] ...]"
|
||||
echo
|
||||
echo "Options"
|
||||
echo " -o output_file"
|
||||
echo " -t global_title"
|
||||
echo " -p picture_type [jpeg|gif|png|postscript|...]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -eq 0 ];then
|
||||
echo "No benchmark results file provided"
|
||||
echo
|
||||
usage
|
||||
fi
|
||||
|
||||
while getopts o:t:p: name ; do
|
||||
case $name in
|
||||
o)
|
||||
output_file="$OPTARG".$picture_type
|
||||
;;
|
||||
t)
|
||||
global_title="$OPTARG"
|
||||
;;
|
||||
p)
|
||||
picture_type="$OPTARG"
|
||||
;;
|
||||
?)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND -1))
|
||||
|
||||
plots=0
|
||||
while [ "$1" ];do
|
||||
if [ ! -f "$1" ];then
|
||||
echo "File $1 does not exist"
|
||||
usage
|
||||
fi
|
||||
file[$plots]="$1"
|
||||
title[$plots]="$2"
|
||||
# echo "File: ${file[$plots]} - ${title[plots]}"
|
||||
shift;shift
|
||||
plots=$((plots + 1))
|
||||
done
|
||||
|
||||
echo "set terminal $picture_type" >> $dir/plot_script.gpl
|
||||
echo "set output \"$output_file\"" >> $dir/plot_script.gpl
|
||||
echo "set title \"$global_title\"" >> $dir/plot_script.gpl
|
||||
echo "set xlabel \"sleep/load time\"" >> $dir/plot_script.gpl
|
||||
echo "set ylabel \"Performance (%)\"" >> $dir/plot_script.gpl
|
||||
|
||||
for((plot=0;plot<$plots;plot++));do
|
||||
|
||||
# Sanity check
|
||||
###### I am to dump to get this redirected to stderr/stdout in one awk call... #####
|
||||
cat ${file[$plot]} |grep -v "^#" |awk '{if ($2 != $3) printf("Error in measure %d:Load time %s does not equal sleep time %s, plot will not be correct\n", $1, $2, $3); ERR=1}'
|
||||
###### I am to dump to get this redirected in one awk call... #####
|
||||
|
||||
# Parse out load time (which must be equal to sleep time for a plot), divide it by 1000
|
||||
# to get ms and parse out the performance in percentage and write it to a temp file for plotting
|
||||
cat ${file[$plot]} |grep -v "^#" |awk '{printf "%lu %.1f\n",$2/1000, $6}' >$dir/data_$plot
|
||||
|
||||
if [ $plot -eq 0 ];then
|
||||
echo -n "plot " >> $dir/plot_script.gpl
|
||||
fi
|
||||
echo -n "\"$dir/data_$plot\" title \"${title[$plot]}\" with lines" >> $dir/plot_script.gpl
|
||||
if [ $(($plot + 1)) -ne $plots ];then
|
||||
echo -n ", " >> $dir/plot_script.gpl
|
||||
fi
|
||||
done
|
||||
echo >> $dir/plot_script.gpl
|
||||
|
||||
gnuplot $dir/plot_script.gpl
|
||||
rm -r $dir
|
||||
101
tools/power/cpupower/bench/cpufreq-bench_script.sh
Normal file
101
tools/power/cpupower/bench/cpufreq-bench_script.sh
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This program 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; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# 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; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
|
||||
|
||||
# Ondemand up_threshold and sampling rate test script for cpufreq-bench
|
||||
# mircobenchmark.
|
||||
# Modify the general variables at the top or extend or copy out parts
|
||||
# if you want to test other things
|
||||
#
|
||||
|
||||
# Default with latest kernels is 95, before micro account patches
|
||||
# it was 80, cmp. with git commit 808009131046b62ac434dbc796
|
||||
UP_THRESHOLD="60 80 95"
|
||||
# Depending on the kernel and the HW sampling rate could be restricted
|
||||
# and cannot be set that low...
|
||||
# E.g. before git commit cef9615a853ebc4972084f7 one could only set
|
||||
# min sampling rate of 80000 if CONFIG_HZ=250
|
||||
SAMPLING_RATE="20000 80000"
|
||||
|
||||
function measure()
|
||||
{
|
||||
local -i up_threshold_set
|
||||
local -i sampling_rate_set
|
||||
|
||||
for up_threshold in $UP_THRESHOLD;do
|
||||
for sampling_rate in $SAMPLING_RATE;do
|
||||
# Set values in sysfs
|
||||
echo $up_threshold >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold
|
||||
echo $sampling_rate >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate
|
||||
up_threshold_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold)
|
||||
sampling_rate_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate)
|
||||
|
||||
# Verify set values in sysfs
|
||||
if [ ${up_threshold_set} -eq ${up_threshold} ];then
|
||||
echo "up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
|
||||
else
|
||||
echo "WARNING: Tried to set up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
|
||||
fi
|
||||
if [ ${sampling_rate_set} -eq ${sampling_rate} ];then
|
||||
echo "sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
|
||||
else
|
||||
echo "WARNING: Tried to set sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
|
||||
fi
|
||||
|
||||
# Benchmark
|
||||
cpufreq-bench -o /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
function create_plots()
|
||||
{
|
||||
local command
|
||||
|
||||
for up_threshold in $UP_THRESHOLD;do
|
||||
command="cpufreq-bench_plot.sh -o \"sampling_rate_${SAMPLING_RATE}_up_threshold_${up_threshold}\" -t \"Ondemand sampling_rate: ${SAMPLING_RATE} comparison - Up_threshold: $up_threshold %\""
|
||||
for sampling_rate in $SAMPLING_RATE;do
|
||||
command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"sampling_rate = $sampling_rate\""
|
||||
done
|
||||
echo $command
|
||||
eval "$command"
|
||||
echo
|
||||
done
|
||||
|
||||
for sampling_rate in $SAMPLING_RATE;do
|
||||
command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${sampling_rate}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} % comparison - sampling_rate: $sampling_rate\""
|
||||
for up_threshold in $UP_THRESHOLD;do
|
||||
command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold\""
|
||||
done
|
||||
echo $command
|
||||
eval "$command"
|
||||
echo
|
||||
done
|
||||
|
||||
command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${SAMPLING_RATE}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} and sampling_rate ${SAMPLING_RATE} comparison\""
|
||||
for sampling_rate in $SAMPLING_RATE;do
|
||||
for up_threshold in $UP_THRESHOLD;do
|
||||
command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold - sampling_rate = $sampling_rate\""
|
||||
done
|
||||
done
|
||||
echo "$command"
|
||||
eval "$command"
|
||||
}
|
||||
|
||||
measure
|
||||
create_plots
|
||||
11
tools/power/cpupower/bench/example.cfg
Normal file
11
tools/power/cpupower/bench/example.cfg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
sleep = 50000
|
||||
load = 50000
|
||||
cpu = 0
|
||||
priority = LOW
|
||||
output = /var/log/cpufreq-bench
|
||||
sleep_step = 50000
|
||||
load_step = 50000
|
||||
cycles = 20
|
||||
rounds = 40
|
||||
verbose = 0
|
||||
governor = ondemand
|
||||
202
tools/power/cpupower/bench/main.c
Normal file
202
tools/power/cpupower/bench/main.c
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "benchmark.h"
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"output", 1, 0, 'o'},
|
||||
{"sleep", 1, 0, 's'},
|
||||
{"load", 1, 0, 'l'},
|
||||
{"verbose", 0, 0, 'v'},
|
||||
{"cpu", 1, 0, 'c'},
|
||||
{"governor", 1, 0, 'g'},
|
||||
{"prio", 1, 0, 'p'},
|
||||
{"file", 1, 0, 'f'},
|
||||
{"cycles", 1, 0, 'n'},
|
||||
{"rounds", 1, 0, 'r'},
|
||||
{"load-step", 1, 0, 'x'},
|
||||
{"sleep-step", 1, 0, 'y'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/*******************************************************************
|
||||
usage
|
||||
*******************************************************************/
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("usage: ./bench\n");
|
||||
printf("Options:\n");
|
||||
printf(" -l, --load=<long int>\t\tinitial load time in us\n");
|
||||
printf(" -s, --sleep=<long int>\t\tinitial sleep time in us\n");
|
||||
printf(" -x, --load-step=<long int>\ttime to be added to load time, in us\n");
|
||||
printf(" -y, --sleep-step=<long int>\ttime to be added to sleep time, in us\n");
|
||||
printf(" -c, --cpu=<cpu #>\t\t\tCPU Nr. to use, starting at 0\n");
|
||||
printf(" -p, --prio=<priority>\t\t\tscheduler priority, HIGH, LOW or DEFAULT\n");
|
||||
printf(" -g, --governor=<governor>\t\tcpufreq governor to test\n");
|
||||
printf(" -n, --cycles=<int>\t\t\tload/sleep cycles\n");
|
||||
printf(" -r, --rounds<int>\t\t\tload/sleep rounds\n");
|
||||
printf(" -f, --file=<configfile>\t\tconfig file to use\n");
|
||||
printf(" -o, --output=<dir>\t\t\toutput path. Filename will be OUTPUTPATH/benchmark_TIMESTAMP.log\n");
|
||||
printf(" -v, --verbose\t\t\t\tverbose output on/off\n");
|
||||
printf(" -h, --help\t\t\t\tPrint this help screen\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
main
|
||||
*******************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int option_index = 0;
|
||||
struct config *config = NULL;
|
||||
|
||||
config = prepare_default_config();
|
||||
|
||||
if (config == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
while (1) {
|
||||
c = getopt_long (argc, argv, "hg:o:s:l:vc:p:f:n:r:x:y:",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'o':
|
||||
if (config->output != NULL)
|
||||
fclose(config->output);
|
||||
|
||||
config->output = prepare_output(optarg);
|
||||
|
||||
if (config->output == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
dprintf("user output path -> %s\n", optarg);
|
||||
break;
|
||||
case 's':
|
||||
sscanf(optarg, "%li", &config->sleep);
|
||||
dprintf("user sleep time -> %s\n", optarg);
|
||||
break;
|
||||
case 'l':
|
||||
sscanf(optarg, "%li", &config->load);
|
||||
dprintf("user load time -> %s\n", optarg);
|
||||
break;
|
||||
case 'c':
|
||||
sscanf(optarg, "%u", &config->cpu);
|
||||
dprintf("user cpu -> %s\n", optarg);
|
||||
break;
|
||||
case 'g':
|
||||
strncpy(config->governor, optarg, 14);
|
||||
dprintf("user governor -> %s\n", optarg);
|
||||
break;
|
||||
case 'p':
|
||||
if (string_to_prio(optarg) != SCHED_ERR) {
|
||||
config->prio = string_to_prio(optarg);
|
||||
dprintf("user prio -> %s\n", optarg);
|
||||
} else {
|
||||
if (config != NULL) {
|
||||
if (config->output != NULL)
|
||||
fclose(config->output);
|
||||
free(config);
|
||||
}
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
sscanf(optarg, "%u", &config->cycles);
|
||||
dprintf("user cycles -> %s\n", optarg);
|
||||
break;
|
||||
case 'r':
|
||||
sscanf(optarg, "%u", &config->rounds);
|
||||
dprintf("user rounds -> %s\n", optarg);
|
||||
break;
|
||||
case 'x':
|
||||
sscanf(optarg, "%li", &config->load_step);
|
||||
dprintf("user load_step -> %s\n", optarg);
|
||||
break;
|
||||
case 'y':
|
||||
sscanf(optarg, "%li", &config->sleep_step);
|
||||
dprintf("user sleep_step -> %s\n", optarg);
|
||||
break;
|
||||
case 'f':
|
||||
if (prepare_config(optarg, config))
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
case 'v':
|
||||
config->verbose = 1;
|
||||
dprintf("verbose output enabled\n");
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
if (config != NULL) {
|
||||
if (config->output != NULL)
|
||||
fclose(config->output);
|
||||
free(config);
|
||||
}
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (config->verbose) {
|
||||
printf("starting benchmark with parameters:\n");
|
||||
printf("config:\n\t"
|
||||
"sleep=%li\n\t"
|
||||
"load=%li\n\t"
|
||||
"sleep_step=%li\n\t"
|
||||
"load_step=%li\n\t"
|
||||
"cpu=%u\n\t"
|
||||
"cycles=%u\n\t"
|
||||
"rounds=%u\n\t"
|
||||
"governor=%s\n\n",
|
||||
config->sleep,
|
||||
config->load,
|
||||
config->sleep_step,
|
||||
config->load_step,
|
||||
config->cpu,
|
||||
config->cycles,
|
||||
config->rounds,
|
||||
config->governor);
|
||||
}
|
||||
|
||||
prepare_user(config);
|
||||
prepare_system(config);
|
||||
start_benchmark(config);
|
||||
|
||||
if (config->output != stdout)
|
||||
fclose(config->output);
|
||||
|
||||
free(config);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
228
tools/power/cpupower/bench/parse.c
Normal file
228
tools/power/cpupower/bench/parse.c
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "config.h"
|
||||
|
||||
/**
|
||||
* converts priority string to priority
|
||||
*
|
||||
* @param str string that represents a scheduler priority
|
||||
*
|
||||
* @retval priority
|
||||
* @retval SCHED_ERR when the priority doesn't exit
|
||||
**/
|
||||
|
||||
enum sched_prio string_to_prio(const char *str)
|
||||
{
|
||||
if (strncasecmp("high", str, strlen(str)) == 0)
|
||||
return SCHED_HIGH;
|
||||
else if (strncasecmp("default", str, strlen(str)) == 0)
|
||||
return SCHED_DEFAULT;
|
||||
else if (strncasecmp("low", str, strlen(str)) == 0)
|
||||
return SCHED_LOW;
|
||||
else
|
||||
return SCHED_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* create and open logfile
|
||||
*
|
||||
* @param dir directory in which the logfile should be created
|
||||
*
|
||||
* @retval logfile on success
|
||||
* @retval NULL when the file can't be created
|
||||
**/
|
||||
|
||||
FILE *prepare_output(const char *dirname)
|
||||
{
|
||||
FILE *output = NULL;
|
||||
int len;
|
||||
char *filename;
|
||||
struct utsname sysdata;
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir(dirname);
|
||||
if (dir == NULL) {
|
||||
if (mkdir(dirname, 0755)) {
|
||||
perror("mkdir");
|
||||
fprintf(stderr, "error: Cannot create dir %s\n",
|
||||
dirname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen(dirname) + 30;
|
||||
filename = malloc(sizeof(char) * len);
|
||||
|
||||
if (uname(&sysdata) == 0) {
|
||||
len += strlen(sysdata.nodename) + strlen(sysdata.release);
|
||||
filename = realloc(filename, sizeof(char) * len);
|
||||
|
||||
if (filename == NULL) {
|
||||
perror("realloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log",
|
||||
dirname, sysdata.nodename, sysdata.release, time(NULL));
|
||||
} else {
|
||||
snprintf(filename, len - 1, "%s/benchmark_%li.log",
|
||||
dirname, time(NULL));
|
||||
}
|
||||
|
||||
dprintf("logilename: %s\n", filename);
|
||||
|
||||
output = fopen(filename, "w+");
|
||||
if (output == NULL) {
|
||||
perror("fopen");
|
||||
fprintf(stderr, "error: unable to open logfile\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, "Logfile: %s\n", filename);
|
||||
|
||||
free(filename);
|
||||
fprintf(output, "#round load sleep performance powersave percentage\n");
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the default config
|
||||
*
|
||||
* @retval default config on success
|
||||
* @retval NULL when the output file can't be created
|
||||
**/
|
||||
|
||||
struct config *prepare_default_config()
|
||||
{
|
||||
struct config *config = malloc(sizeof(struct config));
|
||||
|
||||
dprintf("loading defaults\n");
|
||||
|
||||
config->sleep = 500000;
|
||||
config->load = 500000;
|
||||
config->sleep_step = 500000;
|
||||
config->load_step = 500000;
|
||||
config->cycles = 5;
|
||||
config->rounds = 50;
|
||||
config->cpu = 0;
|
||||
config->prio = SCHED_HIGH;
|
||||
config->verbose = 0;
|
||||
strncpy(config->governor, "ondemand", 8);
|
||||
|
||||
config->output = stdout;
|
||||
|
||||
#ifdef DEFAULT_CONFIG_FILE
|
||||
if (prepare_config(DEFAULT_CONFIG_FILE, config))
|
||||
return NULL;
|
||||
#endif
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* parses config file and returns the config to the caller
|
||||
*
|
||||
* @param path config file name
|
||||
*
|
||||
* @retval 1 on error
|
||||
* @retval 0 on success
|
||||
**/
|
||||
|
||||
int prepare_config(const char *path, struct config *config)
|
||||
{
|
||||
size_t len = 0;
|
||||
char opt[16], val[32], *line = NULL;
|
||||
FILE *configfile;
|
||||
|
||||
if (config == NULL) {
|
||||
fprintf(stderr, "error: config is NULL\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
configfile = fopen(path, "r");
|
||||
if (configfile == NULL) {
|
||||
perror("fopen");
|
||||
fprintf(stderr, "error: unable to read configfile\n");
|
||||
free(config);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (getline(&line, &len, configfile) != -1) {
|
||||
if (line[0] == '#' || line[0] == ' ' || line[0] == '\n')
|
||||
continue;
|
||||
|
||||
if (sscanf(line, "%14s = %30s", opt, val) < 2)
|
||||
continue;
|
||||
|
||||
dprintf("parsing: %s -> %s\n", opt, val);
|
||||
|
||||
if (strcmp("sleep", opt) == 0)
|
||||
sscanf(val, "%li", &config->sleep);
|
||||
|
||||
else if (strcmp("load", opt) == 0)
|
||||
sscanf(val, "%li", &config->load);
|
||||
|
||||
else if (strcmp("load_step", opt) == 0)
|
||||
sscanf(val, "%li", &config->load_step);
|
||||
|
||||
else if (strcmp("sleep_step", opt) == 0)
|
||||
sscanf(val, "%li", &config->sleep_step);
|
||||
|
||||
else if (strcmp("cycles", opt) == 0)
|
||||
sscanf(val, "%u", &config->cycles);
|
||||
|
||||
else if (strcmp("rounds", opt) == 0)
|
||||
sscanf(val, "%u", &config->rounds);
|
||||
|
||||
else if (strcmp("verbose", opt) == 0)
|
||||
sscanf(val, "%u", &config->verbose);
|
||||
|
||||
else if (strcmp("output", opt) == 0)
|
||||
config->output = prepare_output(val);
|
||||
|
||||
else if (strcmp("cpu", opt) == 0)
|
||||
sscanf(val, "%u", &config->cpu);
|
||||
|
||||
else if (strcmp("governor", opt) == 0) {
|
||||
strncpy(config->governor, val,
|
||||
sizeof(config->governor));
|
||||
config->governor[sizeof(config->governor) - 1] = '\0';
|
||||
}
|
||||
|
||||
else if (strcmp("priority", opt) == 0) {
|
||||
if (string_to_prio(val) != SCHED_ERR)
|
||||
config->prio = string_to_prio(val);
|
||||
}
|
||||
}
|
||||
|
||||
free(line);
|
||||
|
||||
return 0;
|
||||
}
|
||||
53
tools/power/cpupower/bench/parse.h
Normal file
53
tools/power/cpupower/bench/parse.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* struct that holds the required config parameters */
|
||||
struct config
|
||||
{
|
||||
long sleep; /* sleep time in µs */
|
||||
long load; /* load time in µs */
|
||||
long sleep_step; /* time value which changes the
|
||||
* sleep time after every round in µs */
|
||||
long load_step; /* time value which changes the
|
||||
* load time after every round in µs */
|
||||
unsigned int cycles; /* calculation cycles with the same sleep/load time */
|
||||
unsigned int rounds; /* calculation rounds with iterated sleep/load time */
|
||||
unsigned int cpu; /* cpu for which the affinity is set */
|
||||
char governor[15]; /* cpufreq governor */
|
||||
enum sched_prio /* possible scheduler priorities */
|
||||
{
|
||||
SCHED_ERR = -1,
|
||||
SCHED_HIGH,
|
||||
SCHED_DEFAULT,
|
||||
SCHED_LOW
|
||||
} prio;
|
||||
|
||||
unsigned int verbose; /* verbose output */
|
||||
FILE *output; /* logfile */
|
||||
char *output_filename; /* logfile name, must be freed at the end
|
||||
if output != NULL and output != stdout*/
|
||||
};
|
||||
|
||||
enum sched_prio string_to_prio(const char *str);
|
||||
|
||||
FILE *prepare_output(const char *dir);
|
||||
|
||||
int prepare_config(const char *path, struct config *config);
|
||||
struct config *prepare_default_config();
|
||||
|
||||
191
tools/power/cpupower/bench/system.c
Normal file
191
tools/power/cpupower/bench/system.c
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
#include <cpufreq.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
|
||||
/**
|
||||
* returns time since epoch in µs
|
||||
*
|
||||
* @retval time
|
||||
**/
|
||||
|
||||
long long int get_time()
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
return (long long int)(now.tv_sec * 1000000LL + now.tv_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the cpufreq governor
|
||||
*
|
||||
* @param governor cpufreq governor name
|
||||
* @param cpu cpu for which the governor should be set
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 when failed
|
||||
**/
|
||||
|
||||
int set_cpufreq_governor(char *governor, unsigned int cpu)
|
||||
{
|
||||
|
||||
dprintf("set %s as cpufreq governor\n", governor);
|
||||
|
||||
if (cpufreq_cpu_exists(cpu) != 0) {
|
||||
perror("cpufreq_cpu_exists");
|
||||
fprintf(stderr, "error: cpu %u does not exist\n", cpu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cpufreq_modify_policy_governor(cpu, governor) != 0) {
|
||||
perror("cpufreq_modify_policy_governor");
|
||||
fprintf(stderr, "error: unable to set %s governor\n", governor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets cpu affinity for the process
|
||||
*
|
||||
* @param cpu cpu# to which the affinity should be set
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 when setting the affinity failed
|
||||
**/
|
||||
|
||||
int set_cpu_affinity(unsigned int cpu)
|
||||
{
|
||||
cpu_set_t cpuset;
|
||||
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(cpu, &cpuset);
|
||||
|
||||
dprintf("set affinity to cpu #%u\n", cpu);
|
||||
|
||||
if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) {
|
||||
perror("sched_setaffinity");
|
||||
fprintf(stderr, "warning: unable to set cpu affinity\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the process priority parameter
|
||||
*
|
||||
* @param priority priority value
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 when setting the priority failed
|
||||
**/
|
||||
|
||||
int set_process_priority(int priority)
|
||||
{
|
||||
struct sched_param param;
|
||||
|
||||
dprintf("set scheduler priority to %i\n", priority);
|
||||
|
||||
param.sched_priority = priority;
|
||||
|
||||
if (sched_setscheduler(0, SCHEDULER, ¶m) < 0) {
|
||||
perror("sched_setscheduler");
|
||||
fprintf(stderr, "warning: unable to set scheduler priority\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* notifies the user that the benchmark may run some time
|
||||
*
|
||||
* @param config benchmark config values
|
||||
*
|
||||
**/
|
||||
|
||||
void prepare_user(const struct config *config)
|
||||
{
|
||||
unsigned long sleep_time = 0;
|
||||
unsigned long load_time = 0;
|
||||
unsigned int round;
|
||||
|
||||
for (round = 0; round < config->rounds; round++) {
|
||||
sleep_time += 2 * config->cycles *
|
||||
(config->sleep + config->sleep_step * round);
|
||||
load_time += 2 * config->cycles *
|
||||
(config->load + config->load_step * round) +
|
||||
(config->load + config->load_step * round * 4);
|
||||
}
|
||||
|
||||
if (config->verbose || config->output != stdout)
|
||||
printf("approx. test duration: %im\n",
|
||||
(int)((sleep_time + load_time) / 60000000));
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up the cpu affinity and scheduler priority
|
||||
*
|
||||
* @param config benchmark config values
|
||||
*
|
||||
**/
|
||||
|
||||
void prepare_system(const struct config *config)
|
||||
{
|
||||
if (config->verbose)
|
||||
printf("set cpu affinity to cpu #%u\n", config->cpu);
|
||||
|
||||
set_cpu_affinity(config->cpu);
|
||||
|
||||
switch (config->prio) {
|
||||
case SCHED_HIGH:
|
||||
if (config->verbose)
|
||||
printf("high priority condition requested\n");
|
||||
|
||||
set_process_priority(PRIORITY_HIGH);
|
||||
break;
|
||||
case SCHED_LOW:
|
||||
if (config->verbose)
|
||||
printf("low priority condition requested\n");
|
||||
|
||||
set_process_priority(PRIORITY_LOW);
|
||||
break;
|
||||
default:
|
||||
if (config->verbose)
|
||||
printf("default priority condition requested\n");
|
||||
|
||||
set_process_priority(PRIORITY_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
29
tools/power/cpupower/bench/system.h
Normal file
29
tools/power/cpupower/bench/system.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* cpufreq-bench CPUFreq microbenchmark
|
||||
*
|
||||
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
long long get_time();
|
||||
|
||||
int set_cpufreq_governor(char *governor, unsigned int cpu);
|
||||
int set_cpu_affinity(unsigned int cpu);
|
||||
int set_process_priority(int priority);
|
||||
|
||||
void prepare_user(const struct config *config);
|
||||
void prepare_system(const struct config *config);
|
||||
Loading…
Add table
Add a link
Reference in a new issue