1*1a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
27fe2f639SDominik Brodowski /* cpufreq-bench CPUFreq microbenchmark
37fe2f639SDominik Brodowski *
47fe2f639SDominik Brodowski * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
57fe2f639SDominik Brodowski */
67fe2f639SDominik Brodowski
77fe2f639SDominik Brodowski #include <stdio.h>
87fe2f639SDominik Brodowski #include <time.h>
97fe2f639SDominik Brodowski #include <sys/time.h>
107fe2f639SDominik Brodowski #include <sys/types.h>
117fe2f639SDominik Brodowski #include <unistd.h>
127fe2f639SDominik Brodowski
137fe2f639SDominik Brodowski #include <sched.h>
147fe2f639SDominik Brodowski
157fe2f639SDominik Brodowski #include <cpufreq.h>
16ac5a181dSThomas Renninger #include <cpupower.h>
177fe2f639SDominik Brodowski
187fe2f639SDominik Brodowski #include "config.h"
197fe2f639SDominik Brodowski #include "system.h"
207fe2f639SDominik Brodowski
217fe2f639SDominik Brodowski /**
2202af3cb5SDominik Brodowski * returns time since epoch in µs
237fe2f639SDominik Brodowski *
247fe2f639SDominik Brodowski * @retval time
257fe2f639SDominik Brodowski **/
267fe2f639SDominik Brodowski
get_time()277fe2f639SDominik Brodowski long long int get_time()
287fe2f639SDominik Brodowski {
297fe2f639SDominik Brodowski struct timeval now;
307fe2f639SDominik Brodowski
317fe2f639SDominik Brodowski gettimeofday(&now, NULL);
327fe2f639SDominik Brodowski
337fe2f639SDominik Brodowski return (long long int)(now.tv_sec * 1000000LL + now.tv_usec);
347fe2f639SDominik Brodowski }
357fe2f639SDominik Brodowski
367fe2f639SDominik Brodowski /**
377fe2f639SDominik Brodowski * sets the cpufreq governor
387fe2f639SDominik Brodowski *
397fe2f639SDominik Brodowski * @param governor cpufreq governor name
407fe2f639SDominik Brodowski * @param cpu cpu for which the governor should be set
417fe2f639SDominik Brodowski *
427fe2f639SDominik Brodowski * @retval 0 on success
437fe2f639SDominik Brodowski * @retval -1 when failed
447fe2f639SDominik Brodowski **/
457fe2f639SDominik Brodowski
set_cpufreq_governor(char * governor,unsigned int cpu)467fe2f639SDominik Brodowski int set_cpufreq_governor(char *governor, unsigned int cpu)
477fe2f639SDominik Brodowski {
487fe2f639SDominik Brodowski
497fe2f639SDominik Brodowski dprintf("set %s as cpufreq governor\n", governor);
507fe2f639SDominik Brodowski
5153d1cd6bSAbhishek Goel if (cpupower_is_cpu_online(cpu) != 1) {
527fe2f639SDominik Brodowski perror("cpufreq_cpu_exists");
537fe2f639SDominik Brodowski fprintf(stderr, "error: cpu %u does not exist\n", cpu);
547fe2f639SDominik Brodowski return -1;
557fe2f639SDominik Brodowski }
567fe2f639SDominik Brodowski
577fe2f639SDominik Brodowski if (cpufreq_modify_policy_governor(cpu, governor) != 0) {
587fe2f639SDominik Brodowski perror("cpufreq_modify_policy_governor");
597fe2f639SDominik Brodowski fprintf(stderr, "error: unable to set %s governor\n", governor);
607fe2f639SDominik Brodowski return -1;
617fe2f639SDominik Brodowski }
627fe2f639SDominik Brodowski
637fe2f639SDominik Brodowski return 0;
647fe2f639SDominik Brodowski }
657fe2f639SDominik Brodowski
667fe2f639SDominik Brodowski /**
677fe2f639SDominik Brodowski * sets cpu affinity for the process
687fe2f639SDominik Brodowski *
697fe2f639SDominik Brodowski * @param cpu cpu# to which the affinity should be set
707fe2f639SDominik Brodowski *
717fe2f639SDominik Brodowski * @retval 0 on success
727fe2f639SDominik Brodowski * @retval -1 when setting the affinity failed
737fe2f639SDominik Brodowski **/
747fe2f639SDominik Brodowski
set_cpu_affinity(unsigned int cpu)757fe2f639SDominik Brodowski int set_cpu_affinity(unsigned int cpu)
767fe2f639SDominik Brodowski {
777fe2f639SDominik Brodowski cpu_set_t cpuset;
787fe2f639SDominik Brodowski
797fe2f639SDominik Brodowski CPU_ZERO(&cpuset);
807fe2f639SDominik Brodowski CPU_SET(cpu, &cpuset);
817fe2f639SDominik Brodowski
827fe2f639SDominik Brodowski dprintf("set affinity to cpu #%u\n", cpu);
837fe2f639SDominik Brodowski
847fe2f639SDominik Brodowski if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) {
857fe2f639SDominik Brodowski perror("sched_setaffinity");
867fe2f639SDominik Brodowski fprintf(stderr, "warning: unable to set cpu affinity\n");
877fe2f639SDominik Brodowski return -1;
887fe2f639SDominik Brodowski }
897fe2f639SDominik Brodowski
907fe2f639SDominik Brodowski return 0;
917fe2f639SDominik Brodowski }
927fe2f639SDominik Brodowski
937fe2f639SDominik Brodowski /**
947fe2f639SDominik Brodowski * sets the process priority parameter
957fe2f639SDominik Brodowski *
967fe2f639SDominik Brodowski * @param priority priority value
977fe2f639SDominik Brodowski *
987fe2f639SDominik Brodowski * @retval 0 on success
997fe2f639SDominik Brodowski * @retval -1 when setting the priority failed
1007fe2f639SDominik Brodowski **/
1017fe2f639SDominik Brodowski
set_process_priority(int priority)1027fe2f639SDominik Brodowski int set_process_priority(int priority)
1037fe2f639SDominik Brodowski {
1047fe2f639SDominik Brodowski struct sched_param param;
1057fe2f639SDominik Brodowski
1067fe2f639SDominik Brodowski dprintf("set scheduler priority to %i\n", priority);
1077fe2f639SDominik Brodowski
1087fe2f639SDominik Brodowski param.sched_priority = priority;
1097fe2f639SDominik Brodowski
1107fe2f639SDominik Brodowski if (sched_setscheduler(0, SCHEDULER, ¶m) < 0) {
1117fe2f639SDominik Brodowski perror("sched_setscheduler");
1127fe2f639SDominik Brodowski fprintf(stderr, "warning: unable to set scheduler priority\n");
1137fe2f639SDominik Brodowski return -1;
1147fe2f639SDominik Brodowski }
1157fe2f639SDominik Brodowski
1167fe2f639SDominik Brodowski return 0;
1177fe2f639SDominik Brodowski }
1187fe2f639SDominik Brodowski
1197fe2f639SDominik Brodowski /**
12002af3cb5SDominik Brodowski * notifies the user that the benchmark may run some time
1217fe2f639SDominik Brodowski *
1227fe2f639SDominik Brodowski * @param config benchmark config values
1237fe2f639SDominik Brodowski *
1247fe2f639SDominik Brodowski **/
1257fe2f639SDominik Brodowski
prepare_user(const struct config * config)1267fe2f639SDominik Brodowski void prepare_user(const struct config *config)
1277fe2f639SDominik Brodowski {
1287fe2f639SDominik Brodowski unsigned long sleep_time = 0;
1297fe2f639SDominik Brodowski unsigned long load_time = 0;
1307fe2f639SDominik Brodowski unsigned int round;
1317fe2f639SDominik Brodowski
1327fe2f639SDominik Brodowski for (round = 0; round < config->rounds; round++) {
13302af3cb5SDominik Brodowski sleep_time += 2 * config->cycles *
13402af3cb5SDominik Brodowski (config->sleep + config->sleep_step * round);
13502af3cb5SDominik Brodowski load_time += 2 * config->cycles *
13602af3cb5SDominik Brodowski (config->load + config->load_step * round) +
13702af3cb5SDominik Brodowski (config->load + config->load_step * round * 4);
1387fe2f639SDominik Brodowski }
1397fe2f639SDominik Brodowski
1407fe2f639SDominik Brodowski if (config->verbose || config->output != stdout)
1417fe2f639SDominik Brodowski printf("approx. test duration: %im\n",
1427fe2f639SDominik Brodowski (int)((sleep_time + load_time) / 60000000));
1437fe2f639SDominik Brodowski }
1447fe2f639SDominik Brodowski
1457fe2f639SDominik Brodowski /**
1467fe2f639SDominik Brodowski * sets up the cpu affinity and scheduler priority
1477fe2f639SDominik Brodowski *
1487fe2f639SDominik Brodowski * @param config benchmark config values
1497fe2f639SDominik Brodowski *
1507fe2f639SDominik Brodowski **/
1517fe2f639SDominik Brodowski
prepare_system(const struct config * config)1527fe2f639SDominik Brodowski void prepare_system(const struct config *config)
1537fe2f639SDominik Brodowski {
1547fe2f639SDominik Brodowski if (config->verbose)
1557fe2f639SDominik Brodowski printf("set cpu affinity to cpu #%u\n", config->cpu);
1567fe2f639SDominik Brodowski
1577fe2f639SDominik Brodowski set_cpu_affinity(config->cpu);
1587fe2f639SDominik Brodowski
1597fe2f639SDominik Brodowski switch (config->prio) {
1607fe2f639SDominik Brodowski case SCHED_HIGH:
1617fe2f639SDominik Brodowski if (config->verbose)
1627fe2f639SDominik Brodowski printf("high priority condition requested\n");
1637fe2f639SDominik Brodowski
1647fe2f639SDominik Brodowski set_process_priority(PRIORITY_HIGH);
1657fe2f639SDominik Brodowski break;
1667fe2f639SDominik Brodowski case SCHED_LOW:
1677fe2f639SDominik Brodowski if (config->verbose)
1687fe2f639SDominik Brodowski printf("low priority condition requested\n");
1697fe2f639SDominik Brodowski
1707fe2f639SDominik Brodowski set_process_priority(PRIORITY_LOW);
1717fe2f639SDominik Brodowski break;
1727fe2f639SDominik Brodowski default:
1737fe2f639SDominik Brodowski if (config->verbose)
1747fe2f639SDominik Brodowski printf("default priority condition requested\n");
1757fe2f639SDominik Brodowski
1767fe2f639SDominik Brodowski set_process_priority(PRIORITY_DEFAULT);
1777fe2f639SDominik Brodowski }
1787fe2f639SDominik Brodowski }
1797fe2f639SDominik Brodowski
180