1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* cpufreq-bench CPUFreq microbenchmark 3 * 4 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de> 5 */ 6 7 #include <stdio.h> 8 #include <time.h> 9 #include <sys/time.h> 10 #include <sys/types.h> 11 #include <unistd.h> 12 13 #include <sched.h> 14 15 #include <cpufreq.h> 16 #include <cpupower.h> 17 18 #include "config.h" 19 #include "system.h" 20 21 /** 22 * returns time since epoch in µs 23 * 24 * @retval time 25 **/ 26 27 long long int get_time() 28 { 29 struct timeval now; 30 31 gettimeofday(&now, NULL); 32 33 return (long long int)(now.tv_sec * 1000000LL + now.tv_usec); 34 } 35 36 /** 37 * sets the cpufreq governor 38 * 39 * @param governor cpufreq governor name 40 * @param cpu cpu for which the governor should be set 41 * 42 * @retval 0 on success 43 * @retval -1 when failed 44 **/ 45 46 int set_cpufreq_governor(char *governor, unsigned int cpu) 47 { 48 49 dprintf("set %s as cpufreq governor\n", governor); 50 51 if (cpupower_is_cpu_online(cpu) != 1) { 52 perror("cpufreq_cpu_exists"); 53 fprintf(stderr, "error: cpu %u does not exist\n", cpu); 54 return -1; 55 } 56 57 if (cpufreq_modify_policy_governor(cpu, governor) != 0) { 58 perror("cpufreq_modify_policy_governor"); 59 fprintf(stderr, "error: unable to set %s governor\n", governor); 60 return -1; 61 } 62 63 return 0; 64 } 65 66 /** 67 * sets cpu affinity for the process 68 * 69 * @param cpu cpu# to which the affinity should be set 70 * 71 * @retval 0 on success 72 * @retval -1 when setting the affinity failed 73 **/ 74 75 int set_cpu_affinity(unsigned int cpu) 76 { 77 cpu_set_t cpuset; 78 79 CPU_ZERO(&cpuset); 80 CPU_SET(cpu, &cpuset); 81 82 dprintf("set affinity to cpu #%u\n", cpu); 83 84 if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) { 85 perror("sched_setaffinity"); 86 fprintf(stderr, "warning: unable to set cpu affinity\n"); 87 return -1; 88 } 89 90 return 0; 91 } 92 93 /** 94 * sets the process priority parameter 95 * 96 * @param priority priority value 97 * 98 * @retval 0 on success 99 * @retval -1 when setting the priority failed 100 **/ 101 102 int set_process_priority(int priority) 103 { 104 struct sched_param param; 105 106 dprintf("set scheduler priority to %i\n", priority); 107 108 param.sched_priority = priority; 109 110 if (sched_setscheduler(0, SCHEDULER, ¶m) < 0) { 111 perror("sched_setscheduler"); 112 fprintf(stderr, "warning: unable to set scheduler priority\n"); 113 return -1; 114 } 115 116 return 0; 117 } 118 119 /** 120 * notifies the user that the benchmark may run some time 121 * 122 * @param config benchmark config values 123 * 124 **/ 125 126 void prepare_user(const struct config *config) 127 { 128 unsigned long sleep_time = 0; 129 unsigned long load_time = 0; 130 unsigned int round; 131 132 for (round = 0; round < config->rounds; round++) { 133 sleep_time += 2 * config->cycles * 134 (config->sleep + config->sleep_step * round); 135 load_time += 2 * config->cycles * 136 (config->load + config->load_step * round) + 137 (config->load + config->load_step * round * 4); 138 } 139 140 if (config->verbose || config->output != stdout) 141 printf("approx. test duration: %im\n", 142 (int)((sleep_time + load_time) / 60000000)); 143 } 144 145 /** 146 * sets up the cpu affinity and scheduler priority 147 * 148 * @param config benchmark config values 149 * 150 **/ 151 152 void prepare_system(const struct config *config) 153 { 154 if (config->verbose) 155 printf("set cpu affinity to cpu #%u\n", config->cpu); 156 157 set_cpu_affinity(config->cpu); 158 159 switch (config->prio) { 160 case SCHED_HIGH: 161 if (config->verbose) 162 printf("high priority condition requested\n"); 163 164 set_process_priority(PRIORITY_HIGH); 165 break; 166 case SCHED_LOW: 167 if (config->verbose) 168 printf("low priority condition requested\n"); 169 170 set_process_priority(PRIORITY_LOW); 171 break; 172 default: 173 if (config->verbose) 174 printf("default priority condition requested\n"); 175 176 set_process_priority(PRIORITY_DEFAULT); 177 } 178 } 179 180