diff --git a/common/include/villas/advio.h b/common/include/villas/advio.hpp similarity index 98% rename from common/include/villas/advio.h rename to common/include/villas/advio.hpp index 9ab01ef53..1e0dbcea4 100644 --- a/common/include/villas/advio.h +++ b/common/include/villas/advio.hpp @@ -27,6 +27,7 @@ #include #include +#include struct advio { CURL *curl; diff --git a/common/include/villas/buffer.h b/common/include/villas/buffer.hpp similarity index 75% rename from common/include/villas/buffer.h rename to common/include/villas/buffer.hpp index 69f03131e..ff7b1e4c6 100644 --- a/common/include/villas/buffer.h +++ b/common/include/villas/buffer.hpp @@ -27,24 +27,28 @@ #include -#include +#include -struct buffer { - enum State state; +namespace villas { +class Buffer { + +public: char *buf; size_t len; size_t size; + + Buffer(size_t size); + + ~Buffer(); + + void clear(); + + int append(const char *data, size_t len); + + int parseJson(json_t **j); + + int appendJson(json_t *j); }; -int buffer_init(struct buffer *b, size_t size); - -int buffer_destroy(struct buffer *b); - -void buffer_clear(struct buffer *b); - -int buffer_append(struct buffer *b, const char *data, size_t len); - -int buffer_parse_json(struct buffer *b, json_t **j); - -int buffer_append_json(struct buffer *b, json_t *j); +} /* namespace villas */ diff --git a/common/include/villas/common.h b/common/include/villas/common.hpp similarity index 96% rename from common/include/villas/common.h rename to common/include/villas/common.hpp index 8f2167800..7db650627 100644 --- a/common/include/villas/common.h +++ b/common/include/villas/common.hpp @@ -31,7 +31,7 @@ enum class State { CHECKED = 3, STARTED = 4, LOADED = 4, /* alias for STARTED used by struct plugin */ - OPENED = 4, /* alias for STARTED used by struct io */ + OPENED = 4, /* alias for STARTED used by IO */ STOPPED = 5, UNLOADED = 5, /* alias for STARTED used by struct plugin */ CLOSED = 5, /* alias for STARTED used by struct io */ diff --git a/common/include/villas/compat.h b/common/include/villas/compat.hpp similarity index 100% rename from common/include/villas/compat.h rename to common/include/villas/compat.hpp diff --git a/common/include/villas/dsp/window.hpp b/common/include/villas/dsp/window.hpp index 765b14f85..ba090bf4a 100644 --- a/common/include/villas/dsp/window.hpp +++ b/common/include/villas/dsp/window.hpp @@ -45,14 +45,14 @@ protected: public: Window(size_type s = 0, T i = 0) : - init(i) + init(i), + steps(s) { size_type len = LOG2_CEIL(s); /* Allocate memory for circular history buffer */ data = std::vector(len, i); - steps = s; pos = len; mask = len - 1; } diff --git a/common/include/villas/json_buffer.hpp b/common/include/villas/json_buffer.hpp index 47217456f..484c6cf91 100644 --- a/common/include/villas/json_buffer.hpp +++ b/common/include/villas/json_buffer.hpp @@ -31,17 +31,7 @@ namespace villas { -class Buffer : public std::vector { - -public: - void append(const char *data, size_t len) - { - insert(end(), data, data + len); - } - -}; - -class JsonBuffer : public Buffer +class JsonBuffer : public std::vector { protected: @@ -53,6 +43,11 @@ public: /** Decode JSON document from the beginning of the buffer */ json_t * decode(); + + void append(const char *data, size_t len) + { + insert(end(), data, data + len); + } }; } /* namespace villas */ diff --git a/common/include/villas/kernel/kernel.h b/common/include/villas/kernel/kernel.h deleted file mode 100644 index b293444b3..000000000 --- a/common/include/villas/kernel/kernel.h +++ /dev/null @@ -1,91 +0,0 @@ -/** Linux kernel related functions. - * - * @file - * @author Steffen Vogel - * @copyright 2014-2020, 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 . - *********************************************************************************/ - -/** @addtogroup kernel Kernel - * @{ - */ - -#pragma once - -#include -#include - -#if WITH_CAP -#include - -/** Check if current process has capability \p cap. - * - * @retval 0 If capabilty is present. - * @retval <0 If capability is not present. - */ -int kernel_check_cap(cap_value_t cap); -#endif - -/** Get number of reserved hugepages. */ -int kernel_get_nr_hugepages(); - -/** Set number of reserved hugepages. */ -int kernel_set_nr_hugepages(int nr); - -/** Get kernel cmdline parameter - * - * See https://www.kernel.org/doc/Documentation/kernel-parameters.txt - * - * @param param The cmdline parameter to look for. - * @param buf The string buffer to which the parameter value will be copied to. - * @param len The length of the buffer \p value - * @retval 0 Parameter \p key was found and value was copied to \p value - * @reval <>0 Kernel was not booted with parameter \p key - */ -int kernel_get_cmdline_param(const char *param, char *buf, size_t len); - -/** Checks if a kernel module is loaded - * - * @param module the name of the module - * @retval 0 Module is loaded. - * @reval <>0 Module is not loaded. - */ -int kernel_module_loaded(const char *module); - -/** Load kernel module via modprobe */ -int kernel_module_load(const char *module); - -/** Set parameter of loaded kernel module */ -int kernel_module_set_param(const char *module, const char *param, const char *value); - -/** Get cacheline size in bytes */ -int kernel_get_cacheline_size(); - -/** Get the size of a standard page in bytes. */ -int kernel_get_page_size(); - -/** Get the size of a huge page in bytes. */ -int kernel_get_hugepage_size(); - -/** Get CPU base frequency */ -int kernel_get_cpu_frequency(uint64_t *freq); - -/** Set SMP affinity of IRQ */ -int kernel_irq_setaffinity(unsigned irq, uintmax_t aff , uintmax_t *old); - -/** @} */ diff --git a/common/include/villas/kernel/kernel.hpp b/common/include/villas/kernel/kernel.hpp index da80a6c71..177d27460 100644 --- a/common/include/villas/kernel/kernel.hpp +++ b/common/include/villas/kernel/kernel.hpp @@ -23,6 +23,8 @@ #pragma once +#include + #include namespace villas { @@ -31,5 +33,63 @@ namespace kernel { /** Get the version of the kernel. */ utils::Version getVersion(); +#if WITH_CAP +#include + +/** Check if current process has capability \p cap. + * + * @retval 0 If capabilty is present. + * @retval <0 If capability is not present. + */ +int check_cap(cap_value_t cap); +#endif + +/** Get number of reserved hugepages. */ +int get_nr_hugepages(); + +/** Set number of reserved hugepages. */ +int set_nr_hugepages(int nr); + +/** Get kernel cmdline parameter + * + * See https://www.kernel.org/doc/Documentation/kernel-parameters.txt + * + * @param param The cmdline parameter to look for. + * @param buf The string buffer to which the parameter value will be copied to. + * @param len The length of the buffer \p value + * @retval 0 Parameter \p key was found and value was copied to \p value + * @reval <>0 Kernel was not booted with parameter \p key + */ +int get_cmdline_param(const char *param, char *buf, size_t len); + +/** Checks if a kernel module is loaded + * + * @param module the name of the module + * @retval 0 Module is loaded. + * @reval <>0 Module is not loaded. + */ +int module_loaded(const char *module); + +/** Load kernel module via modprobe */ +int module_load(const char *module); + +/** Set parameter of loaded kernel module */ +int module_set_param(const char *module, const char *param, const char *value); + +/** Get cacheline size in bytes */ +int get_cacheline_size(); + +/** Get the size of a standard page in bytes. */ +int get_page_size(); + +/** Get the size of a huge page in bytes. */ +int get_hugepage_size(); + +/** Get CPU base frequency */ +int get_cpu_frequency(uint64_t *freq); + +/** Set SMP affinity of IRQ */ +int irq_setaffinity(unsigned irq, uintmax_t aff , uintmax_t *old); + } /* namespace villas */ } /* namespace kernel */ diff --git a/common/include/villas/list.h b/common/include/villas/list.h index e746a00e2..0b83e308a 100644 --- a/common/include/villas/list.h +++ b/common/include/villas/list.h @@ -31,7 +31,7 @@ #include #include -#include +#include #define LIST_CHUNKSIZE 16 @@ -76,7 +76,7 @@ int vlist_init(struct vlist *l); * @param dtor A function pointer to a desctructor which will be called for every list item when the list is destroyed. * @param l A pointer to the list data structure. */ -int vlist_destroy(struct vlist *l, dtor_cb_t dtor, bool free); +int vlist_destroy(struct vlist *l, dtor_cb_t dtor = nullptr, bool free = false); /** Append an element to the end of the list */ void vlist_push(struct vlist *l, void *p); @@ -101,7 +101,7 @@ int vlist_insert(struct vlist *l, size_t idx, void *p); */ void * vlist_lookup(struct vlist *l, const char *name); -ssize_t vlist_lookup_index(struct vlist *l, const char *name); +ssize_t vlist_lookup_index(struct vlist *l, const void *ptr); /** Return the first element of the list for which cmp returns zero */ void * vlist_search(struct vlist *l, cmp_cb_t cmp, void *ctx); diff --git a/common/include/villas/log.hpp b/common/include/villas/log.hpp index 27017411b..322fa9ab8 100644 --- a/common/include/villas/log.hpp +++ b/common/include/villas/log.hpp @@ -33,8 +33,6 @@ #include -#include - namespace villas { /* Forward declarations */ diff --git a/common/include/villas/plugin.hpp b/common/include/villas/plugin.hpp index f2f3fbc66..5fb763f2a 100644 --- a/common/include/villas/plugin.hpp +++ b/common/include/villas/plugin.hpp @@ -29,7 +29,7 @@ #include #include -#include +#include namespace villas { namespace plugin { @@ -120,8 +120,8 @@ public: virtual void dump(); - std::string getName(); - std::string getDescription(); + const std::string & getName() const; + const std::string & getDescription() const; protected: std::string name; diff --git a/common/include/villas/task.h b/common/include/villas/task.hpp similarity index 74% rename from common/include/villas/task.h rename to common/include/villas/task.hpp index 366da8000..5c80c0cf7 100644 --- a/common/include/villas/task.h +++ b/common/include/villas/task.hpp @@ -47,7 +47,7 @@ #include #endif -struct task { +struct Task { int clock; /**< CLOCK_{MONOTONIC,REALTIME} */ #if PERIODIC_TASK_IMPL == RDTSC /* We use cycle counts in RDTSC mode */ @@ -63,26 +63,28 @@ struct task { #elif PERIODIC_TASK_IMPL == RDTSC struct tsc tsc; /**< Initialized by tsc_init(). */ #endif + + /** Create a new task with the given rate. */ + Task(int clock = CLOCK_REALTIME); + + ~Task(); + + /** Wait until task elapsed + * + * @retval 0 An error occured. Maybe the task was stopped. + * @retval >0 The nummer of runs this task already fired. + */ + uint64_t wait(); + + void setNext(const struct timespec *next); + void setTimeout(double to); + void setRate(double rate); + + void stop(); + + /** Returns a poll'able file descriptor which becomes readable when the timer expires. + * + * Note: currently not supported on all platforms. + */ + int getFD() const; }; - -/** Create a new task with the given rate. */ -int task_init(struct task *t, double rate, int clock); - -int task_destroy(struct task *t); - -/** Wait until task elapsed - * - * @retval 0 An error occured. Maybe the task was stopped. - * @retval >0 The nummer of runs this task already fired. - */ -uint64_t task_wait(struct task *t); - -int task_set_next(struct task *t, struct timespec *next); -int task_set_timeout(struct task *t, double to); -int task_set_rate(struct task *t, double rate); - -/** Returns a poll'able file descriptor which becomes readable when the timer expires. - * - * Note: currently not supported on all platforms. - */ -int task_fd(struct task *t); diff --git a/common/include/villas/tsc.h b/common/include/villas/tsc.h index 80708c9a4..889747836 100644 --- a/common/include/villas/tsc.h +++ b/common/include/villas/tsc.h @@ -35,7 +35,7 @@ #include #endif -#include +#include #ifndef bit_TSC #define bit_TSC (1 << 4) diff --git a/common/lib/CMakeLists.txt b/common/lib/CMakeLists.txt index a359051a5..dd3c4e99e 100644 --- a/common/lib/CMakeLists.txt +++ b/common/lib/CMakeLists.txt @@ -28,7 +28,6 @@ add_library(villas-common SHARED hist.cpp dsp/pid.cpp kernel/kernel.cpp - kernel/kernel.cpp kernel/rt.cpp list.cpp log.cpp diff --git a/common/lib/advio.cpp b/common/lib/advio.cpp index 15e76ced4..df5382b1c 100644 --- a/common/lib/advio.cpp +++ b/common/lib/advio.cpp @@ -41,8 +41,9 @@ #include #include -#include +#include +using namespace villas; using namespace villas::utils; #define BAR_WIDTH 60 /**< How wide you want the progress meter to be. */ @@ -209,6 +210,10 @@ AFILE * afopen(const char *uri, const char *mode) const char *sep; AFILE *af = new AFILE; + if (!af) + throw RuntimeError("Failed to allocate memory!"); + + memset(af, 0, sizeof(AFILE)); snprintf(af->mode, sizeof(af->mode), "%s", mode); diff --git a/common/lib/buffer.cpp b/common/lib/buffer.cpp index 149408df6..564e9f10b 100644 --- a/common/lib/buffer.cpp +++ b/common/lib/buffer.cpp @@ -22,78 +22,74 @@ #include -#include -#include -#include +#include +#include +#include +#include -int buffer_init(struct buffer *b, size_t size) +using namespace villas; + +Buffer::Buffer(size_t sz) : + len(0), + size(sz) { - b->len = 0; - b->size = size; - b->buf = new char[size]; - if (!b->buf) - return -1; + buf = new char[size]; + if (!buf) + throw RuntimeError("Failed to allocate memory"); - b->state = State::INITIALIZED; - - return 0; + memset(buf, 0, size); } -int buffer_destroy(struct buffer *b) +Buffer::~Buffer() { - if (b->buf) - delete[] b->buf; - - b->state = State::DESTROYED; - - return 0; + delete[] buf; } -void buffer_clear(struct buffer *b) +void Buffer::clear() { - b->len = 0; + len = 0; } -int buffer_append(struct buffer *b, const char *data, size_t len) +int Buffer::append(const char *data, size_t l) { - if (b->len + len > b->size) { - b->size = b->len + len; - b->buf = (char *) realloc(b->buf, b->size); - if (!b->buf) + if (len + l > size) { + size = len + l; + buf = (char *) realloc(buf, size); + if (!buf) return -1; } - memcpy(b->buf + b->len, data, len); + memcpy(buf + len, data, l); - b->len += len; + len += l; return 0; } -int buffer_parse_json(struct buffer *b, json_t **j) +int Buffer::parseJson(json_t **j) { - *j = json_loadb(b->buf, b->len, 0, nullptr); + *j = json_loadb(buf, len, 0, nullptr); if (!*j) return -1; return 0; } -int buffer_append_json(struct buffer *b, json_t *j) +int Buffer::appendJson(json_t *j) { - size_t len; + size_t l; -retry: len = json_dumpb(j, b->buf + b->len, b->size - b->len, 0); - if (b->size < b->len + len) { - b->buf = (char *) realloc(b->buf, b->len + len); - if (!b->buf) +retry: l = json_dumpb(j, buf + len, size - len, 0); + if (size < len + l) { + buf = (char *) realloc(buf, len + l); + if (!buf) return -1; - b->size = b->len + len; + size = len + l; goto retry; } - b->len += len; + len += l; return 0; } diff --git a/common/lib/common.cpp b/common/lib/common.cpp index 7b1215321..926d084cb 100644 --- a/common/lib/common.cpp +++ b/common/lib/common.cpp @@ -21,7 +21,7 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include diff --git a/common/lib/compat.cpp b/common/lib/compat.cpp index 1c2a7c52f..a38c732cd 100644 --- a/common/lib/compat.cpp +++ b/common/lib/compat.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #if JANSSON_VERSION_HEX < 0x020A00 size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags) diff --git a/common/lib/hist.cpp b/common/lib/hist.cpp index d0f004190..dc08fdc7c 100644 --- a/common/lib/hist.cpp +++ b/common/lib/hist.cpp @@ -28,6 +28,7 @@ #include #include #include +#include using namespace villas::utils; @@ -188,6 +189,10 @@ void Hist::plot() const char * Hist::dump() const { char *buf = new char[128]; + if (!buf) + throw RuntimeError("Failed to allocate memory!"); + + memset(buf, 0, 128); strcatf(&buf, "[ "); diff --git a/common/lib/json_buffer.cpp b/common/lib/json_buffer.cpp index 0f7523949..83939c6e7 100644 --- a/common/lib/json_buffer.cpp +++ b/common/lib/json_buffer.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . *********************************************************************************/ -#include +#include #include using namespace villas; @@ -47,7 +47,7 @@ int JsonBuffer::encode(json_t *j) int JsonBuffer::callback(const char *data, size_t len, void *ctx) { - Buffer *b = static_cast(ctx); + JsonBuffer *b = static_cast(ctx); /* Append junk of JSON to buffer */ b->insert(b->end(), &data[0], &data[len]); diff --git a/common/lib/kernel/kernel.cpp b/common/lib/kernel/kernel.cpp index c1003cc77..26a71aaa5 100644 --- a/common/lib/kernel/kernel.cpp +++ b/common/lib/kernel/kernel.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include @@ -57,7 +57,7 @@ Version villas::kernel::getVersion() return Version(ver); } -int kernel_get_cacheline_size() +int villas::kernel::get_cacheline_size() { #if defined(__linux__) && defined(__x86_64__) return sysconf(_SC_LEVEL1_ICACHE_LINESIZE); @@ -80,7 +80,7 @@ int kernel_get_cacheline_size() } #if defined(__linux__) || defined(__APPLE__) -int kernel_get_page_size() +int villas::kernel::get_page_size() { return sysconf(_SC_PAGESIZE); } @@ -89,7 +89,7 @@ int kernel_get_page_size() #endif /* There is no sysconf interface to get the hugepage size */ -int kernel_get_hugepage_size() +int villas::kernel::get_hugepage_size() { #ifdef __linux__ char *key, *value, *unit, *line = nullptr, *lasts; @@ -127,7 +127,7 @@ int kernel_get_hugepage_size() #ifdef __linux__ -int kernel_module_set_param(const char *module, const char *param, const char *value) +int villas::kernel::module_set_param(const char *module, const char *param, const char *value) { FILE *f; char fn[256]; @@ -144,11 +144,11 @@ int kernel_module_set_param(const char *module, const char *param, const char *v return 0; } -int kernel_module_load(const char *module) +int villas::kernel::module_load(const char *module) { int ret; - ret = kernel_module_loaded(module); + ret = module_loaded(module); if (!ret) { debug(LOG_KERNEL | 5, "Kernel module %s already loaded...", module); return 0; @@ -166,11 +166,11 @@ int kernel_module_load(const char *module) default: wait(&ret); - return kernel_module_loaded(module); + return module_loaded(module); } } -int kernel_module_loaded(const char *module) +int villas::kernel::module_loaded(const char *module) { FILE *f; int ret = -1; @@ -194,7 +194,7 @@ int kernel_module_loaded(const char *module) return ret; } -int kernel_get_cmdline_param(const char *param, char *buf, size_t len) +int villas::kernel::get_cmdline_param(const char *param, char *buf, size_t len) { int ret; char cmdline[512], key[128], value[128], *lasts, *tok; @@ -230,7 +230,7 @@ out: return -1; /* not found or error */ } -int kernel_get_nr_hugepages() +int villas::kernel::get_nr_hugepages() { FILE *f; int nr, ret; @@ -248,7 +248,7 @@ int kernel_get_nr_hugepages() return nr; } -int kernel_set_nr_hugepages(int nr) +int villas::kernel::set_nr_hugepages(int nr) { FILE *f; int ret; @@ -272,7 +272,7 @@ int kernel_set_nr_hugepages(int nr) return 0; } -int kernel_irq_setaffinity(unsigned irq, uintmax_t aff, uintmax_t *old) +int villas::kernel::irq_setaffinity(unsigned irq, uintmax_t aff, uintmax_t *old) { char fn[64]; FILE *f; @@ -293,7 +293,7 @@ int kernel_irq_setaffinity(unsigned irq, uintmax_t aff, uintmax_t *old) return ret; } -int kernel_get_cpu_frequency(uint64_t *freq) +int villas::kernel::get_cpu_frequency(uint64_t *freq) { char *line = nullptr, *sep, *end; size_t len = 0; diff --git a/common/lib/kernel/pci.cpp b/common/lib/kernel/pci.cpp index bda24a42b..7e56a2f10 100644 --- a/common/lib/kernel/pci.cpp +++ b/common/lib/kernel/pci.cpp @@ -26,11 +26,13 @@ #include #include -#include +#include #include +#include #include #include +using namespace villas; using namespace villas::utils; int pci_init(struct pci *p) @@ -58,6 +60,10 @@ int pci_init(struct pci *p) continue; struct pci_device *d = new struct pci_device; + if (!d) + throw RuntimeError("Failed to allocate memory!"); + + memset(d, 0, sizeof(struct pci_device)); struct { const char *s; int *p; } map[] = { { "vendor", &d->id.vendor }, @@ -314,6 +320,9 @@ size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions) if (valid_regions > 0) { *regions = new struct pci_region[valid_regions]; + if (!*regions) + throw RuntimeError("Failed to allocate memory!"); + memcpy(*regions, _regions, valid_regions * sizeof (struct pci_region)); } diff --git a/common/lib/kernel/rt.cpp b/common/lib/kernel/rt.cpp index bfc57ea9a..4e0a6737b 100644 --- a/common/lib/kernel/rt.cpp +++ b/common/lib/kernel/rt.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -83,7 +83,7 @@ void setAffinity(int affinity) /* Pin threads to CPUs by setting the affinity */ CpuSet cset_pin(affinity); - is_isol = kernel_get_cmdline_param("isolcpus", isolcpus, sizeof(isolcpus)); + is_isol = get_cmdline_param("isolcpus", isolcpus, sizeof(isolcpus)); if (is_isol) logger->warn("You should reserve some cores for " PROJECT_NAME " (see 'isolcpus')"); else { diff --git a/common/lib/kernel/vfio.cpp b/common/lib/kernel/vfio.cpp index 482600db6..62aade826 100644 --- a/common/lib/kernel/vfio.cpp +++ b/common/lib/kernel/vfio.cpp @@ -46,7 +46,7 @@ #include #include -#include +#include #include using namespace villas; @@ -84,8 +84,8 @@ VfioContainer::VfioContainer() "vfio", "vfio_pci", "vfio_iommu_type1" }; - for(const char* module : requiredKernelModules) { - if(kernel_module_load(module) != 0) { + for (const char* module : requiredKernelModules) { + if (kernel::module_load(module) != 0) { logger->error("Kernel module '{}' required but could not be loaded. " "Please load manually!", module); throw std::exception(); @@ -299,7 +299,7 @@ VfioContainer::attachDevice(const pci_device* pdev) Logger logger = logging.get("kernel:vfio"); /* Load PCI bus driver for VFIO */ - if (kernel_module_load("vfio_pci")) { + if (kernel::module_load("vfio_pci")) { logger->error("Failed to load kernel driver: vfio_pci"); throw std::exception(); } @@ -318,7 +318,7 @@ VfioContainer::attachDevice(const pci_device* pdev) /* Get IOMMU group of device */ int index = isIommuEnabled() ? pci_get_iommu_group(pdev) : 0; if (index < 0) { - ret = kernel_get_cmdline_param("intel_iommu", iommu_state, sizeof(iommu_state)); + ret = kernel::get_cmdline_param("intel_iommu", iommu_state, sizeof(iommu_state)); if(ret != 0 || strcmp("on", iommu_state) != 0) logger->warn("Kernel booted without command line parameter " "'intel_iommu' set to 'on'. Please check documentation " diff --git a/common/lib/kernel/vfio_legacy.cpp b/common/lib/kernel/vfio_legacy.cpp index 35529f2d8..f2f9a769a 100644 --- a/common/lib/kernel/vfio_legacy.cpp +++ b/common/lib/kernel/vfio_legacy.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -134,7 +134,7 @@ int vfio_init(struct vfio_container *v) vlist_init(&v->groups); /* Load VFIO kernel module */ - if (kernel_module_load("vfio")) + if (module_load("vfio")) error("Failed to load kernel module: %s", "vfio"); /* Open VFIO API */ @@ -207,7 +207,7 @@ int vfio_pci_attach(struct vfio_device *d, struct vfio_container *c, struct pci_ int ret; /* Load PCI bus driver for VFIO */ - if (kernel_module_load("vfio_pci")) + if (module_load("vfio_pci")) error("Failed to load kernel driver: %s", "vfio_pci"); /* Bind PCI card to vfio-pci driver*/ @@ -253,6 +253,10 @@ int vfio_device_attach(struct vfio_device *d, struct vfio_container *c, const ch if (!g) { g = new struct vfio_group; + if (!g) + throw RuntimeError("Failed to allocate memory!"); + + memset(g, 0, sizeof(struct vfio_group)); /* Aquire group ownership */ ret = vfio_group_attach(g, c, index); diff --git a/common/lib/list.cpp b/common/lib/list.cpp index 2015805b5..4b09fe148 100644 --- a/common/lib/list.cpp +++ b/common/lib/list.cpp @@ -190,13 +190,11 @@ void * vlist_lookup(struct vlist *l, const char *name) return vlist_search(l, cmp_lookup, (void *) name); } -ssize_t vlist_lookup_index(struct vlist *l, const char *name) +ssize_t vlist_lookup_index(struct vlist *l, const void *ptr) { - void *ptr = vlist_lookup(l, name); - if (!ptr) - return -1; + void *found = vlist_lookup(l, (char *) ptr); - return vlist_index(l, ptr); + return found ? vlist_index(l, found) : -1; } int vlist_contains(struct vlist *l, void *p) diff --git a/common/lib/log.cpp b/common/lib/log.cpp index 70c8b1f6d..e1d188fef 100644 --- a/common/lib/log.cpp +++ b/common/lib/log.cpp @@ -27,6 +27,7 @@ #include #include +#include #include using namespace villas; @@ -36,6 +37,7 @@ Log villas::logging; Log::Log(Level lvl) : level(lvl), +// pattern("%+") pattern("%H:%M:%S %^%l%$ %n: %v") { char *p = getenv("VILLAS_LOG_PREFIX"); @@ -91,7 +93,7 @@ void Log::parse(json_t *cfg) json_error_t err; json_t *json_expressions = nullptr; - ret = json_unpack_ex(cfg, &err, JSON_STRICT, "{ s?: s, s?: s, s?: s, s?: b, s?: s }", + ret = json_unpack_ex(cfg, &err, JSON_STRICT, "{ s?: s, s?: s, s?: o, s?: b, s?: s }", "level", &level, "file", &path, "expressions", &json_expressions, diff --git a/common/lib/plugin.cpp b/common/lib/plugin.cpp index 3685f6bb3..0bc739834 100644 --- a/common/lib/plugin.cpp +++ b/common/lib/plugin.cpp @@ -100,12 +100,12 @@ Plugin::dump() logger->info("Name: '{}' Description: '{}'", name, description); } -std::string Plugin::getName() +const std::string & Plugin::getName() const { return name; } -std::string Plugin::getDescription() +const std::string & Plugin::getDescription() const { return description; } diff --git a/common/lib/task.cpp b/common/lib/task.cpp index 07cb8b0b4..40a604e7a 100644 --- a/common/lib/task.cpp +++ b/common/lib/task.cpp @@ -25,113 +25,101 @@ #include #include -#include +#include #include +#include + +using namespace villas; #if PERIODIC_TASK_IMPL == TIMERFD #include #endif /* PERIODIC_TASK_IMPL */ -int task_init(struct task *t, double rate, int clock) +Task::Task(int clk) : + clock(clk) { - int ret; - - t->clock = clock; - #if PERIODIC_TASK_IMPL == TIMERFD - t->fd = timerfd_create(t->clock, 0); - if (t->fd < 0) - return -1; + fd = timerfd_create(clock, 0); + if (fd < 0) + throw SystemError("Failed to create timerfd"); #elif PERIODIC_TASK_IMPL == RDTSC - ret = tsc_init(&t->tsc); + int ret = tsc_init(&tsc); if (ret) return ret; #endif /* PERIODIC_TASK_IMPL */ - - ret = task_set_rate(t, rate); - if (ret) - return ret; - - return 0; } -int task_set_timeout(struct task *t, double to) +void Task::setTimeout(double to) { struct timespec now; - clock_gettime(t->clock, &now); + clock_gettime(clock, &now); struct timespec timeout = time_from_double(to); struct timespec next = time_add(&now, &timeout); - return task_set_next(t, &next); + setNext(&next); } -int task_set_next(struct task *t, struct timespec *next) +void Task::setNext(const struct timespec *nxt) { #if PERIODIC_TASK_IMPL != RDTSC - t->next = *next; + next = *nxt; #if PERIODIC_TASK_IMPL == TIMERFD int ret; struct itimerspec its = { .it_interval = (struct timespec) { 0, 0 }, - .it_value = t->next + .it_value = next }; - ret = timerfd_settime(t->fd, TFD_TIMER_ABSTIME, &its, nullptr); + ret = timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, nullptr); if (ret) - return ret; + throw SystemError("Failed to set timerfd"); #endif /* PERIODIC_TASK_IMPL == TIMERFD */ #endif /* PERIODIC_TASK_IMPL != RDTSC */ - - return 0; } -int task_set_rate(struct task *t, double rate) +void Task::setRate(double rate) { #if PERIODIC_TASK_IMPL == RDTSC - t->period = tsc_rate_to_cycles(&t->tsc, rate); - t->next = tsc_now(&t->tsc) + t->period; + period = tsc_rate_to_cycles(&tsc, rate); + next = tsc_now(&tsc) + period; #else /* A rate of 0 will disarm the timer */ - t->period = rate ? time_from_double(1.0 / rate) : (struct timespec) { 0, 0 }; + period = rate ? time_from_double(1.0 / rate) : (struct timespec) { 0, 0 }; #if PERIODIC_TASK_IMPL == CLOCK_NANOSLEEP || PERIODIC_TASK_IMPL == NANOSLEEP struct timespec now, next; - clock_gettime(t->clock, &now); + clock_gettime(clock, &now); - next = time_add(&now, &t->period); + next = time_add(&now, &period); - return task_set_next(t, &next); + return setNext(&next); #elif PERIODIC_TASK_IMPL == TIMERFD int ret; struct itimerspec its = { - .it_interval = t->period, - .it_value = t->period + .it_interval = period, + .it_value = period }; - ret = timerfd_settime(t->fd, 0, &its, nullptr); + ret = timerfd_settime(fd, 0, &its, nullptr); if (ret) - return ret; + throw SystemError("Failed to set timerfd"); #endif /* PERIODIC_TASK_IMPL */ #endif /* PERIODIC_TASK_IMPL == RDTSC */ - - return 0; } -int task_destroy(struct task *t) +Task::~Task() { #if PERIODIC_TASK_IMPL == TIMERFD - return close(t->fd); -#else - return 0; + close(fd); #endif } -uint64_t task_wait(struct task *t) +uint64_t Task::wait() { uint64_t runs; @@ -139,19 +127,19 @@ uint64_t task_wait(struct task *t) int ret; struct timespec now; - ret = clock_gettime(t->clock, &now); + ret = clock_gettime(clock, &now); if (ret) return ret; - for (runs = 0; time_cmp(&t->next, &now) < 0; runs++) - t->next = time_add(&t->next, &t->period); + for (runs = 0; time_cmp(&next, &now) < 0; runs++) + next = time_add(&next, &period); #if PERIODIC_TASK_IMPL == CLOCK_NANOSLEEP do { - ret = clock_nanosleep(t->clock, TIMER_ABSTIME, &t->next, nullptr); + ret = clock_nanosleep(clock, TIMER_ABSTIME, &next, nullptr); } while (ret == EINTR); #elif PERIODIC_TASK_IMPL == NANOSLEEP - struct timespec req, rem = time_diff(&now, &t->next); + struct timespec req, rem = time_diff(&now, &next); do { req = rem; @@ -161,28 +149,28 @@ uint64_t task_wait(struct task *t) if (ret) return 0; - ret = clock_gettime(t->clock, &now); + ret = clock_gettime(clock, &now); if (ret) return ret; - for (; time_cmp(&t->next, &now) < 0; runs++) - t->next = time_add(&t->next, &t->period); + for (; time_cmp(&next, &now) < 0; runs++) + next = time_add(&next, &period); #elif PERIODIC_TASK_IMPL == TIMERFD int ret; - ret = read(t->fd, &runs, sizeof(runs)); + ret = read(fd, &runs, sizeof(runs)); if (ret < 0) return 0; #elif PERIODIC_TASK_IMPL == RDTSC uint64_t now; do { - now = tsc_now(&t->tsc); - } while (now < t->next); + now = tsc_now(&tsc); + } while (now < next); - for (runs = 0; t->next < now; runs++) - t->next += t->period; + for (runs = 0; next < now; runs++) + next += period; #else #error "Invalid period task implementation" #endif @@ -190,10 +178,25 @@ uint64_t task_wait(struct task *t) return runs; } -int task_fd(struct task *t) +void Task::stop() { #if PERIODIC_TASK_IMPL == TIMERFD - return t->fd; + int ret; + struct itimerspec its = { + .it_interval = (struct timespec) { 0, 0 }, + .it_value = (struct timespec) { 0, 0 } + }; + + ret = timerfd_settime(fd, 0, &its, nullptr); + if (ret) + throw SystemError("Failed to disarm timerfd"); +#endif /* PERIODIC_TASK_IMPL == TIMERFD */ +} + +int Task::getFD() const +{ +#if PERIODIC_TASK_IMPL == TIMERFD + return fd; #else return -1; #endif diff --git a/common/lib/terminal.cpp b/common/lib/terminal.cpp index b4dafa344..ef8f82ea7 100644 --- a/common/lib/terminal.cpp +++ b/common/lib/terminal.cpp @@ -40,6 +40,8 @@ Terminal::Terminal() isTty = isatty(fileno(stdin)); if (isTty) { + Logger logger = logging.get("terminal"); + struct sigaction sa_resize; sa_resize.sa_flags = SA_SIGINFO; sa_resize.sa_sigaction = resize; @@ -53,7 +55,7 @@ Terminal::Terminal() /* Try to get initial terminal dimensions */ ret = ioctl(STDERR_FILENO, TIOCGWINSZ, &window); if (ret) - throw SystemError("Failed to get terminal dimensions"); + logger->warn("Failed to get terminal dimensions"); } /* Fallback if for some reason we can not determine a prober window size */ diff --git a/common/lib/tsc.cpp b/common/lib/tsc.cpp index 84f36a139..b3a2d1d3b 100644 --- a/common/lib/tsc.cpp +++ b/common/lib/tsc.cpp @@ -23,6 +23,8 @@ #include +using namespace villas; + int tsc_init(struct tsc *t) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -50,7 +52,7 @@ int tsc_init(struct tsc *t) else { int ret; #ifdef __linux__ - ret = kernel_get_cpu_frequency(&t->frequency); + ret = kernel::get_cpu_frequency(&t->frequency); if (ret) return ret; #elif defined(__APPLE__) diff --git a/common/lib/utils.cpp b/common/lib/utils.cpp index 6ce59b170..d5379ad72 100644 --- a/common/lib/utils.cpp +++ b/common/lib/utils.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include static pthread_t main_thread; diff --git a/common/tests/unit/advio.cpp b/common/tests/unit/advio.cpp index 4ab26959c..ce4e2c631 100644 --- a/common/tests/unit/advio.cpp +++ b/common/tests/unit/advio.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include using namespace villas; diff --git a/common/tests/unit/json_buffer.cpp b/common/tests/unit/json_buffer.cpp index a6fd3152f..6f2b0af68 100644 --- a/common/tests/unit/json_buffer.cpp +++ b/common/tests/unit/json_buffer.cpp @@ -30,7 +30,7 @@ using namespace villas; -using villas::Buffer; +using villas::JsonBuffer; TestSuite(buffer, .description = "Buffer datastructure"); diff --git a/common/tests/unit/kernel.cpp b/common/tests/unit/kernel.cpp index 98eb56a22..9d5aa0009 100644 --- a/common/tests/unit/kernel.cpp +++ b/common/tests/unit/kernel.cpp @@ -22,9 +22,10 @@ #include -#include #include +using namespace villas::kernel; + TestSuite(kernel, .description = "Kernel features"); #if defined(__x86_64__) || defined(__i386__) @@ -45,13 +46,13 @@ Test(kernel, sizes) { int sz; - sz = kernel_get_page_size(); + sz = get_page_size(); cr_assert_eq(sz, PAGESIZE); - sz = kernel_get_hugepage_size(); + sz = get_hugepage_size(); cr_assert(sz == HUGEPAGESIZE); - sz = kernel_get_cacheline_size(); + sz = get_cacheline_size(); cr_assert_eq(sz, CACHELINESIZE); } @@ -60,16 +61,16 @@ Test(kernel, hugepages) { int ret; - ret = kernel_set_nr_hugepages(25); + ret = set_nr_hugepages(25); cr_assert_eq(ret, 0); - ret = kernel_get_nr_hugepages(); + ret = get_nr_hugepages(); cr_assert_eq(ret, 25); - ret = kernel_set_nr_hugepages(10); + ret = set_nr_hugepages(10); cr_assert_eq(ret, 0); - ret = kernel_get_nr_hugepages(); + ret = get_nr_hugepages(); cr_assert_eq(ret, 10); } @@ -89,10 +90,10 @@ Test(kernel, module, .disabled = true) { int ret; - ret = kernel_module_loaded("nf_nat"); + ret = module_loaded("nf_nat"); cr_assert_eq(ret, 0); - ret = kernel_module_loaded("does_not_exist"); + ret = module_loaded("does_not_exist"); cr_assert_neq(ret, 0); } @@ -101,7 +102,7 @@ Test(kernel, frequency) int ret; uint64_t freq; - ret = kernel_get_cpu_frequency(&freq); + ret = get_cpu_frequency(&freq); cr_assert_eq(ret, 0); /* Check for plausability only */ diff --git a/common/tests/unit/task.cpp b/common/tests/unit/task.cpp index a3113a76e..b10200dfd 100644 --- a/common/tests/unit/task.cpp +++ b/common/tests/unit/task.cpp @@ -24,27 +24,25 @@ #include -#include +#include #include TestSuite(task, .description = "Periodic timer tasks"); Test(task, rate, .timeout = 10) { - int ret; int runs = 10; double rate = 5, waited; struct timespec start, end; - struct task task; + Task task(CLOCK_MONOTONIC); - ret = task_init(&task, rate, CLOCK_MONOTONIC); - cr_assert_eq(ret, 0); + task.setRate(rate); int i; for (i = 0; i < runs; i++) { clock_gettime(CLOCK_MONOTONIC, &start); - task_wait(&task); + task.wait(); clock_gettime(CLOCK_MONOTONIC, &end); @@ -56,19 +54,14 @@ Test(task, rate, .timeout = 10) if (i < runs) cr_assert_float_eq(waited, 1.0 / rate, 1e-2, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i); - - ret = task_destroy(&task); - cr_assert_eq(ret, 0); } Test(task, wait_until, .timeout = 5) { int ret; - struct task task; struct timespec start, end, diff, future; - ret = task_init(&task, 1, CLOCK_REALTIME); - cr_assert_eq(ret, 0); + Task task(CLOCK_REALTIME); double waitfor = 3.423456789; @@ -76,10 +69,9 @@ Test(task, wait_until, .timeout = 5) diff = time_from_double(waitfor); future = time_add(&start, &diff); - ret = task_set_next(&task, &future); - cr_assert_eq(ret, 0); + task.setNext(&future); - ret = task_wait(&task); + ret = task.wait(); end = time_now(); @@ -88,7 +80,4 @@ Test(task, wait_until, .timeout = 5) double waited = time_delta(&start, &end); cr_assert_float_eq(waited, waitfor, 1e-2, "We slept for %f instead of %f secs", waited, waitfor); - - ret = task_destroy(&task); - cr_assert_eq(ret, 0); }