| @@ -1,57 +1,68 @@ | | | @@ -1,57 +1,68 @@ |
1 | $NetBSD: patch-estd.c,v 1.2 2019/10/06 11:35:16 jmcneill Exp $ | | 1 | $NetBSD: patch-estd.c,v 1.3 2023/06/23 23:25:52 mrg Exp $ |
2 | | | 2 | |
3 | - Removed useless "estd: Forked" message | | 3 | - Removed useless "estd: Forked" message |
4 | - Add support for generic multi-domain frequency controls | | 4 | - Add support for generic multi-domain frequency controls |
| | | 5 | - Add support for -x/-X options: SIGUSR* adjust min or max speed. |
| | | 6 | Will adjust all frequency domains max or min, up or down. |
5 | | | 7 | |
6 | --- estd.c.orig 2015-02-18 21:38:03.000000000 +0000 | | 8 | --- estd.c.orig 2015-02-18 13:38:03.000000000 -0800 |
7 | +++ estd.c | | 9 | +++ estd.c 2023-06-22 02:47:03.614057986 -0700 |
8 | @@ -58,8 +58,9 @@ | | 10 | @@ -58,8 +58,9 @@ |
9 | #define TECH_INTREPID 4 | | 11 | #define TECH_INTREPID 4 |
10 | #define TECH_LOONGSON 5 | | 12 | #define TECH_LOONGSON 5 |
11 | #define TECH_ROCKCHIP 6 | | 13 | #define TECH_ROCKCHIP 6 |
12 | -#define TECH_GENERIC 7 | | 14 | -#define TECH_GENERIC 7 |
13 | -#define TECH_MAX 7 | | 15 | -#define TECH_MAX 7 |
14 | +#define TECH_GENERIC_MD 7 | | 16 | +#define TECH_GENERIC_MD 7 |
15 | +#define TECH_GENERIC 8 | | 17 | +#define TECH_GENERIC 8 |
16 | +#define TECH_MAX 8 | | 18 | +#define TECH_MAX 8 |
17 | | | 19 | |
18 | /* this is ugly, but... <shrug> */ | | 20 | /* this is ugly, but... <shrug> */ |
19 | #define MAX_FREQS 32 | | 21 | #define MAX_FREQS 32 |
20 | @@ -128,6 +129,7 @@ static char *techdesc[TECH_MAX + 1] = {" | | 22 | @@ -108,6 +109,8 @@ |
| | | 23 | int ncpus = 0; |
| | | 24 | struct domain *domain; |
| | | 25 | int ndomains; |
| | | 26 | +char minmax_mode; |
| | | 27 | +sig_atomic_t got_sigminmax; |
| | | 28 | |
| | | 29 | #if defined(__DragonFly__) |
| | | 30 | static struct kinfo_cputime *cp_time; |
| | | 31 | @@ -128,6 +131,7 @@ |
21 | "Intrepid", | | 32 | "Intrepid", |
22 | "Loongson", | | 33 | "Loongson", |
23 | "Rockchip", | | 34 | "Rockchip", |
24 | + "Generic Multi-domain", | | 35 | + "Generic Multi-domain", |
25 | "Generic" | | 36 | "Generic" |
26 | }; | | 37 | }; |
27 | static char *freqctl[TECH_MAX + 1] = { "", | | 38 | static char *freqctl[TECH_MAX + 1] = { "", |
28 | @@ -137,6 +139,7 @@ static char *freqctl[TECH_MAX + 1] = { " | | 39 | @@ -137,6 +141,7 @@ |
29 | "machdep.intrepid.frequency.available", | | 40 | "machdep.intrepid.frequency.available", |
30 | "machdep.loongson.frequency.available", | | 41 | "machdep.loongson.frequency.available", |
31 | "machdep.cpu.frequency.available", | | 42 | "machdep.cpu.frequency.available", |
32 | + "machdep.cpufreq.cpu0.available", | | 43 | + "machdep.cpufreq.cpu0.available", |
33 | "machdep.frequency.available" | | 44 | "machdep.frequency.available" |
34 | }; | | 45 | }; |
35 | static char *setctl[TECH_MAX + 1] = { "", | | 46 | static char *setctl[TECH_MAX + 1] = { "", |
36 | @@ -146,6 +149,7 @@ static char *setctl[TECH_MAX + 1] = { "" | | 47 | @@ -146,6 +151,7 @@ |
37 | "machdep.intrepid.frequency.target", | | 48 | "machdep.intrepid.frequency.target", |
38 | "machdep.loongson.frequency.target", | | 49 | "machdep.loongson.frequency.target", |
39 | "machdep.cpu.frequency.target", | | 50 | "machdep.cpu.frequency.target", |
40 | + "machdep.cpufreq.cpu0.target", | | 51 | + "machdep.cpufreq.cpu0.target", |
41 | "machdep.frequency.current" | | 52 | "machdep.frequency.current" |
42 | }; | | 53 | }; |
43 | | | 54 | |
44 | @@ -234,6 +238,63 @@ acpi_init() | | 55 | @@ -234,6 +240,63 @@ |
45 | } | | 56 | } |
46 | | | 57 | |
47 | | | 58 | |
48 | +int | | 59 | +int |
49 | +generic_md_init_cpu(int d, int cpu) | | 60 | +generic_md_init_cpu(int d, int cpu) |
50 | +{ | | 61 | +{ |
51 | + char name[256]; | | 62 | + char name[256]; |
52 | + char current[SYSCTLBUF]; | | 63 | + char current[SYSCTLBUF]; |
53 | + char *mp; | | 64 | + char *mp; |
54 | + size_t currentsize = SYSCTLBUF; | | 65 | + size_t currentsize = SYSCTLBUF; |
55 | + int i; | | 66 | + int i; |
56 | + | | 67 | + |
57 | + snprintf(name, sizeof(name), "machdep.cpufreq.cpu%d.current", cpu); | | 68 | + snprintf(name, sizeof(name), "machdep.cpufreq.cpu%d.current", cpu); |
| @@ -95,102 +106,214 @@ $NetBSD: patch-estd.c,v 1.2 2019/10/06 1 | | | @@ -95,102 +106,214 @@ $NetBSD: patch-estd.c,v 1.2 2019/10/06 1 |
95 | + int d = 0, cpu; | | 106 | + int d = 0, cpu; |
96 | + | | 107 | + |
97 | + for (cpu = 0; cpu < ncpus; cpu++) | | 108 | + for (cpu = 0; cpu < ncpus; cpu++) |
98 | + if (generic_md_init_cpu(d, cpu) == 0) | | 109 | + if (generic_md_init_cpu(d, cpu) == 0) |
99 | + d++; | | 110 | + d++; |
100 | + | | 111 | + |
101 | + return d > 0 ? 0 : 1; | | 112 | + return d > 0 ? 0 : 1; |
102 | +} | | 113 | +} |
103 | + | | 114 | + |
104 | + | | 115 | + |
105 | /* returns cpu-usage in percent, mean over the sleep-interval or -1 if an error occured */ | | 116 | /* returns cpu-usage in percent, mean over the sleep-interval or -1 if an error occured */ |
106 | #if defined(__DragonFly__) | | 117 | #if defined(__DragonFly__) |
107 | int | | 118 | int |
108 | @@ -308,8 +369,10 @@ get_cpuusage(int d) | | 119 | @@ -308,8 +371,10 @@ |
109 | int cpu_of_max = 0; | | 120 | int cpu_of_max = 0; |
110 | int cpu; | | 121 | int cpu; |
111 | int i; | | 122 | int i; |
112 | + int n; | | 123 | + int n; |
113 | | | 124 | |
114 | - for (cpu = 0; cpu < ncpus; cpu++) { | | 125 | - for (cpu = 0; cpu < ncpus; cpu++) { |
115 | + for (n = 0; n < domain[d].ncpus; n++) { | | 126 | + for (n = 0; n < domain[d].ncpus; n++) { |
116 | + cpu = domain[d].cpus[n]; | | 127 | + cpu = domain[d].cpus[n]; |
117 | u_int64_t total_time = 0; | | 128 | u_int64_t total_time = 0; |
118 | | | 129 | |
119 | for (i = 0; i < CPUSTATES; i++) { | | 130 | for (i = 0; i < CPUSTATES; i++) { |
120 | @@ -401,7 +464,7 @@ main(int argc, char *argv[]) | | 131 | @@ -384,13 +449,80 @@ |
| | | 132 | void |
| | | 133 | sigusrhandler(int sig) |
| | | 134 | { |
| | | 135 | - switch (sig) { |
| | | 136 | + if (minmax_mode) { |
| | | 137 | + got_sigminmax = sig; |
| | | 138 | + } else { |
| | | 139 | + switch (sig) { |
| | | 140 | case SIGUSR1: |
| | | 141 | - if (strategy>BATTERY) strategy--; |
| | | 142 | - break; |
| | | 143 | + if (strategy>BATTERY) strategy--; |
| | | 144 | + break; |
| | | 145 | case SIGUSR2: |
| | | 146 | - if (strategy<AGGRESSIVE) strategy++; |
| | | 147 | - break; |
| | | 148 | + if (strategy<AGGRESSIVE) strategy++; |
| | | 149 | + break; |
| | | 150 | + } |
| | | 151 | + } |
| | | 152 | +} |
| | | 153 | + |
| | | 154 | +static void handle_sigminmax(int sig) |
| | | 155 | +{ |
| | | 156 | + int d, idx; |
| | | 157 | + |
| | | 158 | + /* SIGUSR1 to reduce, SIGUSR2 to increase */ |
| | | 159 | + for (d = 0; d < ndomains; d++) { |
| | | 160 | + if (minmax_mode == 'X' && sig == SIGUSR1) { |
| | | 161 | + if (domain[d].maxidx == 0) |
| | | 162 | + return; |
| | | 163 | + domain[d].maxidx--; |
| | | 164 | + if (verbose) |
| | | 165 | + printf("SIGUSR1, reducing maxfreq to %d Mhz\n", domain[d].freqtab[domain[d].maxidx]); |
| | | 166 | + if (domain[d].maxidx < domain[d].curfreq) { |
| | | 167 | + domain[d].curfreq--; |
| | | 168 | + set_freq(d); |
| | | 169 | + set_clockmod(clockmod_min); |
| | | 170 | + if (verbose) |
| | | 171 | + printf("SIGUSR1, also set curfreq to %d Mhz\n", domain[d].freqtab[domain[d].maxidx]); |
| | | 172 | + } |
| | | 173 | + return; |
| | | 174 | + } |
| | | 175 | + if (minmax_mode == 'X' && sig == SIGUSR2) { |
| | | 176 | + if (domain[d].maxidx + 1 == domain[d].nfreqs) |
| | | 177 | + return; |
| | | 178 | + domain[d].maxidx++; |
| | | 179 | + /* |
| | | 180 | + * Nothing to worry about here; if we need to increase the |
| | | 181 | + * frequency due to load, the current iteration will. |
| | | 182 | + */ |
| | | 183 | + if (verbose) |
| | | 184 | + printf("SIGUSR1, increased maxfreq to %d Mhz\n", domain[d].freqtab[domain[d].maxidx]); |
| | | 185 | + return; |
| | | 186 | + } |
| | | 187 | + if (minmax_mode == 'x' && sig == SIGUSR1) { |
| | | 188 | + if (domain[d].minidx == 0) |
| | | 189 | + return; |
| | | 190 | + domain[d].minidx--; |
| | | 191 | + /* |
| | | 192 | + * Nothing to worry about here; if we need to increase the |
| | | 193 | + * frequency due to load, the current iteration will. |
| | | 194 | + */ |
| | | 195 | + if (verbose) |
| | | 196 | + printf("SIGUSR1, reducing minfreq to %d Mhz\n", domain[d].freqtab[domain[d].minidx]); |
| | | 197 | + return; |
| | | 198 | + } |
| | | 199 | + if (minmax_mode == 'x' && sig == SIGUSR2) { |
| | | 200 | + if (domain[d].minidx + 1 == domain[d].nfreqs) |
| | | 201 | + return; |
| | | 202 | + domain[d].minidx++; |
| | | 203 | + if (verbose) |
| | | 204 | + printf("SIGUSR1, increased minfreq to %d Mhz\n", domain[d].freqtab[domain[d].minidx]); |
| | | 205 | + if (domain[d].minidx < domain[d].curfreq) { |
| | | 206 | + domain[d].curfreq--; |
| | | 207 | + set_freq(d); |
| | | 208 | + set_clockmod(clockmod_min); |
| | | 209 | + if (verbose) |
| | | 210 | + printf("SIGUSR1, also set curfreq to %d Mhz\n", domain[d].freqtab[domain[d].minidx]); |
| | | 211 | + } |
| | | 212 | + return; |
| | | 213 | + } |
| | | 214 | } |
| | | 215 | } |
| | | 216 | |
| | | 217 | @@ -401,7 +533,7 @@ |
121 | int i; | | 218 | int i; |
122 | char frequencies[SYSCTLBUF]; /* XXX Ugly */ | | 219 | char frequencies[SYSCTLBUF]; /* XXX Ugly */ |
123 | char *fp; | | 220 | char *fp; |
124 | - size_t freqsize = SYSCTLBUF; | | 221 | - size_t freqsize = SYSCTLBUF; |
125 | + size_t freqsize; | | 222 | + size_t freqsize; |
126 | int curstrat = strategy; | | 223 | int curstrat = strategy; |
127 | int d; | | 224 | int d; |
128 | FILE *fexists; | | 225 | FILE *fexists; |
129 | @@ -410,7 +473,7 @@ main(int argc, char *argv[]) | | 226 | @@ -410,7 +542,7 @@ |
130 | #endif | | 227 | #endif |
131 | | | 228 | |
132 | /* get command-line options */ | | 229 | /* get command-line options */ |
133 | - while ((ch = getopt(argc, argv, "vfdonACEGILPasbp:h:l:g:m:M:")) != -1) | | 230 | - while ((ch = getopt(argc, argv, "vfdonACEGILPasbp:h:l:g:m:M:")) != -1) |
134 | + while ((ch = getopt(argc, argv, "vfdonACDEGILPasbp:h:l:g:m:M:")) != -1) | | 231 | + while ((ch = getopt(argc, argv, "vfdonACDEGILPasbp:h:l:g:m:M:xX")) != -1) |
135 | switch (ch) { | | 232 | switch (ch) { |
136 | case 'v': | | 233 | case 'v': |
137 | version(); | | 234 | version(); |
138 | @@ -438,6 +501,9 @@ main(int argc, char *argv[]) | | 235 | @@ -438,6 +570,9 @@ |
139 | fprintf(stderr, "-C not available under DragonFly\n"); | | 236 | fprintf(stderr, "-C not available under DragonFly\n"); |
140 | exit(1); | | 237 | exit(1); |
141 | #endif | | 238 | #endif |
142 | + case 'D': | | 239 | + case 'D': |
143 | + tech = TECH_GENERIC_MD; | | 240 | + tech = TECH_GENERIC_MD; |
144 | + break; | | 241 | + break; |
145 | case 'E': | | 242 | case 'E': |
146 | tech = TECH_EST; | | 243 | tech = TECH_EST; |
147 | break; | | 244 | break; |
148 | @@ -516,6 +582,7 @@ main(int argc, char *argv[]) | | 245 | @@ -483,6 +618,12 @@ |
| | | 246 | case 'M': |
| | | 247 | maxmhz = atoi(optarg); |
| | | 248 | break; |
| | | 249 | + case 'x': |
| | | 250 | + minmax_mode = 'x'; |
| | | 251 | + break; |
| | | 252 | + case 'X': |
| | | 253 | + minmax_mode = 'X'; |
| | | 254 | + break; |
| | | 255 | default: |
| | | 256 | usage(); |
| | | 257 | /* NOTREACHED */ |
| | | 258 | @@ -516,6 +657,7 @@ |
149 | /* try to guess cpu-scaling technology */ | | 259 | /* try to guess cpu-scaling technology */ |
150 | if (tech == TECH_UNKNOWN) { | | 260 | if (tech == TECH_UNKNOWN) { |
151 | for (tech = 1; tech <= TECH_MAX; tech++) { | | 261 | for (tech = 1; tech <= TECH_MAX; tech++) { |
152 | + freqsize = SYSCTLBUF; | | 262 | + freqsize = SYSCTLBUF; |
153 | if (sysctlbyname(freqctl[tech], &frequencies, &freqsize, NULL, 0) >= 0) break; | | 263 | if (sysctlbyname(freqctl[tech], &frequencies, &freqsize, NULL, 0) >= 0) break; |
154 | } | | 264 | } |
155 | if (tech > TECH_MAX) { | | 265 | if (tech > TECH_MAX) { |
156 | @@ -529,6 +596,11 @@ main(int argc, char *argv[]) | | 266 | @@ -529,6 +671,11 @@ |
157 | fprintf(stderr, "estd: Cannot ACPI P-States\n"); | | 267 | fprintf(stderr, "estd: Cannot ACPI P-States\n"); |
158 | exit(1); | | 268 | exit(1); |
159 | } | | 269 | } |
160 | + } else if (tech == TECH_GENERIC_MD) { | | 270 | + } else if (tech == TECH_GENERIC_MD) { |
161 | + if (generic_md_init()) { | | 271 | + if (generic_md_init()) { |
162 | + fprintf(stderr, "estd: Cannot init generic multi-domain support\n"); | | 272 | + fprintf(stderr, "estd: Cannot init generic multi-domain support\n"); |
163 | + exit(1); | | 273 | + exit(1); |
164 | + } | | 274 | + } |
165 | } else { | | 275 | } else { |
166 | domain[0].freqctl = freqctl[tech]; | | 276 | domain[0].freqctl = freqctl[tech]; |
167 | domain[0].setctl = setctl[tech]; | | 277 | domain[0].setctl = setctl[tech]; |
168 | @@ -552,6 +624,7 @@ main(int argc, char *argv[]) | | 278 | @@ -552,6 +699,7 @@ |
169 | /* for each cpu domain... */ | | 279 | /* for each cpu domain... */ |
170 | for (d = 0; d < ndomains; d++) { | | 280 | for (d = 0; d < ndomains; d++) { |
171 | /* get supported frequencies... */ | | 281 | /* get supported frequencies... */ |
172 | + freqsize = SYSCTLBUF; | | 282 | + freqsize = SYSCTLBUF; |
173 | if (sysctlbyname(domain[d].freqctl, &frequencies, &freqsize, NULL, 0) < 0) { | | 283 | if (sysctlbyname(domain[d].freqctl, &frequencies, &freqsize, NULL, 0) < 0) { |
174 | fprintf(stderr, "estd: Cannot get supported frequencies (maybe you forced the wrong CPU-scaling technology?)\n"); | | 284 | fprintf(stderr, "estd: Cannot get supported frequencies (maybe you forced the wrong CPU-scaling technology?)\n"); |
175 | exit(1); | | 285 | exit(1); |
176 | @@ -588,7 +661,11 @@ main(int argc, char *argv[]) | | 286 | @@ -588,7 +736,11 @@ |
177 | if (listfreq) { | | 287 | if (listfreq) { |
178 | printf("Supported frequencies (%s Mode):\n",techdesc[tech]); | | 288 | printf("Supported frequencies (%s Mode):\n",techdesc[tech]); |
179 | for (d = 0; d < ndomains; d++) { | | 289 | for (d = 0; d < ndomains; d++) { |
180 | - printf("Domain %d:\n", d); | | 290 | - printf("Domain %d:\n", d); |
181 | + printf("Domain %d:", d); | | 291 | + printf("Domain %d:", d); |
182 | + for (i = 0; i < domain[d].ncpus; i++) { | | 292 | + for (i = 0; i < domain[d].ncpus; i++) { |
183 | + printf(" cpu%d", domain[d].cpus[i]); | | 293 | + printf(" cpu%d", domain[d].cpus[i]); |
184 | + } | | 294 | + } |
185 | + printf("\n"); | | 295 | + printf("\n"); |
186 | for (i = 0; i < domain[d].nfreqs; i++) { | | 296 | for (i = 0; i < domain[d].nfreqs; i++) { |
187 | printf("%i MHz\n", domain[d].freqtab[i]); | | 297 | printf("%i MHz\n", domain[d].freqtab[i]); |
188 | } | | 298 | } |
189 | @@ -626,7 +703,6 @@ main(int argc, char *argv[]) | | 299 | @@ -626,7 +778,6 @@ |
190 | /* all ok, here we go */ | | 300 | /* all ok, here we go */ |
191 | if (daemonize) { | | 301 | if (daemonize) { |
192 | if (fork()) { | | 302 | if (fork()) { |
193 | - printf("estd: Forked\n"); | | 303 | - printf("estd: Forked\n"); |
194 | exit(0); | | 304 | exit(0); |
195 | } | | 305 | } |
196 | } else { | | 306 | } else { |
| | | 307 | @@ -664,6 +815,12 @@ |
| | | 308 | |
| | | 309 | /* the big processing loop, we will only exit via signal */ |
| | | 310 | while (1) { |
| | | 311 | + if (got_sigminmax) { |
| | | 312 | + int sig = got_sigminmax; |
| | | 313 | + |
| | | 314 | + got_sigminmax = 0; |
| | | 315 | + handle_sigminmax(sig); |
| | | 316 | + } |
| | | 317 | get_cputime(); |
| | | 318 | for (d = 0; d < ndomains; d++) { |
| | | 319 | domain[d].curcpu = get_cpuusage(d); |