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; 680b81561cSArjun Sreedharan char *filename, *filename_tmp; 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); 84983d9e06SColin Ian King if (!filename) { 85983d9e06SColin Ian King perror("malloc"); 86983d9e06SColin Ian King goto out_dir; 87983d9e06SColin Ian King } 887fe2f639SDominik Brodowski 897fe2f639SDominik Brodowski if (uname(&sysdata) == 0) { 907fe2f639SDominik Brodowski len += strlen(sysdata.nodename) + strlen(sysdata.release); 910b81561cSArjun Sreedharan filename_tmp = realloc(filename, sizeof(*filename) * len); 927fe2f639SDominik Brodowski 930b81561cSArjun Sreedharan if (filename_tmp == NULL) { 940b81561cSArjun Sreedharan free(filename); 957fe2f639SDominik Brodowski perror("realloc"); 96983d9e06SColin Ian King goto out_dir; 977fe2f639SDominik Brodowski } 987fe2f639SDominik Brodowski 990b81561cSArjun Sreedharan filename = filename_tmp; 1007fe2f639SDominik Brodowski snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", 1017fe2f639SDominik Brodowski dirname, sysdata.nodename, sysdata.release, time(NULL)); 1027fe2f639SDominik Brodowski } else { 10302af3cb5SDominik Brodowski snprintf(filename, len - 1, "%s/benchmark_%li.log", 10402af3cb5SDominik Brodowski dirname, time(NULL)); 1057fe2f639SDominik Brodowski } 1067fe2f639SDominik Brodowski 107*9fd0c404SColin Ian King dprintf("logfilename: %s\n", filename); 1087fe2f639SDominik Brodowski 10902af3cb5SDominik Brodowski output = fopen(filename, "w+"); 11002af3cb5SDominik Brodowski if (output == NULL) { 1117fe2f639SDominik Brodowski perror("fopen"); 1127fe2f639SDominik Brodowski fprintf(stderr, "error: unable to open logfile\n"); 113983d9e06SColin Ian King goto out; 1147fe2f639SDominik Brodowski } 1157fe2f639SDominik Brodowski 1167fe2f639SDominik Brodowski fprintf(stdout, "Logfile: %s\n", filename); 1177fe2f639SDominik Brodowski 1187fe2f639SDominik Brodowski fprintf(output, "#round load sleep performance powersave percentage\n"); 119983d9e06SColin Ian King out: 120983d9e06SColin Ian King free(filename); 121983d9e06SColin Ian King out_dir: 122983d9e06SColin Ian King closedir(dir); 1237fe2f639SDominik Brodowski return output; 1247fe2f639SDominik Brodowski } 1257fe2f639SDominik Brodowski 1267fe2f639SDominik Brodowski /** 1277fe2f639SDominik Brodowski * returns the default config 1287fe2f639SDominik Brodowski * 1297fe2f639SDominik Brodowski * @retval default config on success 1307fe2f639SDominik Brodowski * @retval NULL when the output file can't be created 1317fe2f639SDominik Brodowski **/ 1327fe2f639SDominik Brodowski 1337fe2f639SDominik Brodowski struct config *prepare_default_config() 1347fe2f639SDominik Brodowski { 1357fe2f639SDominik Brodowski struct config *config = malloc(sizeof(struct config)); 1367fe2f639SDominik Brodowski 1377fe2f639SDominik Brodowski dprintf("loading defaults\n"); 1387fe2f639SDominik Brodowski 1397fe2f639SDominik Brodowski config->sleep = 500000; 1407fe2f639SDominik Brodowski config->load = 500000; 1417fe2f639SDominik Brodowski config->sleep_step = 500000; 1427fe2f639SDominik Brodowski config->load_step = 500000; 1437fe2f639SDominik Brodowski config->cycles = 5; 1447fe2f639SDominik Brodowski config->rounds = 50; 1457fe2f639SDominik Brodowski config->cpu = 0; 1467fe2f639SDominik Brodowski config->prio = SCHED_HIGH; 1477fe2f639SDominik Brodowski config->verbose = 0; 1487fe2f639SDominik Brodowski strncpy(config->governor, "ondemand", 8); 1497fe2f639SDominik Brodowski 1507fe2f639SDominik Brodowski config->output = stdout; 1517fe2f639SDominik Brodowski 1527fe2f639SDominik Brodowski #ifdef DEFAULT_CONFIG_FILE 1537fe2f639SDominik Brodowski if (prepare_config(DEFAULT_CONFIG_FILE, config)) 1547fe2f639SDominik Brodowski return NULL; 1557fe2f639SDominik Brodowski #endif 1567fe2f639SDominik Brodowski return config; 1577fe2f639SDominik Brodowski } 1587fe2f639SDominik Brodowski 1597fe2f639SDominik Brodowski /** 1607fe2f639SDominik Brodowski * parses config file and returns the config to the caller 1617fe2f639SDominik Brodowski * 1627fe2f639SDominik Brodowski * @param path config file name 1637fe2f639SDominik Brodowski * 1647fe2f639SDominik Brodowski * @retval 1 on error 1657fe2f639SDominik Brodowski * @retval 0 on success 1667fe2f639SDominik Brodowski **/ 1677fe2f639SDominik Brodowski 1687fe2f639SDominik Brodowski int prepare_config(const char *path, struct config *config) 1697fe2f639SDominik Brodowski { 1707fe2f639SDominik Brodowski size_t len = 0; 17113f6de52SRickard Strandqvist char opt[16], val[32], *line = NULL; 17213f6de52SRickard Strandqvist FILE *configfile; 1737fe2f639SDominik Brodowski 1747fe2f639SDominik Brodowski if (config == NULL) { 1757fe2f639SDominik Brodowski fprintf(stderr, "error: config is NULL\n"); 1767fe2f639SDominik Brodowski return 1; 1777fe2f639SDominik Brodowski } 1787fe2f639SDominik Brodowski 17913f6de52SRickard Strandqvist configfile = fopen(path, "r"); 1807fe2f639SDominik Brodowski if (configfile == NULL) { 1817fe2f639SDominik Brodowski perror("fopen"); 1827fe2f639SDominik Brodowski fprintf(stderr, "error: unable to read configfile\n"); 1837fe2f639SDominik Brodowski free(config); 1847fe2f639SDominik Brodowski return 1; 1857fe2f639SDominik Brodowski } 1867fe2f639SDominik Brodowski 18702af3cb5SDominik Brodowski while (getline(&line, &len, configfile) != -1) { 18813f6de52SRickard Strandqvist if (line[0] == '#' || line[0] == ' ' || line[0] == '\n') 1897fe2f639SDominik Brodowski continue; 1907fe2f639SDominik Brodowski 19113f6de52SRickard Strandqvist if (sscanf(line, "%14s = %30s", opt, val) < 2) 19213f6de52SRickard Strandqvist continue; 1937fe2f639SDominik Brodowski 1947fe2f639SDominik Brodowski dprintf("parsing: %s -> %s\n", opt, val); 1957fe2f639SDominik Brodowski 19613f6de52SRickard Strandqvist if (strcmp("sleep", opt) == 0) 1977fe2f639SDominik Brodowski sscanf(val, "%li", &config->sleep); 1987fe2f639SDominik Brodowski 19913f6de52SRickard Strandqvist else if (strcmp("load", opt) == 0) 2007fe2f639SDominik Brodowski sscanf(val, "%li", &config->load); 2017fe2f639SDominik Brodowski 20213f6de52SRickard Strandqvist else if (strcmp("load_step", opt) == 0) 2037fe2f639SDominik Brodowski sscanf(val, "%li", &config->load_step); 2047fe2f639SDominik Brodowski 20513f6de52SRickard Strandqvist else if (strcmp("sleep_step", opt) == 0) 2067fe2f639SDominik Brodowski sscanf(val, "%li", &config->sleep_step); 2077fe2f639SDominik Brodowski 20813f6de52SRickard Strandqvist else if (strcmp("cycles", opt) == 0) 2097fe2f639SDominik Brodowski sscanf(val, "%u", &config->cycles); 2107fe2f639SDominik Brodowski 21113f6de52SRickard Strandqvist else if (strcmp("rounds", opt) == 0) 2127fe2f639SDominik Brodowski sscanf(val, "%u", &config->rounds); 2137fe2f639SDominik Brodowski 21413f6de52SRickard Strandqvist else if (strcmp("verbose", opt) == 0) 2157fe2f639SDominik Brodowski sscanf(val, "%u", &config->verbose); 2167fe2f639SDominik Brodowski 21713f6de52SRickard Strandqvist else if (strcmp("output", opt) == 0) 2187fe2f639SDominik Brodowski config->output = prepare_output(val); 2197fe2f639SDominik Brodowski 22013f6de52SRickard Strandqvist else if (strcmp("cpu", opt) == 0) 2217fe2f639SDominik Brodowski sscanf(val, "%u", &config->cpu); 2227fe2f639SDominik Brodowski 22313f6de52SRickard Strandqvist else if (strcmp("governor", opt) == 0) { 22413f6de52SRickard Strandqvist strncpy(config->governor, val, 22513f6de52SRickard Strandqvist sizeof(config->governor)); 22613f6de52SRickard Strandqvist config->governor[sizeof(config->governor) - 1] = '\0'; 22713f6de52SRickard Strandqvist } 2287fe2f639SDominik Brodowski 22913f6de52SRickard Strandqvist else if (strcmp("priority", opt) == 0) { 2307fe2f639SDominik Brodowski if (string_to_prio(val) != SCHED_ERR) 2317fe2f639SDominik Brodowski config->prio = string_to_prio(val); 2327fe2f639SDominik Brodowski } 2337fe2f639SDominik Brodowski } 2347fe2f639SDominik Brodowski 2357fe2f639SDominik Brodowski free(line); 2367fe2f639SDominik Brodowski 2377fe2f639SDominik Brodowski return 0; 2387fe2f639SDominik Brodowski } 239