17fe2f639SDominik Brodowski /* cpufreq-bench CPUFreq microbenchmark 27fe2f639SDominik Brodowski * 37fe2f639SDominik Brodowski * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de> 47fe2f639SDominik Brodowski * 57fe2f639SDominik Brodowski * This program is free software; you can redistribute it and/or modify 67fe2f639SDominik Brodowski * it under the terms of the GNU General Public License as published by 77fe2f639SDominik Brodowski * the Free Software Foundation; either version 2 of the License, or 87fe2f639SDominik Brodowski * (at your option) any later version. 97fe2f639SDominik Brodowski * 107fe2f639SDominik Brodowski * This program is distributed in the hope that it will be useful, 117fe2f639SDominik Brodowski * but WITHOUT ANY WARRANTY; without even the implied warranty of 127fe2f639SDominik Brodowski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137fe2f639SDominik Brodowski * GNU General Public License for more details. 147fe2f639SDominik Brodowski * 157fe2f639SDominik Brodowski * You should have received a copy of the GNU General Public License 167fe2f639SDominik Brodowski * along with this program; if not, write to the Free Software 177fe2f639SDominik Brodowski * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 187fe2f639SDominik Brodowski */ 197fe2f639SDominik Brodowski 207fe2f639SDominik Brodowski #include <stdio.h> 217fe2f639SDominik Brodowski #include <stdlib.h> 227fe2f639SDominik Brodowski #include <stdarg.h> 237fe2f639SDominik Brodowski #include <string.h> 247fe2f639SDominik Brodowski #include <time.h> 257fe2f639SDominik Brodowski #include <dirent.h> 267fe2f639SDominik Brodowski 277fe2f639SDominik Brodowski #include <sys/utsname.h> 287fe2f639SDominik Brodowski #include <sys/types.h> 297fe2f639SDominik Brodowski #include <sys/stat.h> 307fe2f639SDominik Brodowski 317fe2f639SDominik Brodowski #include "parse.h" 327fe2f639SDominik Brodowski #include "config.h" 337fe2f639SDominik Brodowski 347fe2f639SDominik Brodowski /** 357fe2f639SDominik Brodowski * converts priority string to priority 367fe2f639SDominik Brodowski * 377fe2f639SDominik Brodowski * @param str string that represents a scheduler priority 387fe2f639SDominik Brodowski * 397fe2f639SDominik Brodowski * @retval priority 407fe2f639SDominik Brodowski * @retval SCHED_ERR when the priority doesn't exit 417fe2f639SDominik Brodowski **/ 427fe2f639SDominik Brodowski 437fe2f639SDominik Brodowski enum sched_prio string_to_prio(const char *str) 447fe2f639SDominik Brodowski { 457fe2f639SDominik Brodowski if (strncasecmp("high", str, strlen(str)) == 0) 467fe2f639SDominik Brodowski return SCHED_HIGH; 477fe2f639SDominik Brodowski else if (strncasecmp("default", str, strlen(str)) == 0) 487fe2f639SDominik Brodowski return SCHED_DEFAULT; 497fe2f639SDominik Brodowski else if (strncasecmp("low", str, strlen(str)) == 0) 507fe2f639SDominik Brodowski return SCHED_LOW; 517fe2f639SDominik Brodowski else 527fe2f639SDominik Brodowski return SCHED_ERR; 537fe2f639SDominik Brodowski } 547fe2f639SDominik Brodowski 557fe2f639SDominik Brodowski /** 567fe2f639SDominik Brodowski * create and open logfile 577fe2f639SDominik Brodowski * 587fe2f639SDominik Brodowski * @param dir directory in which the logfile should be created 597fe2f639SDominik Brodowski * 607fe2f639SDominik Brodowski * @retval logfile on success 617fe2f639SDominik Brodowski * @retval NULL when the file can't be created 627fe2f639SDominik Brodowski **/ 637fe2f639SDominik Brodowski 647fe2f639SDominik Brodowski FILE *prepare_output(const char *dirname) 657fe2f639SDominik Brodowski { 667fe2f639SDominik Brodowski FILE *output = NULL; 677fe2f639SDominik Brodowski int len; 687fe2f639SDominik Brodowski char *filename; 697fe2f639SDominik Brodowski struct utsname sysdata; 707fe2f639SDominik Brodowski DIR *dir; 717fe2f639SDominik Brodowski 727fe2f639SDominik Brodowski dir = opendir(dirname); 737fe2f639SDominik Brodowski if (dir == NULL) { 747fe2f639SDominik Brodowski if (mkdir(dirname, 0755)) { 757fe2f639SDominik Brodowski perror("mkdir"); 767fe2f639SDominik Brodowski fprintf(stderr, "error: Cannot create dir %s\n", 777fe2f639SDominik Brodowski dirname); 787fe2f639SDominik Brodowski return NULL; 797fe2f639SDominik Brodowski } 807fe2f639SDominik Brodowski } 817fe2f639SDominik Brodowski 827fe2f639SDominik Brodowski len = strlen(dirname) + 30; 837fe2f639SDominik Brodowski filename = malloc(sizeof(char) * len); 847fe2f639SDominik Brodowski 857fe2f639SDominik Brodowski if (uname(&sysdata) == 0) { 867fe2f639SDominik Brodowski len += strlen(sysdata.nodename) + strlen(sysdata.release); 877fe2f639SDominik Brodowski filename = realloc(filename, sizeof(char) * len); 887fe2f639SDominik Brodowski 897fe2f639SDominik Brodowski if (filename == NULL) { 907fe2f639SDominik Brodowski perror("realloc"); 917fe2f639SDominik Brodowski return NULL; 927fe2f639SDominik Brodowski } 937fe2f639SDominik Brodowski 947fe2f639SDominik Brodowski snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", 957fe2f639SDominik Brodowski dirname, sysdata.nodename, sysdata.release, time(NULL)); 967fe2f639SDominik Brodowski } else { 9702af3cb5SDominik Brodowski snprintf(filename, len - 1, "%s/benchmark_%li.log", 9802af3cb5SDominik Brodowski dirname, time(NULL)); 997fe2f639SDominik Brodowski } 1007fe2f639SDominik Brodowski 1017fe2f639SDominik Brodowski dprintf("logilename: %s\n", filename); 1027fe2f639SDominik Brodowski 10302af3cb5SDominik Brodowski output = fopen(filename, "w+"); 10402af3cb5SDominik Brodowski if (output == NULL) { 1057fe2f639SDominik Brodowski perror("fopen"); 1067fe2f639SDominik Brodowski fprintf(stderr, "error: unable to open logfile\n"); 1077fe2f639SDominik Brodowski } 1087fe2f639SDominik Brodowski 1097fe2f639SDominik Brodowski fprintf(stdout, "Logfile: %s\n", filename); 1107fe2f639SDominik Brodowski 1117fe2f639SDominik Brodowski free(filename); 1127fe2f639SDominik Brodowski fprintf(output, "#round load sleep performance powersave percentage\n"); 1137fe2f639SDominik Brodowski return output; 1147fe2f639SDominik Brodowski } 1157fe2f639SDominik Brodowski 1167fe2f639SDominik Brodowski /** 1177fe2f639SDominik Brodowski * returns the default config 1187fe2f639SDominik Brodowski * 1197fe2f639SDominik Brodowski * @retval default config on success 1207fe2f639SDominik Brodowski * @retval NULL when the output file can't be created 1217fe2f639SDominik Brodowski **/ 1227fe2f639SDominik Brodowski 1237fe2f639SDominik Brodowski struct config *prepare_default_config() 1247fe2f639SDominik Brodowski { 1257fe2f639SDominik Brodowski struct config *config = malloc(sizeof(struct config)); 1267fe2f639SDominik Brodowski 1277fe2f639SDominik Brodowski dprintf("loading defaults\n"); 1287fe2f639SDominik Brodowski 1297fe2f639SDominik Brodowski config->sleep = 500000; 1307fe2f639SDominik Brodowski config->load = 500000; 1317fe2f639SDominik Brodowski config->sleep_step = 500000; 1327fe2f639SDominik Brodowski config->load_step = 500000; 1337fe2f639SDominik Brodowski config->cycles = 5; 1347fe2f639SDominik Brodowski config->rounds = 50; 1357fe2f639SDominik Brodowski config->cpu = 0; 1367fe2f639SDominik Brodowski config->prio = SCHED_HIGH; 1377fe2f639SDominik Brodowski config->verbose = 0; 1387fe2f639SDominik Brodowski strncpy(config->governor, "ondemand", 8); 1397fe2f639SDominik Brodowski 1407fe2f639SDominik Brodowski config->output = stdout; 1417fe2f639SDominik Brodowski 1427fe2f639SDominik Brodowski #ifdef DEFAULT_CONFIG_FILE 1437fe2f639SDominik Brodowski if (prepare_config(DEFAULT_CONFIG_FILE, config)) 1447fe2f639SDominik Brodowski return NULL; 1457fe2f639SDominik Brodowski #endif 1467fe2f639SDominik Brodowski return config; 1477fe2f639SDominik Brodowski } 1487fe2f639SDominik Brodowski 1497fe2f639SDominik Brodowski /** 1507fe2f639SDominik Brodowski * parses config file and returns the config to the caller 1517fe2f639SDominik Brodowski * 1527fe2f639SDominik Brodowski * @param path config file name 1537fe2f639SDominik Brodowski * 1547fe2f639SDominik Brodowski * @retval 1 on error 1557fe2f639SDominik Brodowski * @retval 0 on success 1567fe2f639SDominik Brodowski **/ 1577fe2f639SDominik Brodowski 1587fe2f639SDominik Brodowski int prepare_config(const char *path, struct config *config) 1597fe2f639SDominik Brodowski { 1607fe2f639SDominik Brodowski size_t len = 0; 161*13f6de52SRickard Strandqvist char opt[16], val[32], *line = NULL; 162*13f6de52SRickard Strandqvist FILE *configfile; 1637fe2f639SDominik Brodowski 1647fe2f639SDominik Brodowski if (config == NULL) { 1657fe2f639SDominik Brodowski fprintf(stderr, "error: config is NULL\n"); 1667fe2f639SDominik Brodowski return 1; 1677fe2f639SDominik Brodowski } 1687fe2f639SDominik Brodowski 169*13f6de52SRickard Strandqvist configfile = fopen(path, "r"); 1707fe2f639SDominik Brodowski if (configfile == NULL) { 1717fe2f639SDominik Brodowski perror("fopen"); 1727fe2f639SDominik Brodowski fprintf(stderr, "error: unable to read configfile\n"); 1737fe2f639SDominik Brodowski free(config); 1747fe2f639SDominik Brodowski return 1; 1757fe2f639SDominik Brodowski } 1767fe2f639SDominik Brodowski 17702af3cb5SDominik Brodowski while (getline(&line, &len, configfile) != -1) { 178*13f6de52SRickard Strandqvist if (line[0] == '#' || line[0] == ' ' || line[0] == '\n') 1797fe2f639SDominik Brodowski continue; 1807fe2f639SDominik Brodowski 181*13f6de52SRickard Strandqvist if (sscanf(line, "%14s = %30s", opt, val) < 2) 182*13f6de52SRickard Strandqvist continue; 1837fe2f639SDominik Brodowski 1847fe2f639SDominik Brodowski dprintf("parsing: %s -> %s\n", opt, val); 1857fe2f639SDominik Brodowski 186*13f6de52SRickard Strandqvist if (strcmp("sleep", opt) == 0) 1877fe2f639SDominik Brodowski sscanf(val, "%li", &config->sleep); 1887fe2f639SDominik Brodowski 189*13f6de52SRickard Strandqvist else if (strcmp("load", opt) == 0) 1907fe2f639SDominik Brodowski sscanf(val, "%li", &config->load); 1917fe2f639SDominik Brodowski 192*13f6de52SRickard Strandqvist else if (strcmp("load_step", opt) == 0) 1937fe2f639SDominik Brodowski sscanf(val, "%li", &config->load_step); 1947fe2f639SDominik Brodowski 195*13f6de52SRickard Strandqvist else if (strcmp("sleep_step", opt) == 0) 1967fe2f639SDominik Brodowski sscanf(val, "%li", &config->sleep_step); 1977fe2f639SDominik Brodowski 198*13f6de52SRickard Strandqvist else if (strcmp("cycles", opt) == 0) 1997fe2f639SDominik Brodowski sscanf(val, "%u", &config->cycles); 2007fe2f639SDominik Brodowski 201*13f6de52SRickard Strandqvist else if (strcmp("rounds", opt) == 0) 2027fe2f639SDominik Brodowski sscanf(val, "%u", &config->rounds); 2037fe2f639SDominik Brodowski 204*13f6de52SRickard Strandqvist else if (strcmp("verbose", opt) == 0) 2057fe2f639SDominik Brodowski sscanf(val, "%u", &config->verbose); 2067fe2f639SDominik Brodowski 207*13f6de52SRickard Strandqvist else if (strcmp("output", opt) == 0) 2087fe2f639SDominik Brodowski config->output = prepare_output(val); 2097fe2f639SDominik Brodowski 210*13f6de52SRickard Strandqvist else if (strcmp("cpu", opt) == 0) 2117fe2f639SDominik Brodowski sscanf(val, "%u", &config->cpu); 2127fe2f639SDominik Brodowski 213*13f6de52SRickard Strandqvist else if (strcmp("governor", opt) == 0) { 214*13f6de52SRickard Strandqvist strncpy(config->governor, val, 215*13f6de52SRickard Strandqvist sizeof(config->governor)); 216*13f6de52SRickard Strandqvist config->governor[sizeof(config->governor) - 1] = '\0'; 217*13f6de52SRickard Strandqvist } 2187fe2f639SDominik Brodowski 219*13f6de52SRickard Strandqvist else if (strcmp("priority", opt) == 0) { 2207fe2f639SDominik Brodowski if (string_to_prio(val) != SCHED_ERR) 2217fe2f639SDominik Brodowski config->prio = string_to_prio(val); 2227fe2f639SDominik Brodowski } 2237fe2f639SDominik Brodowski } 2247fe2f639SDominik Brodowski 2257fe2f639SDominik Brodowski free(line); 2267fe2f639SDominik Brodowski 2277fe2f639SDominik Brodowski return 0; 2287fe2f639SDominik Brodowski } 229