diff --git a/common/include/villas/hist.h b/common/include/villas/hist.hpp similarity index 100% rename from common/include/villas/hist.h rename to common/include/villas/hist.hpp diff --git a/common/include/villas/list.h b/common/include/villas/list.h index 175fe4932..154bf754a 100644 --- a/common/include/villas/list.h +++ b/common/include/villas/list.h @@ -121,7 +121,7 @@ int vlist_contains(struct vlist *l, void *p); void vlist_sort(struct vlist *l, cmp_cb_t cmp); /** Set single element in list */ -int vlist_set(struct vlist *l, int index, void *value); +int vlist_set(struct vlist *l, unsigned index, void *value); /** Return index in list for value. * diff --git a/common/include/villas/table.h b/common/include/villas/table.hpp similarity index 54% rename from common/include/villas/table.h rename to common/include/villas/table.hpp index e3a9a0ecf..bf594ff8b 100644 --- a/common/include/villas/table.h +++ b/common/include/villas/table.hpp @@ -27,38 +27,72 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif +#include +#include -struct table_column { - int width; /**< Width of the column. */ - char *title; /**< The title as shown in the table header. */ - char *format; /**< The format which is used to print the table rows. */ - char *unit; /**< An optional unit which will be shown in the table header. */ +class Table; - enum { - TABLE_ALIGN_LEFT, - TABLE_ALIGN_RIGHT - } align; +class TableColumn { + friend Table; + +public: + enum align { + LEFT, + RIGHT + }; + +protected: int _width; /**< The real width of this column. Calculated by table_header() */ + + int width; /**< Width of the column. */ + +public: + TableColumn(int w, enum align a, const std::string &t, const std::string &f, const std::string &u = "") : + width(w), + title(t), + format(f), + unit(u), + align(a) + { } + + std::string title; /**< The title as shown in the table header. */ + std::string format; /**< The format which is used to print the table rows. */ + std::string unit; /**< An optional unit which will be shown in the table header. */ + + enum align align; + + int getWidth() const + { + return _width; + } }; -struct table { - int ncols; +class Table { + +protected: + int resize(int w); + int width; - struct table_column *cols; + + std::vector columns; + +public: + Table(const std::vector &cols) : + width(-1), + columns(cols) + { } + + /** Print a table header consisting of \p n columns. */ + void header(); + + /** Print table rows. */ + void row(int count, ...); + + int getWidth() const + { + return width; + } }; -/** Print a table header consisting of \p n columns. */ -void table_header(struct table *t); - -/** Print table rows. */ -void table_row(struct table *t, ...); - -/** @} */ - -#ifdef __cplusplus -} -#endif +/** @} */ \ No newline at end of file diff --git a/common/lib/CMakeLists.txt b/common/lib/CMakeLists.txt index a69215d3f..76d01ffe9 100644 --- a/common/lib/CMakeLists.txt +++ b/common/lib/CMakeLists.txt @@ -21,34 +21,33 @@ ############################################################################## add_library(villas-common SHARED - advio.c - bitset.c - buffer.c + advio.cpp + bitset.cpp + buffer.cpp json_buffer.cpp - compat.c - crypt.c - hash_table.c - hist.c - kernel/kernel.c + compat.cpp + crypt.cpp + hash_table.cpp + hist.cpp + kernel/kernel.cpp kernel/kernel.cpp kernel/rt.cpp - list.c + list.cpp log.cpp log_legacy.cpp memory.cpp memory_manager.cpp plugin.cpp - table.c - task.c - timing.c - utils.c + table.cpp + task.cpp + timing.cpp utils.cpp cpuset.cpp terminal.cpp version.cpp copyright.cpp - common.c - window.c + common.cpp + window.cpp ) execute_process( @@ -58,13 +57,14 @@ execute_process( ) if(ARCH STREQUAL "x86_64") - target_sources(villas-common PRIVATE tsc.c) + target_sources(villas-common PRIVATE tsc.cpp) endif() if(CMAKE_SYSTEM_NAME STREQUAL Linux) target_sources(villas-common PRIVATE - kernel/pci.c + kernel/pci.cpp kernel/vfio.cpp +# kernel/vfio_legacy.cpp ) endif() diff --git a/common/lib/advio.c b/common/lib/advio.cpp similarity index 93% rename from common/lib/advio.c rename to common/lib/advio.cpp index 8cef11dec..6b4d2f28e 100644 --- a/common/lib/advio.c +++ b/common/lib/advio.cpp @@ -39,7 +39,7 @@ #define BAR_WIDTH 60 /**< How wide you want the progress meter to be. */ -static int advio_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp) +static int advio_trace(CURL * /* handle */, curl_infotype type, char *data, size_t size, void * /* userp */) { const char *text; @@ -83,7 +83,7 @@ static int advio_trace(CURL *handle, curl_infotype type, char *data, size_t size static char * advio_human_time(double t, char *buf, size_t len) { - int i = 0; + unsigned i = 0; const char *units[] = { "secs", "mins", "hrs", "days", "weeks", "months", "years" }; int divs[] = { 60, 60, 24, 7, 4, 12 }; @@ -99,7 +99,7 @@ static char * advio_human_time(double t, char *buf, size_t len) static char * advio_human_size(double s, char *buf, size_t len) { - int i = 0; + unsigned i = 0; const char *units[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" }; while (s > 1024 && i < ARRAY_LEN(units)) { @@ -180,14 +180,14 @@ static int advio_xferinfo(void *p, curl_off_t dl_total_bytes, curl_off_t dl_byte int aislocal(const char *uri) { - char *sep; + const char *sep; const char *supported_schemas[] = { "file", "http", "https", "tftp", "ftp", "scp", "sftp", "smb", "smbs" }; sep = strstr(uri, "://"); if (!sep) return 1; /* no schema, we assume its a local file */ - for (int i = 0; i < ARRAY_LEN(supported_schemas); i++) { + for (unsigned i = 0; i < ARRAY_LEN(supported_schemas); i++) { if (!strncmp(supported_schemas[i], uri, sep - uri)) return 0; } @@ -198,9 +198,10 @@ int aislocal(const char *uri) AFILE * afopen(const char *uri, const char *mode) { int ret; - char *sep, *cwd; + char *cwd; + const char *sep; - AFILE *af = alloc(sizeof(AFILE)); + AFILE *af = (AFILE *) alloc(sizeof(AFILE)); snprintf(af->mode, sizeof(af->mode), "%s", mode); @@ -290,29 +291,29 @@ int afclose(AFILE *af) int afseek(AFILE *af, long offset, int origin) { - long new, cur = aftell(af); + long new_seek, cur_seek = aftell(af); switch (origin) { case SEEK_SET: - new = offset; + new_seek = offset; break; case SEEK_END: fseek(af->file, 0, SEEK_END); - new = aftell(af); - fseek(af->file, cur, SEEK_SET); + new_seek = aftell(af); + fseek(af->file, cur_seek, SEEK_SET); break; case SEEK_CUR: - new = cur + offset; + new_seek = cur_seek + offset; break; default: return -1; } - if (new < af->uploaded) - af->uploaded = new; + if (new_seek < af->uploaded) + af->uploaded = new_seek; return fseek(af->file, offset, origin); } @@ -403,6 +404,7 @@ int adownload(AFILE *af, int resume) double total_bytes = 0, total_time = 0; char buf[2][32]; + char *total_bytes_human, *total_time_human; pos = aftell(af); @@ -428,8 +430,8 @@ int adownload(AFILE *af, int resume) curl_easy_getinfo(af->curl, CURLINFO_SIZE_DOWNLOAD, &total_bytes); curl_easy_getinfo(af->curl, CURLINFO_TOTAL_TIME, &total_time); - char *total_bytes_human = advio_human_size(total_bytes, buf[0], sizeof(buf[0])); - char *total_time_human = advio_human_time(total_time, buf[1], sizeof(buf[1])); + total_bytes_human = advio_human_size(total_bytes, buf[0], sizeof(buf[0])); + total_time_human = advio_human_time(total_time, buf[1], sizeof(buf[1])); info("Finished download of %s in %s", total_bytes_human, total_time_human); @@ -460,6 +462,7 @@ int adownload(AFILE *af, int resume) af->file = fopen(af->uri, af->mode); if (!af->file) return -1; + break; default: error("Failed to download file: %s: %s", af->uri, curl_easy_strerror(res)); diff --git a/common/lib/bitset.c b/common/lib/bitset.cpp similarity index 97% rename from common/lib/bitset.c rename to common/lib/bitset.cpp index 532a0683e..54cc72efa 100644 --- a/common/lib/bitset.c +++ b/common/lib/bitset.cpp @@ -34,7 +34,7 @@ int bitset_init(struct bitset *b, size_t dim) { int s = bitset_nslots(dim); - b->set = alloc(s * CHAR_BIT); + b->set = (char *) alloc(s * CHAR_BIT); b->dimension = dim; return 0; @@ -163,7 +163,7 @@ char * bitset_dump(struct bitset *b) { char *str = NULL; - for (int i = 0; i < b->dimension; i++) + for (unsigned i = 0; i < b->dimension; i++) strcatf(&str, "%d", bitset_test(b, i)); return str; diff --git a/common/lib/buffer.c b/common/lib/buffer.cpp similarity index 93% rename from common/lib/buffer.c rename to common/lib/buffer.cpp index 8e8d698fb..075476dff 100644 --- a/common/lib/buffer.c +++ b/common/lib/buffer.cpp @@ -30,7 +30,7 @@ int buffer_init(struct buffer *b, size_t size) { b->len = 0; b->size = size; - b->buf = malloc(size); + b->buf = (char *) malloc(size); if (!b->buf) return -1; @@ -58,7 +58,7 @@ int buffer_append(struct buffer *b, const char *data, size_t len) { if (b->len + len > b->size) { b->size = b->len + len; - b->buf = realloc(b->buf, b->size); + b->buf = (char *) realloc(b->buf, b->size); if (!b->buf) return -1; } @@ -85,7 +85,7 @@ int buffer_append_json(struct buffer *b, json_t *j) retry: len = json_dumpb(j, b->buf + b->len, b->size - b->len, 0); if (b->size < b->len + len) { - b->buf = realloc(b->buf, b->len + len); + b->buf = (char *) realloc(b->buf, b->len + len); if (!b->buf) return -1; diff --git a/common/lib/common.c b/common/lib/common.cpp similarity index 100% rename from common/lib/common.c rename to common/lib/common.cpp diff --git a/common/lib/compat.c b/common/lib/compat.cpp similarity index 100% rename from common/lib/compat.c rename to common/lib/compat.cpp diff --git a/common/lib/crypt.c b/common/lib/crypt.cpp similarity index 100% rename from common/lib/crypt.c rename to common/lib/crypt.cpp diff --git a/common/lib/hash_table.c b/common/lib/hash_table.cpp similarity index 94% rename from common/lib/hash_table.c rename to common/lib/hash_table.cpp index 62780e200..11cdcd29b 100644 --- a/common/lib/hash_table.c +++ b/common/lib/hash_table.cpp @@ -43,7 +43,7 @@ int hash_table_init(struct hash_table *ht, size_t size) if (ret) return ret; - ht->table = alloc(len); + ht->table = (struct hash_table_entry **) alloc(len); memset(ht->table, 0, len); @@ -62,7 +62,7 @@ int hash_table_destroy(struct hash_table *ht, dtor_cb_t dtor, bool release) pthread_mutex_lock(&ht->lock); - for (int i = 0; i < ht->size; i++) { + for (unsigned i = 0; i < ht->size; i++) { for (cur = ht->table[i]; cur; cur = next) { if (dtor) dtor(cur->data); @@ -106,7 +106,7 @@ int hash_table_insert(struct hash_table *ht, const void *key, void *data) if (cur) ret = -1; else { - hte = alloc(sizeof(struct hash_table_entry)); + hte = (struct hash_table_entry *) alloc(sizeof(struct hash_table_entry)); if (hte) { hte->key = key; hte->data = data; @@ -191,7 +191,7 @@ void hash_table_dump(struct hash_table *ht) pthread_mutex_lock(&ht->lock); - for (int i = 0; i < ht->size; i++) { + for (unsigned i = 0; i < ht->size; i++) { char *strlst = NULL; for (hte = ht->table[i]; hte; hte = hte->next) diff --git a/common/lib/hist.c b/common/lib/hist.cpp similarity index 90% rename from common/lib/hist.c rename to common/lib/hist.cpp index e8d167c97..058126576 100644 --- a/common/lib/hist.c +++ b/common/lib/hist.cpp @@ -28,9 +28,9 @@ #include #include -#include +#include #include -#include +#include #define VAL(h, i) ((h)->low + (i) * (h)->resolution) #define INDEX(h, v) round((v - (h)->low) / (h)->resolution) @@ -40,7 +40,7 @@ int hist_init(struct hist *h, int buckets, hist_cnt_t warmup) h->length = buckets; h->warmup = warmup; - h->data = buckets ? alloc(h->length * sizeof(hist_cnt_t)) : NULL; + h->data = (hist_cnt_t *) (buckets ? alloc(h->length * sizeof(hist_cnt_t)) : nullptr); hist_reset(h); @@ -51,7 +51,7 @@ int hist_destroy(struct hist *h) { if (h->data) { free(h->data); - h->data = NULL; + h->data = nullptr; } return 0; @@ -83,7 +83,7 @@ void hist_put(struct hist *h, double value) h->higher++; else if (idx < 0) h->lower++; - else if (h->data != NULL) + else if (h->data != nullptr) h->data[idx]++; } @@ -169,30 +169,27 @@ void hist_plot(const struct hist *h) max = h->data[i]; } - struct table_column cols[] = { - { -9, "Value", "%+9.3g", NULL, TABLE_ALIGN_RIGHT }, - { -6, "Count", "%6ju", NULL, TABLE_ALIGN_RIGHT }, - { 0, "Plot", "%s", "occurences", TABLE_ALIGN_LEFT } + std::vector cols = { + { -9, TableColumn::align::RIGHT, "Value", "%+9.3g" }, + { -6, TableColumn::align::RIGHT, "Count", "%6ju" }, + { 0, TableColumn::align::LEFT, "Plot", "%s", "occurences" } }; - struct table table = { - .ncols = ARRAY_LEN(cols), - .cols = cols - }; + Table table = Table(cols); /* Print plot */ - table_header(&table); + table.header(); for (int i = 0; i < h->length; i++) { double value = VAL(h, i); hist_cnt_t cnt = h->data[i]; - int bar = cols[2]._width * ((double) cnt / max); + int bar = cols[2].getWidth() * ((double) cnt / max); char *buf = strf("%s", ""); for (int i = 0; i < bar; i++) buf = strcatf(&buf, "\u2588"); - table_row(&table, value, cnt, buf); + table.row(value, cnt, buf); free(buf); } @@ -200,7 +197,7 @@ void hist_plot(const struct hist *h) char * hist_dump(const struct hist *h) { - char *buf = alloc(128); + char *buf = (char *) alloc(128); strcatf(&buf, "[ "); diff --git a/common/lib/kernel/kernel.c b/common/lib/kernel/kernel.c deleted file mode 100644 index 2faf6dd41..000000000 --- a/common/lib/kernel/kernel.c +++ /dev/null @@ -1,326 +0,0 @@ -/** Linux kernel related functions. - * - * @author Steffen Vogel - * @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLAScommon - * - * 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. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -int kernel_get_cacheline_size() -{ -#if defined(__linux__) && defined(__x86_64__) - return sysconf(_SC_LEVEL1_ICACHE_LINESIZE); -#elif defined(__MACH__) - /* Open the command for reading. */ - FILE *fp = popen("sysctl -n machdep.cpu.cache.linesize", "r"); - if (fp == NULL) - return -1; - - int ret, size; - - ret = fscanf(fp, "%d", &size); - - pclose(fp); - - return ret == 1 ? size : -1; -#else - return CACHELINE_SIZE; -#endif -} - -#if defined(__linux__) || defined(__APPLE__) -int kernel_get_page_size() -{ - return sysconf(_SC_PAGESIZE); -} -#else - #error "Unsupported platform" -#endif - -/* There is no sysconf interface to get the hugepage size */ -int kernel_get_hugepage_size() -{ -#ifdef __linux__ - char *key, *value, *unit, *line = NULL, *lasts; - 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_r(line, ": ", &lasts); - value = strtok_r(NULL, " ", &lasts); - unit = strtok_r(NULL, "\n", &lasts); - - if (!strcmp(key, "Hugepagesize") && !strcmp(unit, "kB")) { - sz = strtoul(value, NULL, 10) * 1024; - break; - } - } - - free(line); - fclose(f); - - return sz; -#elif defined(__x86_64__) - return 1 << 21; -#elif defined(__i386__) - return 1 << 22; -#else - #error "Unsupported architecture" -#endif -} - -#ifdef __linux__ - -int kernel_module_set_param(const char *module, const char *param, const char *value) -{ - FILE *f; - char fn[256]; - - snprintf(fn, sizeof(fn), "%s/module/%s/parameters/%s", SYSFS_PATH, module, param); - f = fopen(fn, "w"); - if (!f) - serror("Failed set parameter %s for kernel module %s to %s", module, param, value); - - debug(LOG_KERNEL | 5, "Set parameter %s of kernel module %s to %s", module, param, value); - fprintf(f, "%s", value); - fclose(f); - - return 0; -} - -int kernel_module_load(const char *module) -{ - int ret; - - ret = kernel_module_loaded(module); - if (!ret) { - debug(LOG_KERNEL | 5, "Kernel module %s already loaded...", module); - return 0; - } - - pid_t pid = fork(); - switch (pid) { - case -1: /* error */ - return -1; - - case 0: /* child */ - execlp("modprobe", "modprobe", module, (char *) 0); - exit(EXIT_FAILURE); /* exec never returns */ - - default: - wait(&ret); - - return kernel_module_loaded(module); - } -} - -int kernel_module_loaded(const char *module) -{ - FILE *f; - int ret = -1; - char *line = NULL; - size_t len = 0; - - 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_cmdline_param(const char *param, char *buf, size_t len) -{ - int ret; - char cmdline[512], *lasts; - - FILE *f = fopen(PROCFS_PATH "/cmdline", "r"); - if (!f) - return -1; - - if (!fgets(cmdline, sizeof(cmdline), f)) - goto out; - - char *tok = strtok_r(cmdline, " \t", &lasts); - 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) - snprintf(buf, len, "%s", value); - - return 0; /* found */ - } - } - } while ((tok = strtok_r(NULL, " \t", &lasts))); - -out: - fclose(f); - - return -1; /* not found or error */ -} - -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; -} - -int kernel_irq_setaffinity(unsigned irq, uintmax_t aff, uintmax_t *old) -{ - char fn[64]; - FILE *f; - int ret = 0; - - snprintf(fn, sizeof(fn), "/proc/irq/%u/smp_affinity", irq); - - f = fopen(fn, "w+"); - if (!f) - return -1; /* IRQ does not exist */ - - if (old) - ret = fscanf(f, "%jx", old); - - fprintf(f, "%jx", aff); - fclose(f); - - return ret; -} - -int kernel_get_cpu_frequency(uint64_t *freq) -{ - char *line = NULL, *sep, *end; - size_t len = 0; - double dfreq; - int ret; - FILE *f; - - /* Try to get CPU frequency from cpufreq module */ - f = fopen(SYSFS_PATH "/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r"); - if (!f) - goto cpuinfo; - - ret = fscanf(f, "%" PRIu64, freq); - fclose(f); - if (ret != 1) - return -1; - - /* cpufreq reports kHz */ - *freq = *freq * 1000; - - return 0; - -cpuinfo: - /* Try to read CPU frequency from /proc/cpuinfo */ - f = fopen(PROCFS_PATH "/cpuinfo", "r"); - if (!f) - return -1; /* We give up here */ - - ret = -1; - while (getline(&line, &len, f) >= 0) { - if (strstr(line, "cpu MHz") == line) { - ret = 0; - break; - } - } - if (ret) - goto out; - - sep = strchr(line, ':'); - if (!sep) { - ret = -1; - goto out; - } - - dfreq = strtod(sep+1, &end); - - if (end == sep+1) { - ret = -1; - goto out; - } - - /* Frequency is given in MHz */ - *freq = dfreq * 1e6; - -out: fclose(f); - free(line); - - return ret; -} -#endif /* __linux__ */ diff --git a/common/lib/kernel/kernel.cpp b/common/lib/kernel/kernel.cpp index 88d5e7285..c81324b2a 100644 --- a/common/lib/kernel/kernel.cpp +++ b/common/lib/kernel/kernel.cpp @@ -21,6 +21,20 @@ *********************************************************************************/ #include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include #include #include @@ -42,3 +56,291 @@ Version villas::kernel::getVersion() return Version(ver); } + +int kernel_get_cacheline_size() +{ +#if defined(__linux__) && defined(__x86_64__) + return sysconf(_SC_LEVEL1_ICACHE_LINESIZE); +#elif defined(__MACH__) + /* Open the command for reading. */ + FILE *fp = popen("sysctl -n machdep.cpu.cache.linesize", "r"); + if (fp == NULL) + return -1; + + int ret, size; + + ret = fscanf(fp, "%d", &size); + + pclose(fp); + + return ret == 1 ? size : -1; +#else + return CACHELINE_SIZE; +#endif +} + +#if defined(__linux__) || defined(__APPLE__) +int kernel_get_page_size() +{ + return sysconf(_SC_PAGESIZE); +} +#else + #error "Unsupported platform" +#endif + +/* There is no sysconf interface to get the hugepage size */ +int kernel_get_hugepage_size() +{ +#ifdef __linux__ + char *key, *value, *unit, *line = NULL, *lasts; + 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_r(line, ": ", &lasts); + value = strtok_r(NULL, " ", &lasts); + unit = strtok_r(NULL, "\n", &lasts); + + if (!strcmp(key, "Hugepagesize") && !strcmp(unit, "kB")) { + sz = strtoul(value, NULL, 10) * 1024; + break; + } + } + + free(line); + fclose(f); + + return sz; +#elif defined(__x86_64__) + return 1 << 21; +#elif defined(__i386__) + return 1 << 22; +#else + #error "Unsupported architecture" +#endif +} + +#ifdef __linux__ + +int kernel_module_set_param(const char *module, const char *param, const char *value) +{ + FILE *f; + char fn[256]; + + snprintf(fn, sizeof(fn), "%s/module/%s/parameters/%s", SYSFS_PATH, module, param); + f = fopen(fn, "w"); + if (!f) + serror("Failed set parameter %s for kernel module %s to %s", module, param, value); + + debug(LOG_KERNEL | 5, "Set parameter %s of kernel module %s to %s", module, param, value); + fprintf(f, "%s", value); + fclose(f); + + return 0; +} + +int kernel_module_load(const char *module) +{ + int ret; + + ret = kernel_module_loaded(module); + if (!ret) { + debug(LOG_KERNEL | 5, "Kernel module %s already loaded...", module); + return 0; + } + + pid_t pid = fork(); + switch (pid) { + case -1: /* error */ + return -1; + + case 0: /* child */ + execlp("modprobe", "modprobe", module, (char *) 0); + exit(EXIT_FAILURE); /* exec never returns */ + + default: + wait(&ret); + + return kernel_module_loaded(module); + } +} + +int kernel_module_loaded(const char *module) +{ + FILE *f; + int ret = -1; + char *line = NULL; + size_t len = 0; + + 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_cmdline_param(const char *param, char *buf, size_t len) +{ + int ret; + char cmdline[512], key[128], value[128], *lasts, *tok; + + FILE *f = fopen(PROCFS_PATH "/cmdline", "r"); + if (!f) + return -1; + + if (!fgets(cmdline, sizeof(cmdline), f)) + goto out; + + tok = strtok_r(cmdline, " \t", &lasts); + do { + 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) + snprintf(buf, len, "%s", value); + + return 0; /* found */ + } + } + } while ((tok = strtok_r(NULL, " \t", &lasts))); + +out: + fclose(f); + + return -1; /* not found or error */ +} + +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; +} + +int kernel_irq_setaffinity(unsigned irq, uintmax_t aff, uintmax_t *old) +{ + char fn[64]; + FILE *f; + int ret = 0; + + snprintf(fn, sizeof(fn), "/proc/irq/%u/smp_affinity", irq); + + f = fopen(fn, "w+"); + if (!f) + return -1; /* IRQ does not exist */ + + if (old) + ret = fscanf(f, "%jx", old); + + fprintf(f, "%jx", aff); + fclose(f); + + return ret; +} + +int kernel_get_cpu_frequency(uint64_t *freq) +{ + char *line = NULL, *sep, *end; + size_t len = 0; + double dfreq; + int ret; + FILE *f; + + /* Try to get CPU frequency from cpufreq module */ + f = fopen(SYSFS_PATH "/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r"); + if (!f) + goto cpuinfo; + + ret = fscanf(f, "%" PRIu64, freq); + fclose(f); + if (ret != 1) + return -1; + + /* cpufreq reports kHz */ + *freq = *freq * 1000; + + return 0; + +cpuinfo: + /* Try to read CPU frequency from /proc/cpuinfo */ + f = fopen(PROCFS_PATH "/cpuinfo", "r"); + if (!f) + return -1; /* We give up here */ + + ret = -1; + while (getline(&line, &len, f) >= 0) { + if (strstr(line, "cpu MHz") == line) { + ret = 0; + break; + } + } + if (ret) + goto out; + + sep = strchr(line, ':'); + if (!sep) { + ret = -1; + goto out; + } + + dfreq = strtod(sep+1, &end); + + if (end == sep+1) { + ret = -1; + goto out; + } + + /* Frequency is given in MHz */ + *freq = dfreq * 1e6; + +out: fclose(f); + free(line); + + return ret; +} +#endif /* __linux__ */ diff --git a/common/lib/kernel/pci.c b/common/lib/kernel/pci.cpp similarity index 94% rename from common/lib/kernel/pci.c rename to common/lib/kernel/pci.cpp index 584bec248..21a75e1a9 100644 --- a/common/lib/kernel/pci.c +++ b/common/lib/kernel/pci.cpp @@ -175,19 +175,20 @@ fail: int pci_device_parse_id(struct pci_device *f, const char *str, const char **error) { char *s, *c, *e; + char *tmp = strdup(str); - if (!*str) + if (!*tmp) return 0; - s = strchr(str, ':'); + s = strchr(tmp, ':'); if (!s) { *error = "':' expected"; goto fail; } *s++ = 0; - if (str[0] && strcmp(str, "*")) { - long int x = strtol(str, &e, 16); + if (tmp[0] && strcmp(tmp, "*")) { + long int x = strtol(tmp, &e, 16); if ((e && *e) || (x < 0 || x > 0xffff)) { *error = "Invalid vendor ID"; @@ -225,6 +226,7 @@ int pci_device_parse_id(struct pci_device *f, const char *str, const char **erro return 0; fail: + free(tmp); return -1; } @@ -248,7 +250,7 @@ int pci_device_compare(const struct pci_device *d, const struct pci_device *f) struct pci_device * pci_lookup_device(struct pci *p, struct pci_device *f) { - return vlist_search(&p->devices, (cmp_cb_t) pci_device_compare, (void *) f); + return (struct pci_device *) vlist_search(&p->devices, (cmp_cb_t) pci_device_compare, (void *) f); } size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions) @@ -276,10 +278,10 @@ size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions) int region = 0; /* Cap to 8 regions, just because we don't know how many may exist. */ - while(region < 8 && (bytesRead = getline(&line, &len, f)) != -1) { + while (region < 8 && (bytesRead = getline(&line, &len, f)) != -1) { unsigned long long tokens[3]; char* s = line; - for(int i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { char* end; tokens[i] = strtoull(s, &end, 16); if(s == end) { @@ -296,7 +298,7 @@ size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions) line = NULL; len = 0; - if(tokens[0] != tokens[1]) { + if (tokens[0] != tokens[1]) { /* This is a valid region */ cur_region->num = region; cur_region->start = tokens[0]; @@ -309,9 +311,9 @@ size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions) region++; } - if(valid_regions > 0) { + if (valid_regions > 0) { const size_t len = valid_regions * sizeof (struct pci_region); - *regions = malloc(len); + *regions = (struct pci_region *) malloc(len); memcpy(*regions, _regions, len); } diff --git a/common/lib/kernel/vfio.c b/common/lib/kernel/vfio_legacy.cpp similarity index 100% rename from common/lib/kernel/vfio.c rename to common/lib/kernel/vfio_legacy.cpp diff --git a/common/lib/list.c b/common/lib/list.cpp similarity index 94% rename from common/lib/list.c rename to common/lib/list.cpp index a905a3cd1..02f2d21dc 100644 --- a/common/lib/list.c +++ b/common/lib/list.cpp @@ -30,11 +30,13 @@ /* Compare functions */ static int cmp_lookup(const void *a, const void *b) { - const struct { + struct name_tag { char *name; - } *obj = a; + }; - return strcmp(obj->name, b); + const name_tag *obj = (struct name_tag *) a; + + return strcmp(obj->name, (char *) b); } static int cmp_contains(const void *a, const void *b) { @@ -102,7 +104,7 @@ void vlist_push(struct vlist *l, void *p) /* Resize array if out of capacity */ if (l->length >= l->capacity) { l->capacity += LIST_CHUNKSIZE; - l->array = realloc(l->array, l->capacity * sizeof(void *)); + l->array = (void **) realloc(l->array, l->capacity * sizeof(void *)); } l->array[l->length] = p; @@ -145,7 +147,7 @@ int vlist_insert(struct vlist *l, size_t idx, void *p) /* Resize array if out of capacity */ if (l->length + 1 > l->capacity) { l->capacity += LIST_CHUNKSIZE; - l->array = realloc(l->array, l->capacity * sizeof(void *)); + l->array = (void **) realloc(l->array, l->capacity * sizeof(void *)); } o = p; @@ -258,7 +260,7 @@ void vlist_sort(struct vlist *l, cmp_cb_t cmp) pthread_mutex_unlock(&l->lock); } -int vlist_set(struct vlist *l, int index, void *value) +int vlist_set(struct vlist *l, unsigned index, void *value) { if (index >= l->length) return -1; diff --git a/common/lib/log.cpp b/common/lib/log.cpp index 35c7783fc..4b8a3de6c 100644 --- a/common/lib/log.cpp +++ b/common/lib/log.cpp @@ -81,9 +81,9 @@ Logger Log::get(const std::string &name) void Log::parse(json_t *cfg) { - const char *level = NULL; - const char *path = NULL; - const char *pattern = NULL; + const char *level = nullptr; + const char *path = nullptr; + const char *pattern = nullptr; int syslog; int ret; diff --git a/common/lib/table.c b/common/lib/table.cpp similarity index 55% rename from common/lib/table.c rename to common/lib/table.cpp index 08c3f04fc..73df285c2 100644 --- a/common/lib/table.c +++ b/common/lib/table.cpp @@ -24,62 +24,62 @@ #include #include -#include +#include #include -static int table_resize(struct table *t, int width) +int Table::resize(int w) { int norm, flex, fixed, total; - t->width = width; + width = w; norm = 0; flex = 0; fixed = 0; - total = t->width - t->ncols * 2; + total = width - columns.size() * 2; /* Normalize width */ - for (int i = 0; i < t->ncols; i++) { - if (t->cols[i].width > 0) - norm += t->cols[i].width; - if (t->cols[i].width == 0) + for (unsigned i = 0; i < columns.size(); i++) { + if (columns[i].width > 0) + norm += columns[i].width; + if (columns[i].width == 0) flex++; - if (t->cols[i].width < 0) - fixed += -1 * t->cols[i].width; + if (columns[i].width < 0) + fixed += -1 * columns[i].width; } - for (int i = 0; i < t->ncols; i++) { - if (t->cols[i].width > 0) - t->cols[i]._width = t->cols[i].width * (float) (total - fixed) / norm; - if (t->cols[i].width == 0) - t->cols[i]._width = (float) (total - fixed) / flex; - if (t->cols[i].width < 0) - t->cols[i]._width = -1 * t->cols[i].width; + for (unsigned i = 0; i < columns.size(); i++) { + if (columns[i].width > 0) + columns[i]._width = columns[i].width * (float) (total - fixed) / norm; + if (columns[i].width == 0) + columns[i]._width = (float) (total - fixed) / flex; + if (columns[i].width < 0) + columns[i]._width = -1 * columns[i].width; } return 0; } -void table_header(struct table *t) +void Table::header() { - if (t->width != log_get_width()) - table_resize(t, log_get_width()); + if (width != log_get_width()) + resize(log_get_width()); - char *line1 = NULL; - char *line2 = NULL; - char *line3 = NULL; + char *line1 = nullptr; + char *line2 = nullptr; + char *line3 = nullptr; - for (int i = 0; i < t->ncols; i++) { + for (unsigned i = 0; i < columns.size(); i++) { int w, u; char *col, *unit; - col = strf(CLR_BLD("%s"), t->cols[i].title); - unit = t->cols[i].unit ? strf(CLR_YEL("%s"), t->cols[i].unit) : ""; + col = strf(CLR_BLD("%s"), columns[i].title.c_str()); + unit = columns[i].unit.size() ? strf(CLR_YEL("%s"), columns[i].unit.c_str()) : strf(""); - w = t->cols[i]._width + strlen(col) - strlenp(col); - u = t->cols[i]._width + strlen(unit) - strlenp(unit); + w = columns[i]._width + strlen(col) - strlenp(col); + u = columns[i]._width + strlen(unit) - strlenp(unit); - if (t->cols[i].align == TABLE_ALIGN_LEFT) { + if (columns[i].align == TableColumn::align::LEFT) { strcatf(&line1, " %-*.*s\e[0m", w, w, col); strcatf(&line2, " %-*.*s\e[0m", u, u, unit); } @@ -88,11 +88,11 @@ void table_header(struct table *t) strcatf(&line2, " %*.*s\e[0m", u, u, unit); } - for (int j = 0; j < t->cols[i]._width + 2; j++) { + for (int j = 0; j < columns[i]._width + 2; j++) { strcatf(&line3, "%s", BOX_LR); } - if (i != t->ncols - 1) { + if (i != columns.size() - 1) { strcatf(&line1, " %s", BOX_UD); strcatf(&line2, " %s", BOX_UD); strcatf(&line3, "%s", BOX_UDLR); @@ -110,31 +110,31 @@ void table_header(struct table *t) free(line3); } -void table_row(struct table *t, ...) +void Table::row(int count, ...) { - if (t->width != log_get_width()) { - table_resize(t, log_get_width()); - table_header(t); + if (width != log_get_width()) { + resize(log_get_width()); + header(); } va_list args; - va_start(args, t); + va_start(args, count); - char *line = NULL; + char *line = nullptr; - for (int i = 0; i < t->ncols; ++i) { - char *col = vstrf(t->cols[i].format, args); + for (unsigned i = 0; i < columns.size(); ++i) { + char *col = vstrf(columns[i].format.c_str(), args); int l = strlenp(col); int r = strlen(col); - int w = t->cols[i]._width + r - l; + int w = columns[i]._width + r - l; - if (t->cols[i].align == TABLE_ALIGN_LEFT) + if (columns[i].align == TableColumn::align::LEFT) strcatf(&line, " %-*.*s\e[0m ", w, w, col); else strcatf(&line, " %*.*s\e[0m ", w, w, col); - if (i != t->ncols - 1) + if (i != columns.size() - 1) strcatf(&line, BOX_UD); free(col); diff --git a/common/lib/task.c b/common/lib/task.cpp similarity index 100% rename from common/lib/task.c rename to common/lib/task.cpp diff --git a/common/lib/terminal.cpp b/common/lib/terminal.cpp index 3614e28f9..502cff113 100644 --- a/common/lib/terminal.cpp +++ b/common/lib/terminal.cpp @@ -46,7 +46,7 @@ Terminal::Terminal() sigemptyset(&sa_resize.sa_mask); - ret = sigaction(SIGWINCH, &sa_resize, NULL); + ret = sigaction(SIGWINCH, &sa_resize, nullptr); if (ret) throw SystemError("Failed to register signal handler"); diff --git a/common/lib/timing.c b/common/lib/timing.cpp similarity index 100% rename from common/lib/timing.c rename to common/lib/timing.cpp diff --git a/common/lib/tsc.c b/common/lib/tsc.cpp similarity index 100% rename from common/lib/tsc.c rename to common/lib/tsc.cpp diff --git a/common/lib/utils.c b/common/lib/utils.c index 2bf46b4c2..4e153bc07 100644 --- a/common/lib/utils.c +++ b/common/lib/utils.c @@ -20,166 +20,3 @@ * along with this program. If not, see . *********************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -double box_muller(float m, float s) -{ - double x1, x2, y1; - static double y2; - static int use_last = 0; - - if (use_last) { /* use value from previous call */ - y1 = y2; - use_last = 0; - } - else { - double w; - do { - x1 = 2.0 * randf() - 1.0; - x2 = 2.0 * randf() - 1.0; - w = x1*x1 + x2*x2; - } while (w >= 1.0); - - w = sqrt(-2.0 * log(w) / w); - y1 = x1 * w; - y2 = x2 * w; - use_last = 1; - } - - return m + y1 * s; -} - -double randf() -{ - return (double) random() / RAND_MAX; -} - -char * strcatf(char **dest, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vstrcatf(dest, fmt, ap); - va_end(ap); - - return *dest; -} - -char * vstrcatf(char **dest, const char *fmt, va_list ap) -{ - char *tmp; - int n = *dest ? strlen(*dest) : 0; - int i = vasprintf(&tmp, fmt, ap); - - *dest = (char *)(realloc(*dest, n + i + 1)); - if (*dest != NULL) - strncpy(*dest+n, tmp, i + 1); - - free(tmp); - - return *dest; -} - -char * strf(const char *fmt, ...) -{ - char *buf = NULL; - - va_list ap; - va_start(ap, fmt); - vstrcatf(&buf, fmt, ap); - va_end(ap); - - return buf; -} - -char * vstrf(const char *fmt, va_list va) -{ - char *buf = NULL; - - vstrcatf(&buf, fmt, va); - - return buf; -} - -void * alloc(size_t bytes) -{ - void *p = malloc(bytes); - if (!p) - error("Failed to allocate memory"); - - memset(p, 0, bytes); - - return p; -} - -void * memdup(const void *src, size_t bytes) -{ - void *dst = alloc(bytes); - - memcpy(dst, src, bytes); - - return dst; -} - -pid_t spawn(const char* name, char *const argv[]) -{ - pid_t pid; - - pid = fork(); - switch (pid) { - case -1: return -1; - case 0: return execvp(name, (char * const*) argv); - } - - return pid; -} - -size_t strlenp(const char *str) -{ - size_t sz = 0; - - for (const char *d = str; *d; d++) { - const unsigned char *c = (const unsigned char *) d; - - if (isprint(*c)) - sz++; - else if (c[0] == '\b') - sz--; - else if (c[0] == '\t') - sz += 4; /* tab width == 4 */ - /* CSI sequence */ - else if (c[0] == '\e' && c[1] == '[') { - c += 2; - while (*c && *c != 'm') - c++; - } - /* UTF-8 */ - else if (c[0] >= 0xc2 && c[0] <= 0xdf) { - sz++; - c += 1; - } - else if (c[0] >= 0xe0 && c[0] <= 0xef) { - sz++; - c += 2; - } - else if (c[0] >= 0xf0 && c[0] <= 0xf4) { - sz++; - c += 3; - } - - d = (const char *) c; - } - - return sz; -} diff --git a/common/lib/utils.cpp b/common/lib/utils.cpp index c41fa9a7a..d4e6b0050 100644 --- a/common/lib/utils.cpp +++ b/common/lib/utils.cpp @@ -24,9 +24,19 @@ #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include #include #include @@ -107,19 +117,19 @@ int signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx)) sigemptyset(&sa_quit.sa_mask); sigemptyset(&sa_chld.sa_mask); - ret = sigaction(SIGINT, &sa_quit, NULL); + ret = sigaction(SIGINT, &sa_quit, nullptr); if (ret) return ret; - ret = sigaction(SIGTERM, &sa_quit, NULL); + ret = sigaction(SIGTERM, &sa_quit, nullptr); if (ret) return ret; - ret = sigaction(SIGALRM, &sa_quit, NULL); + ret = sigaction(SIGALRM, &sa_quit, nullptr); if (ret) return ret; - ret = sigaction(SIGCHLD, &sa_chld, NULL); + ret = sigaction(SIGCHLD, &sa_chld, nullptr); if (ret) return ret; @@ -174,3 +184,153 @@ void killme(int sig) } /* namespace utils */ } /* namespace villas */ + +double box_muller(float m, float s) +{ + double x1, x2, y1; + static double y2; + static int use_last = 0; + + if (use_last) { /* use value from previous call */ + y1 = y2; + use_last = 0; + } + else { + double w; + do { + x1 = 2.0 * randf() - 1.0; + x2 = 2.0 * randf() - 1.0; + w = x1*x1 + x2*x2; + } while (w >= 1.0); + + w = sqrt(-2.0 * log(w) / w); + y1 = x1 * w; + y2 = x2 * w; + use_last = 1; + } + + return m + y1 * s; +} + +double randf() +{ + return (double) random() / RAND_MAX; +} + +char * strcatf(char **dest, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vstrcatf(dest, fmt, ap); + va_end(ap); + + return *dest; +} + +char * vstrcatf(char **dest, const char *fmt, va_list ap) +{ + char *tmp; + int n = *dest ? strlen(*dest) : 0; + int i = vasprintf(&tmp, fmt, ap); + + *dest = (char *)(realloc(*dest, n + i + 1)); + if (*dest != NULL) + strncpy(*dest+n, tmp, i + 1); + + free(tmp); + + return *dest; +} + +char * strf(const char *fmt, ...) +{ + char *buf = NULL; + + va_list ap; + va_start(ap, fmt); + vstrcatf(&buf, fmt, ap); + va_end(ap); + + return buf; +} + +char * vstrf(const char *fmt, va_list va) +{ + char *buf = NULL; + + vstrcatf(&buf, fmt, va); + + return buf; +} + +void * alloc(size_t bytes) +{ + void *p = malloc(bytes); + if (!p) + error("Failed to allocate memory"); + + memset(p, 0, bytes); + + return p; +} + +void * memdup(const void *src, size_t bytes) +{ + void *dst = alloc(bytes); + + memcpy(dst, src, bytes); + + return dst; +} + +pid_t spawn(const char* name, char *const argv[]) +{ + pid_t pid; + + pid = fork(); + switch (pid) { + case -1: return -1; + case 0: return execvp(name, (char * const*) argv); + } + + return pid; +} + +size_t strlenp(const char *str) +{ + size_t sz = 0; + + for (const char *d = str; *d; d++) { + const unsigned char *c = (const unsigned char *) d; + + if (isprint(*c)) + sz++; + else if (c[0] == '\b') + sz--; + else if (c[0] == '\t') + sz += 4; /* tab width == 4 */ + /* CSI sequence */ + else if (c[0] == '\e' && c[1] == '[') { + c += 2; + while (*c && *c != 'm') + c++; + } + /* UTF-8 */ + else if (c[0] >= 0xc2 && c[0] <= 0xdf) { + sz++; + c += 1; + } + else if (c[0] >= 0xe0 && c[0] <= 0xef) { + sz++; + c += 2; + } + else if (c[0] >= 0xf0 && c[0] <= 0xf4) { + sz++; + c += 3; + } + + d = (const char *) c; + } + + return sz; +} diff --git a/common/lib/window.c b/common/lib/window.cpp similarity index 96% rename from common/lib/window.c rename to common/lib/window.cpp index 295f050c4..a9cae8120 100644 --- a/common/lib/window.c +++ b/common/lib/window.cpp @@ -30,7 +30,7 @@ int window_init(struct window *w, size_t steps, double init) size_t len = LOG2_CEIL(steps); /* Allocate memory for ciruclar history buffer */ - w->data = alloc(len * sizeof(double)); + w->data = (double *) alloc(len * sizeof(double)); if (!w->data) return -1; diff --git a/common/tests/unit/hist.cpp b/common/tests/unit/hist.cpp index 7dc6d5272..89dc17ccc 100644 --- a/common/tests/unit/hist.cpp +++ b/common/tests/unit/hist.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include const double test_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};