162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* cpufreq-bench CPUFreq microbenchmark 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <stdio.h> 862306a36Sopenharmony_ci#include <stdlib.h> 962306a36Sopenharmony_ci#include <stdarg.h> 1062306a36Sopenharmony_ci#include <string.h> 1162306a36Sopenharmony_ci#include <time.h> 1262306a36Sopenharmony_ci#include <dirent.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <sys/utsname.h> 1562306a36Sopenharmony_ci#include <sys/types.h> 1662306a36Sopenharmony_ci#include <sys/stat.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "parse.h" 1962306a36Sopenharmony_ci#include "config.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/** 2262306a36Sopenharmony_ci * converts priority string to priority 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * @param str string that represents a scheduler priority 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * @retval priority 2762306a36Sopenharmony_ci * @retval SCHED_ERR when the priority doesn't exit 2862306a36Sopenharmony_ci **/ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cienum sched_prio string_to_prio(const char *str) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci if (strncasecmp("high", str, strlen(str)) == 0) 3362306a36Sopenharmony_ci return SCHED_HIGH; 3462306a36Sopenharmony_ci else if (strncasecmp("default", str, strlen(str)) == 0) 3562306a36Sopenharmony_ci return SCHED_DEFAULT; 3662306a36Sopenharmony_ci else if (strncasecmp("low", str, strlen(str)) == 0) 3762306a36Sopenharmony_ci return SCHED_LOW; 3862306a36Sopenharmony_ci else 3962306a36Sopenharmony_ci return SCHED_ERR; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * create and open logfile 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * @param dir directory in which the logfile should be created 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * @retval logfile on success 4862306a36Sopenharmony_ci * @retval NULL when the file can't be created 4962306a36Sopenharmony_ci **/ 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciFILE *prepare_output(const char *dirname) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci FILE *output = NULL; 5462306a36Sopenharmony_ci int len; 5562306a36Sopenharmony_ci char *filename, *filename_tmp; 5662306a36Sopenharmony_ci struct utsname sysdata; 5762306a36Sopenharmony_ci DIR *dir; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dir = opendir(dirname); 6062306a36Sopenharmony_ci if (dir == NULL) { 6162306a36Sopenharmony_ci if (mkdir(dirname, 0755)) { 6262306a36Sopenharmony_ci perror("mkdir"); 6362306a36Sopenharmony_ci fprintf(stderr, "error: Cannot create dir %s\n", 6462306a36Sopenharmony_ci dirname); 6562306a36Sopenharmony_ci return NULL; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci len = strlen(dirname) + 30; 7062306a36Sopenharmony_ci filename = malloc(sizeof(char) * len); 7162306a36Sopenharmony_ci if (!filename) { 7262306a36Sopenharmony_ci perror("malloc"); 7362306a36Sopenharmony_ci goto out_dir; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (uname(&sysdata) == 0) { 7762306a36Sopenharmony_ci len += strlen(sysdata.nodename) + strlen(sysdata.release); 7862306a36Sopenharmony_ci filename_tmp = realloc(filename, sizeof(*filename) * len); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (filename_tmp == NULL) { 8162306a36Sopenharmony_ci free(filename); 8262306a36Sopenharmony_ci perror("realloc"); 8362306a36Sopenharmony_ci goto out_dir; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci filename = filename_tmp; 8762306a36Sopenharmony_ci snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", 8862306a36Sopenharmony_ci dirname, sysdata.nodename, sysdata.release, time(NULL)); 8962306a36Sopenharmony_ci } else { 9062306a36Sopenharmony_ci snprintf(filename, len - 1, "%s/benchmark_%li.log", 9162306a36Sopenharmony_ci dirname, time(NULL)); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci dprintf("logfilename: %s\n", filename); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci output = fopen(filename, "w+"); 9762306a36Sopenharmony_ci if (output == NULL) { 9862306a36Sopenharmony_ci perror("fopen"); 9962306a36Sopenharmony_ci fprintf(stderr, "error: unable to open logfile\n"); 10062306a36Sopenharmony_ci goto out; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci fprintf(stdout, "Logfile: %s\n", filename); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci fprintf(output, "#round load sleep performance powersave percentage\n"); 10662306a36Sopenharmony_ciout: 10762306a36Sopenharmony_ci free(filename); 10862306a36Sopenharmony_ciout_dir: 10962306a36Sopenharmony_ci closedir(dir); 11062306a36Sopenharmony_ci return output; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/** 11462306a36Sopenharmony_ci * returns the default config 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * @retval default config on success 11762306a36Sopenharmony_ci * @retval NULL when the output file can't be created 11862306a36Sopenharmony_ci **/ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistruct config *prepare_default_config() 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct config *config = malloc(sizeof(struct config)); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci dprintf("loading defaults\n"); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci config->sleep = 500000; 12762306a36Sopenharmony_ci config->load = 500000; 12862306a36Sopenharmony_ci config->sleep_step = 500000; 12962306a36Sopenharmony_ci config->load_step = 500000; 13062306a36Sopenharmony_ci config->cycles = 5; 13162306a36Sopenharmony_ci config->rounds = 50; 13262306a36Sopenharmony_ci config->cpu = 0; 13362306a36Sopenharmony_ci config->prio = SCHED_HIGH; 13462306a36Sopenharmony_ci config->verbose = 0; 13562306a36Sopenharmony_ci strncpy(config->governor, "ondemand", sizeof(config->governor)); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci config->output = stdout; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#ifdef DEFAULT_CONFIG_FILE 14062306a36Sopenharmony_ci if (prepare_config(DEFAULT_CONFIG_FILE, config)) 14162306a36Sopenharmony_ci return NULL; 14262306a36Sopenharmony_ci#endif 14362306a36Sopenharmony_ci return config; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/** 14762306a36Sopenharmony_ci * parses config file and returns the config to the caller 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * @param path config file name 15062306a36Sopenharmony_ci * 15162306a36Sopenharmony_ci * @retval 1 on error 15262306a36Sopenharmony_ci * @retval 0 on success 15362306a36Sopenharmony_ci **/ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ciint prepare_config(const char *path, struct config *config) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci size_t len = 0; 15862306a36Sopenharmony_ci char opt[16], val[32], *line = NULL; 15962306a36Sopenharmony_ci FILE *configfile; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (config == NULL) { 16262306a36Sopenharmony_ci fprintf(stderr, "error: config is NULL\n"); 16362306a36Sopenharmony_ci return 1; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci configfile = fopen(path, "r"); 16762306a36Sopenharmony_ci if (configfile == NULL) { 16862306a36Sopenharmony_ci perror("fopen"); 16962306a36Sopenharmony_ci fprintf(stderr, "error: unable to read configfile\n"); 17062306a36Sopenharmony_ci free(config); 17162306a36Sopenharmony_ci return 1; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci while (getline(&line, &len, configfile) != -1) { 17562306a36Sopenharmony_ci if (line[0] == '#' || line[0] == ' ' || line[0] == '\n') 17662306a36Sopenharmony_ci continue; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (sscanf(line, "%14s = %30s", opt, val) < 2) 17962306a36Sopenharmony_ci continue; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci dprintf("parsing: %s -> %s\n", opt, val); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (strcmp("sleep", opt) == 0) 18462306a36Sopenharmony_ci sscanf(val, "%li", &config->sleep); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci else if (strcmp("load", opt) == 0) 18762306a36Sopenharmony_ci sscanf(val, "%li", &config->load); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci else if (strcmp("load_step", opt) == 0) 19062306a36Sopenharmony_ci sscanf(val, "%li", &config->load_step); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci else if (strcmp("sleep_step", opt) == 0) 19362306a36Sopenharmony_ci sscanf(val, "%li", &config->sleep_step); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci else if (strcmp("cycles", opt) == 0) 19662306a36Sopenharmony_ci sscanf(val, "%u", &config->cycles); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci else if (strcmp("rounds", opt) == 0) 19962306a36Sopenharmony_ci sscanf(val, "%u", &config->rounds); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci else if (strcmp("verbose", opt) == 0) 20262306a36Sopenharmony_ci sscanf(val, "%u", &config->verbose); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci else if (strcmp("output", opt) == 0) 20562306a36Sopenharmony_ci config->output = prepare_output(val); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci else if (strcmp("cpu", opt) == 0) 20862306a36Sopenharmony_ci sscanf(val, "%u", &config->cpu); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci else if (strcmp("governor", opt) == 0) { 21162306a36Sopenharmony_ci strncpy(config->governor, val, 21262306a36Sopenharmony_ci sizeof(config->governor)); 21362306a36Sopenharmony_ci config->governor[sizeof(config->governor) - 1] = '\0'; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci else if (strcmp("priority", opt) == 0) { 21762306a36Sopenharmony_ci if (string_to_prio(val) != SCHED_ERR) 21862306a36Sopenharmony_ci config->prio = string_to_prio(val); 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci free(line); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return 0; 22562306a36Sopenharmony_ci} 226