1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00
VILLASnode/lib/kernel/kernel.c

283 lines
5.3 KiB
C
Raw Permalink Normal View History

2016-06-08 22:36:38 +02:00
/** Linux kernel related functions.
2015-09-17 00:55:20 +02:00
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
2017-04-27 12:56:43 +02:00
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
2017-04-27 12:56:43 +02:00
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
2017-04-27 12:56:43 +02:00
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2015-09-17 00:55:20 +02:00
*********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
2015-09-17 00:55:20 +02:00
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/wait.h>
2015-09-17 00:55:20 +02:00
2017-12-09 02:19:28 +08:00
#include <villas/utils.h>
#include <villas/config.h>
#include <villas/kernel/kernel.h>
2015-09-17 00:55:20 +02:00
int kernel_get_cacheline_size()
{
#ifdef __linux__
return sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
#else
return 64; /** @todo fixme */
#endif
}
#ifdef __linux__
int kernel_module_set_param(const char *module, const char *param, const char *value)
2015-09-17 00:55:20 +02:00
{
FILE *f;
char fn[256];
snprintf(fn, sizeof(fn), "%s/module/%s/parameters/%s", SYSFS_PATH, module, param);
f = fopen(fn, "w");
2016-06-13 17:19:47 +02:00
if (!f)
serror("Failed set parameter %s for kernel module %s to %s", module, param, value);
2017-05-05 19:09:32 +00:00
debug(LOG_KERNEL | 5, "Set parameter %s of kernel module %s to %s", module, param, value);
2016-06-13 17:19:47 +02:00
fprintf(f, "%s", value);
fclose(f);
2015-09-17 00:55:20 +02:00
return 0;
2015-09-17 00:55:20 +02:00
}
int kernel_module_load(const char *module)
2015-09-17 00:55:20 +02:00
{
int ret;
ret = kernel_module_loaded(module);
if (!ret) {
2017-05-05 19:09:32 +00:00
debug(LOG_KERNEL | 5, "Kernel module %s already loaded...", module);
return 0;
}
2015-09-17 00:55:20 +02:00
pid_t pid = fork();
switch (pid) {
case -1: // error
return -1;
2015-09-17 00:55:20 +02:00
case 0: // child
execlp("modprobe", "modprobe", module, (char *) 0);
2017-05-05 19:09:32 +00:00
exit(EXIT_FAILURE); // exec never returns
2015-09-17 00:55:20 +02:00
default:
2017-05-05 19:09:32 +00:00
wait(&ret);
2015-09-17 00:55:20 +02:00
2017-05-05 19:09:32 +00:00
return kernel_module_loaded(module);
}
2015-09-17 00:55:20 +02:00
}
int kernel_module_loaded(const char *module)
{
FILE *f;
int ret = -1;
char *line = NULL;
size_t len = 0;
2015-09-19 15:28:28 +02:00
f = fopen(PROCFS_PATH "/modules", "r");
if (!f)
return -1;
while (getline(&line, &len, f) >= 0) {
if (strstr(line, module) == line) {
ret = 0;
break;
}
}
free(line);
fclose(f);
return ret;
}
int kernel_get_version(struct version *v)
{
struct utsname uts;
if (uname(&uts) < 0)
return -1;
if (version_parse(uts.release, v))
return -1;
return 0;
}
2016-06-26 15:29:07 +02:00
int kernel_get_cmdline_param(const char *param, char *buf, size_t len)
{
2016-06-26 15:29:07 +02:00
int ret;
char cmdline[512];
FILE *f = fopen(PROCFS_PATH "/cmdline", "r");
if (!f)
return -1;
2016-06-26 15:29:07 +02:00
if (!fgets(cmdline, sizeof(cmdline), f))
goto out;
char *tok = strtok(cmdline, " \t");
do {
char key[128], value[128];
ret = sscanf(tok, "%127[^=]=%127s", key, value);
if (ret >= 1) {
if (ret >= 2)
debug(30, "Found kernel param: %s=%s", key, value);
else
debug(30, "Found kernel param: %s", key);
if (strcmp(param, key) == 0) {
if (ret >= 2 && buf)
2018-04-04 08:53:00 +02:00
snprintf(buf, len, "%s", value);
2016-06-26 15:29:07 +02:00
return 0; /* found */
}
}
} while((tok = strtok(NULL, " \t")));
out:
2016-06-08 22:44:44 +02:00
fclose(f);
2016-06-26 15:29:07 +02:00
return -1; /* not found or error */
}
2016-06-08 22:36:38 +02:00
int kernel_get_page_size()
{
return sysconf(_SC_PAGESIZE);
}
/* There is no sysconf interface to get the hugepage size */
int kernel_get_hugepage_size()
{
char *key, *value, *unit, *line = NULL;
int sz = -1;
size_t len = 0;
FILE *f;
f = fopen(PROCFS_PATH "/meminfo", "r");
if (!f)
return -1;
while (getline(&line, &len, f) != -1) {
key = strtok(line, ": ");
value = strtok(NULL, " ");
unit = strtok(NULL, "\n");
if (!strcmp(key, "Hugepagesize") && !strcmp(unit, "kB")) {
sz = strtoul(value, NULL, 10) * 1024;
break;
}
}
2017-04-02 13:03:31 +02:00
free(line);
fclose(f);
return sz;
}
int kernel_get_nr_hugepages()
{
FILE *f;
int nr, ret;
f = fopen(PROCFS_PATH "/sys/vm/nr_hugepages", "r");
if (!f)
serror("Failed to open %s", PROCFS_PATH "/sys/vm/nr_hugepages");
ret = fscanf(f, "%d", &nr);
if (ret != 1)
nr = -1;
fclose(f);
return nr;
}
int kernel_set_nr_hugepages(int nr)
{
FILE *f;
f = fopen(PROCFS_PATH "/sys/vm/nr_hugepages", "w");
if (!f)
serror("Failed to open %s", PROCFS_PATH "/sys/vm/nr_hugepages");
fprintf(f, "%d\n", nr);
fclose(f);
return 0;
}
2016-06-08 22:44:44 +02:00
#if 0
int kernel_has_cap(cap_value_t cap)
2016-06-08 22:44:44 +02:00
{
int ret;
cap_t caps;
cap_flag_value_t value;
2016-06-08 22:44:44 +02:00
caps = cap_get_proc();
if (caps == NULL)
return -1;
ret = cap_get_proc(caps);
if (ret == -1)
return -1;
2016-06-08 22:44:44 +02:00
ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &value);
if (ret == -1)
return -1;
ret = cap_free(caps);
2016-06-08 22:44:44 +02:00
if (ret)
return -1;
2016-06-08 22:44:44 +02:00
return value == CAP_SET ? 0 : -1;
}
2016-06-13 17:16:45 +02:00
#endif
int kernel_irq_setaffinity(unsigned irq, uintmax_t aff, uintmax_t *old)
2016-06-13 17:16:45 +02:00
{
char fn[64];
FILE *f;
int ret = 0;
2016-06-13 17:16:45 +02:00
snprintf(fn, sizeof(fn), "/proc/irq/%u/smp_affinity", irq);
2016-06-13 17:16:45 +02:00
f = fopen(fn, "w+");
if (!f)
return -1; /* IRQ does not exist */
if (old)
ret = fscanf(f, "%jx", old);
2016-06-13 17:16:45 +02:00
fprintf(f, "%jx", aff);
2016-06-13 17:16:45 +02:00
fclose(f);
return ret;
2016-06-13 17:16:45 +02:00
}
#endif /* __linux__ */