Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/power/x86/intel-speed-select/isst-daemon.c
26292 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Intel Speed Select -- Allow speed select to daemonize
4
* Copyright (c) 2022 Intel Corporation.
5
*/
6
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <stdarg.h>
10
#include <string.h>
11
#include <unistd.h>
12
#include <fcntl.h>
13
#include <sys/file.h>
14
#include <sys/types.h>
15
#include <sys/stat.h>
16
#include <errno.h>
17
#include <getopt.h>
18
#include <signal.h>
19
#include <time.h>
20
21
#include "isst.h"
22
23
static int per_package_levels_info[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
24
static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
25
26
static void init_levels(void)
27
{
28
int i, j, k;
29
30
for (i = 0; i < MAX_PACKAGE_COUNT; ++i)
31
for (j = 0; j < MAX_DIE_PER_PACKAGE; ++j)
32
for (k = 0; k < MAX_PUNIT_PER_DIE; ++k)
33
per_package_levels_info[i][j][k] = -1;
34
}
35
36
void process_level_change(struct isst_id *id)
37
{
38
struct isst_pkg_ctdp_level_info ctdp_level;
39
struct isst_pkg_ctdp pkg_dev;
40
time_t tm;
41
int ret;
42
43
if (id->pkg < 0 || id->die < 0 || id->punit < 0) {
44
debug_printf("Invalid package/die info for cpu:%d\n", id->cpu);
45
return;
46
}
47
48
tm = time(NULL);
49
if (tm - per_package_levels_tm[id->pkg][id->die][id->punit] < 2)
50
return;
51
52
per_package_levels_tm[id->pkg][id->die][id->punit] = tm;
53
54
ret = isst_get_ctdp_levels(id, &pkg_dev);
55
if (ret) {
56
debug_printf("Can't get tdp levels for cpu:%d\n", id->cpu);
57
return;
58
}
59
60
debug_printf("Get Config level %d pkg:%d die:%d current_level:%d\n", id->cpu,
61
id->pkg, id->die, pkg_dev.current_level);
62
63
if (pkg_dev.locked) {
64
debug_printf("config TDP s locked \n");
65
return;
66
}
67
68
if (per_package_levels_info[id->pkg][id->die][id->punit] == pkg_dev.current_level)
69
return;
70
71
debug_printf("**Config level change for cpu:%d pkg:%d die:%d from %d to %d\n",
72
id->cpu, id->pkg, id->die, per_package_levels_info[id->pkg][id->die][id->punit],
73
pkg_dev.current_level);
74
75
per_package_levels_info[id->pkg][id->die][id->punit] = pkg_dev.current_level;
76
77
ctdp_level.core_cpumask_size =
78
alloc_cpu_set(&ctdp_level.core_cpumask);
79
ret = isst_get_coremask_info(id, pkg_dev.current_level, &ctdp_level);
80
if (ret) {
81
free_cpu_set(ctdp_level.core_cpumask);
82
debug_printf("Can't get core_mask:%d\n", id->cpu);
83
return;
84
}
85
86
if (use_cgroupv2()) {
87
int ret;
88
89
ret = enable_cpuset_controller();
90
if (ret)
91
goto use_offline;
92
93
isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask,
94
pkg_dev.current_level, 0);
95
96
goto free_mask;
97
}
98
99
use_offline:
100
if (ctdp_level.cpu_count) {
101
int i, max_cpus = get_topo_max_cpus();
102
for (i = 0; i < max_cpus; ++i) {
103
if (!is_cpu_in_power_domain(i, id))
104
continue;
105
if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
106
fprintf(stderr, "online cpu %d\n", i);
107
set_cpu_online_offline(i, 1);
108
} else {
109
fprintf(stderr, "offline cpu %d\n", i);
110
set_cpu_online_offline(i, 0);
111
}
112
}
113
}
114
free_mask:
115
free_cpu_set(ctdp_level.core_cpumask);
116
}
117
118
static void _poll_for_config_change(struct isst_id *id, void *arg1, void *arg2,
119
void *arg3, void *arg4)
120
{
121
process_level_change(id);
122
}
123
124
static void poll_for_config_change(void)
125
{
126
for_each_online_power_domain_in_set(_poll_for_config_change, NULL, NULL,
127
NULL, NULL);
128
}
129
130
static int done = 0;
131
static int pid_file_handle;
132
133
static void signal_handler(int sig)
134
{
135
switch (sig) {
136
case SIGINT:
137
case SIGTERM:
138
done = 1;
139
hfi_exit();
140
exit(0);
141
break;
142
default:
143
break;
144
}
145
}
146
147
static void daemonize(char *rundir, char *pidfile)
148
{
149
int pid, sid, i;
150
char str[10];
151
struct sigaction sig_actions;
152
sigset_t sig_set;
153
int ret;
154
155
if (getppid() == 1)
156
return;
157
158
sigemptyset(&sig_set);
159
sigaddset(&sig_set, SIGCHLD);
160
sigaddset(&sig_set, SIGTSTP);
161
sigaddset(&sig_set, SIGTTOU);
162
sigaddset(&sig_set, SIGTTIN);
163
sigprocmask(SIG_BLOCK, &sig_set, NULL);
164
165
sig_actions.sa_handler = signal_handler;
166
sigemptyset(&sig_actions.sa_mask);
167
sig_actions.sa_flags = 0;
168
169
sigaction(SIGHUP, &sig_actions, NULL);
170
sigaction(SIGTERM, &sig_actions, NULL);
171
sigaction(SIGINT, &sig_actions, NULL);
172
173
pid = fork();
174
if (pid < 0) {
175
/* Could not fork */
176
exit(EXIT_FAILURE);
177
}
178
if (pid > 0)
179
exit(EXIT_SUCCESS);
180
181
umask(027);
182
183
sid = setsid();
184
if (sid < 0)
185
exit(EXIT_FAILURE);
186
187
/* close all descriptors */
188
for (i = getdtablesize(); i >= 0; --i)
189
close(i);
190
191
i = open("/dev/null", O_RDWR);
192
if (i < 0)
193
exit(EXIT_FAILURE);
194
195
ret = dup(i);
196
if (ret == -1)
197
exit(EXIT_FAILURE);
198
199
ret = chdir(rundir);
200
if (ret == -1)
201
exit(EXIT_FAILURE);
202
203
pid_file_handle = open(pidfile, O_RDWR | O_CREAT, 0600);
204
if (pid_file_handle == -1) {
205
/* Couldn't open lock file */
206
exit(1);
207
}
208
/* Try to lock file */
209
#ifdef LOCKF_SUPPORT
210
if (lockf(pid_file_handle, F_TLOCK, 0) == -1) {
211
#else
212
if (flock(pid_file_handle, LOCK_EX|LOCK_NB) < 0) {
213
#endif
214
/* Couldn't get lock on lock file */
215
fprintf(stderr, "Couldn't get lock file %d\n", getpid());
216
exit(1);
217
}
218
snprintf(str, sizeof(str), "%d\n", getpid());
219
ret = write(pid_file_handle, str, strlen(str));
220
if (ret == -1)
221
exit(EXIT_FAILURE);
222
223
close(i);
224
}
225
226
int isst_daemon(int debug_mode, int poll_interval, int no_daemon)
227
{
228
int ret;
229
230
if (!no_daemon && poll_interval < 0 && !debug_mode) {
231
fprintf(stderr, "OOB mode is enabled and will run as daemon\n");
232
daemonize((char *) "/tmp/",
233
(char *)"/tmp/hfi-events.pid");
234
} else {
235
signal(SIGINT, signal_handler);
236
}
237
238
init_levels();
239
240
if (poll_interval < 0) {
241
ret = hfi_main();
242
if (ret) {
243
fprintf(stderr, "HFI initialization failed\n");
244
}
245
fprintf(stderr, "Must specify poll-interval\n");
246
return ret;
247
}
248
249
debug_printf("Starting loop\n");
250
while (!done) {
251
sleep(poll_interval);
252
poll_for_config_change();
253
}
254
255
return 0;
256
}
257
258