mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
utils: partial port to C++
This commit is contained in:
parent
13a9fcd10b
commit
b71eee85b8
9 changed files with 587 additions and 309 deletions
200
common/include/villas/cpuset.hpp
Normal file
200
common/include/villas/cpuset.hpp
Normal file
|
@ -0,0 +1,200 @@
|
|||
/** Human readable cpusets.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <github@daniel-krebs.net>
|
||||
* @copyright 2017-2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <sched.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <villas/exceptions.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace utils {
|
||||
|
||||
class CpuSet {
|
||||
|
||||
protected:
|
||||
cpu_set_t *setp;
|
||||
|
||||
unsigned num_cpus;
|
||||
size_t sz;
|
||||
|
||||
public:
|
||||
|
||||
CpuSet() :
|
||||
num_cpus(sizeof(uintmax_t) * 8),
|
||||
sz(CPU_ALLOC_SIZE(num_cpus))
|
||||
{
|
||||
|
||||
setp = CPU_ALLOC(num_cpus);
|
||||
if (!setp)
|
||||
throw new villas::RuntimeError("Failed to allocated memory");
|
||||
|
||||
zero();
|
||||
}
|
||||
|
||||
/** Parses string with list of CPU ranges.
|
||||
*
|
||||
* @param str Human readable representation of the set.
|
||||
*/
|
||||
CpuSet(const std::string &str);
|
||||
|
||||
/** Convert integer to cpu_set_t.
|
||||
*
|
||||
* @param set An integer number which is used as the mask
|
||||
*/
|
||||
CpuSet(uintmax_t set);
|
||||
|
||||
/** Convert cpu_set_t to an integer. */
|
||||
operator uintmax_t();
|
||||
|
||||
operator const cpu_set_t*()
|
||||
{
|
||||
return setp;
|
||||
}
|
||||
|
||||
/** Returns human readable representation of the cpuset.
|
||||
*
|
||||
* The output format is a list of CPUs with ranges (for example, "0,1,3-9").
|
||||
*/
|
||||
operator std::string();
|
||||
|
||||
~CpuSet()
|
||||
{
|
||||
CPU_FREE(setp);
|
||||
}
|
||||
|
||||
CpuSet(const CpuSet &src) :
|
||||
CpuSet(src.num_cpus)
|
||||
{
|
||||
memcpy(setp, src.setp, sz);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return count() == 0;
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return count() == num_cpus;
|
||||
}
|
||||
|
||||
unsigned count() const
|
||||
{
|
||||
return CPU_COUNT_S(sz, setp);
|
||||
}
|
||||
|
||||
void zero()
|
||||
{
|
||||
CPU_ZERO_S(sz, setp);
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return sz;
|
||||
}
|
||||
|
||||
CpuSet operator~()
|
||||
{
|
||||
CpuSet full = UINTMAX_MAX;
|
||||
|
||||
return full ^ *this;
|
||||
}
|
||||
|
||||
bool operator==(const CpuSet &rhs)
|
||||
{
|
||||
return CPU_EQUAL_S(sz, setp, rhs.setp);
|
||||
}
|
||||
|
||||
CpuSet& operator&=(const CpuSet &rhs)
|
||||
{
|
||||
CPU_AND_S(sz, setp, setp, rhs.setp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CpuSet& operator|=(const CpuSet &rhs)
|
||||
{
|
||||
CPU_OR_S(sz, setp, setp, rhs.setp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CpuSet& operator^=(const CpuSet &rhs)
|
||||
{
|
||||
CPU_XOR_S(sz, setp, setp, rhs.setp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend CpuSet operator&(CpuSet lhs, const CpuSet &rhs)
|
||||
{
|
||||
lhs &= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend CpuSet operator|(CpuSet lhs, const CpuSet &rhs)
|
||||
{
|
||||
lhs |= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend CpuSet operator^(CpuSet lhs, const CpuSet &rhs)
|
||||
{
|
||||
lhs ^= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//bool& operator[](std::size_t cpu)
|
||||
//{
|
||||
// void cpuset_set_cpu(cpuset_t*setp, cpu_t cpu, int state)
|
||||
//}
|
||||
|
||||
bool operator[](size_t cpu) const
|
||||
{
|
||||
return isset(cpu);
|
||||
}
|
||||
|
||||
bool isset(size_t cpu) const
|
||||
{
|
||||
return CPU_ISSET_S(cpu, sz, setp);
|
||||
}
|
||||
|
||||
void clear(size_t cpu)
|
||||
{
|
||||
CPU_CLR_S(cpu, sz, setp);
|
||||
}
|
||||
|
||||
void set(size_t cpu)
|
||||
{
|
||||
CPU_SET_S(cpu, sz, setp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace villas
|
||||
} // namespace utils
|
||||
|
||||
|
||||
#include <fmt/format.h>
|
|
@ -27,7 +27,6 @@
|
|||
#include <stdint.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <villas/config.h>
|
||||
|
@ -37,6 +36,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern pthread_t main_thread;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define LIKELY(x) __builtin_expect((x),1)
|
||||
#define UNLIKELY(x) __builtin_expect((x),0)
|
||||
|
@ -137,15 +138,6 @@ extern "C" {
|
|||
#define BITMASK(h, l) (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONGLONG - 1 - (h))))
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
|
||||
/* Forward declarations */
|
||||
struct timespec;
|
||||
|
||||
/** Print copyright message to stdout. */
|
||||
void print_copyright();
|
||||
|
||||
/** Print version to stdout. */
|
||||
void print_version();
|
||||
|
||||
/** Normal random variate generator using the Box-Muller method
|
||||
*
|
||||
* @param m Mean
|
||||
|
@ -178,38 +170,6 @@ char * vstrcatf(char **dest, const char *fmt, va_list va)
|
|||
#define strf(fmt, ...) strcatf(&(char *) { NULL }, fmt, ##__VA_ARGS__)
|
||||
#define vstrf(fmt, va) vstrcatf(&(char *) { NULL }, fmt, va)
|
||||
|
||||
#ifdef __linux__
|
||||
/** Convert integer to cpu_set_t.
|
||||
*
|
||||
* @param set An integer number which is used as the mask
|
||||
* @param cset A pointer to the cpu_set_t datastructure
|
||||
*/
|
||||
void cpuset_from_integer(uintmax_t set, cpu_set_t *cset);
|
||||
|
||||
/** Convert cpu_set_t to an integer. */
|
||||
void cpuset_to_integer(cpu_set_t *cset, uintmax_t *set);
|
||||
|
||||
/** Parses string with list of CPU ranges.
|
||||
*
|
||||
* From: https://github.com/mmalecki/util-linux/blob/master/lib/cpuset.c
|
||||
*
|
||||
* @retval 0 On success.
|
||||
* @retval 1 On error.
|
||||
* @retval 2 If fail is set and a cpu number passed in the list doesn't fit
|
||||
* into the cpu_set. If fail is not set cpu numbers that do not fit are
|
||||
* ignored and 0 is returned instead.
|
||||
*/
|
||||
int cpulist_parse(const char *str, cpu_set_t *set, int fail);
|
||||
|
||||
/** Returns human readable representation of the cpuset.
|
||||
*
|
||||
* From: https://github.com/mmalecki/util-linux/blob/master/lib/cpuset.c
|
||||
*
|
||||
* The output format is a list of CPUs with ranges (for example, "0,1,3-9").
|
||||
*/
|
||||
char * cpulist_create(char *str, size_t len, cpu_set_t *set);
|
||||
#endif
|
||||
|
||||
/** Allocate and initialize memory. */
|
||||
void * alloc(size_t bytes);
|
||||
|
||||
|
@ -219,18 +179,6 @@ void * memdup(const void *src, size_t bytes);
|
|||
/** Call quit() in the main thread. */
|
||||
void die();
|
||||
|
||||
/** Used by version_parse(), version_compare() */
|
||||
struct version {
|
||||
int major;
|
||||
int minor;
|
||||
};
|
||||
|
||||
/** Compare two versions. */
|
||||
int version_cmp(struct version *a, struct version *b);
|
||||
|
||||
/** Parse a dotted version string. */
|
||||
int version_parse(const char *s, struct version *v);
|
||||
|
||||
/** Check assertion and exit if failed. */
|
||||
#ifndef assert
|
||||
#define assert(exp) do { \
|
||||
|
@ -240,9 +188,6 @@ int version_parse(const char *s, struct version *v);
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
/** Fill buffer with random data */
|
||||
ssize_t read_random(char *buf, size_t len);
|
||||
|
||||
/** Get log2 of long long integers */
|
||||
static inline int log2i(long long x) {
|
||||
if (x == 0)
|
||||
|
@ -251,9 +196,6 @@ static inline int log2i(long long x) {
|
|||
return sizeof(x) * 8 - __builtin_clzll(x) - 1;
|
||||
}
|
||||
|
||||
/** Register a exit callback for program termination: SIGINT, SIGKILL & SIGALRM. */
|
||||
int signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx));
|
||||
|
||||
/** Send signal \p sig to main thread. */
|
||||
void killme(int sig);
|
||||
|
||||
|
@ -262,10 +204,6 @@ pid_t spawn(const char *name, char *const argv[]);
|
|||
/** Determines the string length as printed on the screen (ignores escable sequences). */
|
||||
size_t strlenp(const char *str);
|
||||
|
||||
/** Remove ANSI control sequences for colored output. */
|
||||
char * decolor(char *str);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/** Utilities.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <github@daniel-krebs.net>
|
||||
* @author Daniel Krebs <github@daniel-krebs.net>
|
||||
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
|
@ -26,6 +27,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
namespace villas {
|
||||
namespace utils {
|
||||
|
||||
|
@ -41,6 +44,21 @@ assertExcept(bool condition, const T& exception)
|
|||
throw exception;
|
||||
}
|
||||
|
||||
/** Print copyright message to stdout. */
|
||||
void print_copyright();
|
||||
|
||||
/** Print version to stdout. */
|
||||
void print_version();
|
||||
|
||||
/** Register a exit callback for program termination: SIGINT, SIGKILL & SIGALRM. */
|
||||
int signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx));
|
||||
|
||||
/** Fill buffer with random data */
|
||||
ssize_t read_random(char *buf, size_t len);
|
||||
|
||||
/** Remove ANSI control sequences for colored output. */
|
||||
char * decolor(char *str);
|
||||
|
||||
} // namespace utils
|
||||
} // namespace villas
|
||||
|
||||
|
|
53
common/include/villas/version.hpp
Normal file
53
common/include/villas/version.hpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/** Version.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <github@daniel-krebs.net>
|
||||
* @copyright 2017-2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace villas {
|
||||
namespace utils {
|
||||
|
||||
class Version {
|
||||
|
||||
protected:
|
||||
int components[3];
|
||||
|
||||
static int cmp(const Version& lhs, const Version& rhs);
|
||||
|
||||
public:
|
||||
/** Parse a dotted version string. */
|
||||
Version(const std::string &s);
|
||||
|
||||
Version(int maj, int min = 0, int pat = 0);
|
||||
|
||||
inline bool operator==(const Version& rhs) { return cmp(*this, rhs) == 0; }
|
||||
inline bool operator!=(const Version& rhs) { return cmp(*this, rhs) != 0; }
|
||||
inline bool operator< (const Version& rhs) { return cmp(*this, rhs) < 0; }
|
||||
inline bool operator> (const Version& rhs) { return cmp(*this, rhs) > 0; }
|
||||
inline bool operator<=(const Version& rhs) { return cmp(*this, rhs) <= 0; }
|
||||
inline bool operator>=(const Version& rhs) { return cmp(*this, rhs) >= 0; }
|
||||
};
|
||||
|
||||
} // namespace villas
|
||||
} // namespace utils
|
|
@ -44,6 +44,8 @@ add_library(villas-common SHARED
|
|||
tsc.c
|
||||
utils.c
|
||||
utils.cpp
|
||||
cpuset.cpp
|
||||
version.cpp
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||
|
|
127
common/lib/cpuset.cpp
Normal file
127
common/lib/cpuset.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
/** Human readable cpusets.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <github@daniel-krebs.net>
|
||||
* @copyright 2017-2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <villas/cpuset.hpp>
|
||||
#include <villas/utils.hpp>
|
||||
|
||||
using namespace villas::utils;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
CpuSet::operator uintmax_t()
|
||||
{
|
||||
uintmax_t iset = 0;
|
||||
|
||||
for (size_t i = 0; i < num_cpus; i++) {
|
||||
if (isset(i))
|
||||
iset |= 1ULL << i;
|
||||
}
|
||||
|
||||
return iset;
|
||||
}
|
||||
|
||||
CpuSet::CpuSet(uintmax_t iset) :
|
||||
CpuSet()
|
||||
{
|
||||
zero();
|
||||
|
||||
for (size_t i = 0; i < num_cpus; i++) {
|
||||
if (iset & (1L << i))
|
||||
set(i);
|
||||
}
|
||||
}
|
||||
|
||||
CpuSet::CpuSet(const std::string &str) :
|
||||
CpuSet()
|
||||
{
|
||||
size_t endpos, start, end;
|
||||
|
||||
for (auto token : tokenize(str, ",")) {
|
||||
auto sep = token.find('-');
|
||||
|
||||
if (sep == std::string::npos) {
|
||||
start = std::stoi(token, &endpos);
|
||||
|
||||
if (token.begin() + endpos != token.end())
|
||||
throw new std::invalid_argument("Not a valid CPU set");
|
||||
|
||||
if (start < num_cpus)
|
||||
set(start);
|
||||
}
|
||||
else {
|
||||
start = std::stoi(token, &endpos);
|
||||
|
||||
if (token.begin() + endpos != token.begin() + sep)
|
||||
throw new std::invalid_argument("Not a valid CPU set");
|
||||
|
||||
auto token2 = token.substr(endpos + 1);
|
||||
|
||||
end = std::stoi(token2, &endpos);
|
||||
|
||||
if (token2.begin() + endpos != token2.end())
|
||||
throw new std::invalid_argument("Not a valid CPU set");
|
||||
|
||||
for (size_t i = start; i <= end && i < num_cpus; i++)
|
||||
set(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CpuSet::operator std::string ()
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (size_t i = 0; i < num_cpus; i++) {
|
||||
if (isset(i)) {
|
||||
size_t run = 0;
|
||||
for (size_t j = i + 1; j < num_cpus; j++) {
|
||||
if (!isset(j))
|
||||
break;
|
||||
|
||||
run++;
|
||||
}
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
ss << ",";
|
||||
|
||||
ss << i;
|
||||
|
||||
if (run == 1) {
|
||||
ss << "," << (i + 1);
|
||||
i++;
|
||||
}
|
||||
else if (run > 1) {
|
||||
ss << "-" << (i + run);
|
||||
i += run;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
|
@ -23,44 +23,20 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <villas/config.h>
|
||||
#include <villas/utils.h>
|
||||
|
||||
pthread_t main_thread;
|
||||
|
||||
void print_copyright()
|
||||
{
|
||||
printf(PROJECT_NAME " %s (built on %s %s)\n",
|
||||
CLR_BLU(PROJECT_BUILD_ID), CLR_MAG(__DATE__), CLR_MAG(__TIME__));
|
||||
printf(" Copyright 2014-2017, Institute for Automation of Complex Power Systems, EONERC\n");
|
||||
printf(" Steffen Vogel <StVogel@eonerc.rwth-aachen.de>\n");
|
||||
}
|
||||
|
||||
void print_version()
|
||||
{
|
||||
printf("%s\n", PROJECT_BUILD_ID);
|
||||
}
|
||||
|
||||
int version_parse(const char *s, struct version *v)
|
||||
{
|
||||
return sscanf(s, "%u.%u", &v->major, &v->minor) != 2;
|
||||
}
|
||||
|
||||
int version_cmp(struct version *a, struct version *b) {
|
||||
int major = a->major - b->major;
|
||||
int minor = a->minor - b->minor;
|
||||
|
||||
return major ? major : minor;
|
||||
}
|
||||
|
||||
double box_muller(float m, float s)
|
||||
{
|
||||
double x1, x2, y1;
|
||||
|
@ -118,128 +94,6 @@ char * vstrcatf(char **dest, const char *fmt, va_list ap)
|
|||
return *dest;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
void cpuset_to_integer(cpu_set_t *cset, uintmax_t *set)
|
||||
{
|
||||
*set = 0;
|
||||
for (int i = 0; i < MIN(sizeof(*set) * 8, CPU_SETSIZE); i++) {
|
||||
if (CPU_ISSET(i, cset))
|
||||
*set |= 1ULL << i;
|
||||
}
|
||||
}
|
||||
|
||||
void cpuset_from_integer(uintmax_t set, cpu_set_t *cset)
|
||||
{
|
||||
CPU_ZERO(cset);
|
||||
for (int i = 0; i < MIN(sizeof(set) * 8, CPU_SETSIZE); i++) {
|
||||
if (set & (1L << i))
|
||||
CPU_SET(i, cset);
|
||||
}
|
||||
}
|
||||
|
||||
/* From: https://github.com/mmalecki/util-linux/blob/master/lib/cpuset.c */
|
||||
static const char *nexttoken(const char *q, int sep)
|
||||
{
|
||||
if (q)
|
||||
q = strchr(q, sep);
|
||||
if (q)
|
||||
q++;
|
||||
return q;
|
||||
}
|
||||
|
||||
int cpulist_parse(const char *str, cpu_set_t *set, int fail)
|
||||
{
|
||||
const char *p, *q;
|
||||
int r = 0;
|
||||
|
||||
q = str;
|
||||
CPU_ZERO(set);
|
||||
|
||||
while (p = q, q = nexttoken(q, ','), p) {
|
||||
unsigned int a; /* beginning of range */
|
||||
unsigned int b; /* end of range */
|
||||
unsigned int s; /* stride */
|
||||
const char *c1, *c2;
|
||||
char c;
|
||||
|
||||
if ((r = sscanf(p, "%u%c", &a, &c)) < 1)
|
||||
return 1;
|
||||
b = a;
|
||||
s = 1;
|
||||
|
||||
c1 = nexttoken(p, '-');
|
||||
c2 = nexttoken(p, ',');
|
||||
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
|
||||
if ((r = sscanf(c1, "%u%c", &b, &c)) < 1)
|
||||
return 1;
|
||||
c1 = nexttoken(c1, ':');
|
||||
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
|
||||
if ((r = sscanf(c1, "%u%c", &s, &c)) < 1)
|
||||
return 1;
|
||||
if (s == 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(a <= b))
|
||||
return 1;
|
||||
while (a <= b) {
|
||||
if (fail && (a >= CPU_SETSIZE))
|
||||
return 2;
|
||||
CPU_SET(a, set);
|
||||
a += s;
|
||||
}
|
||||
}
|
||||
|
||||
if (r == 2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *cpulist_create(char *str, size_t len, cpu_set_t *set)
|
||||
{
|
||||
size_t i;
|
||||
char *ptr = str;
|
||||
int entry_made = 0;
|
||||
|
||||
for (i = 0; i < CPU_SETSIZE; i++) {
|
||||
if (CPU_ISSET(i, set)) {
|
||||
int rlen;
|
||||
size_t j, run = 0;
|
||||
entry_made = 1;
|
||||
for (j = i + 1; j < CPU_SETSIZE; j++) {
|
||||
if (CPU_ISSET(j, set))
|
||||
run++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!run)
|
||||
rlen = snprintf(ptr, len, "%zd,", i);
|
||||
else if (run == 1) {
|
||||
rlen = snprintf(ptr, len, "%zd,%zd,", i, i + 1);
|
||||
i++;
|
||||
} else {
|
||||
rlen = snprintf(ptr, len, "%zd-%zd,", i, i + run);
|
||||
i += run;
|
||||
}
|
||||
if (rlen < 0 || (size_t) rlen + 1 > len)
|
||||
return NULL;
|
||||
ptr += rlen;
|
||||
if (rlen > 0 && len > (size_t) rlen)
|
||||
len -= rlen;
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
ptr -= entry_made;
|
||||
*ptr = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
void * alloc(size_t bytes)
|
||||
{
|
||||
void *p = malloc(bytes);
|
||||
|
@ -260,70 +114,6 @@ void * memdup(const void *src, size_t bytes)
|
|||
return dst;
|
||||
}
|
||||
|
||||
ssize_t read_random(char *buf, size_t len)
|
||||
{
|
||||
int fd;
|
||||
ssize_t bytes, total;
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
bytes = 0;
|
||||
total = 0;
|
||||
while (total < len) {
|
||||
bytes = read(fd, buf + total, len - total);
|
||||
if (bytes < 0)
|
||||
break;
|
||||
|
||||
total += bytes;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* Setup exit handler */
|
||||
int signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx))
|
||||
{
|
||||
int ret;
|
||||
|
||||
info("Initialize signals");
|
||||
|
||||
struct sigaction sa_quit = {
|
||||
.sa_flags = SA_SIGINFO | SA_NODEFER,
|
||||
.sa_sigaction = cb
|
||||
};
|
||||
|
||||
struct sigaction sa_chld = {
|
||||
.sa_flags = 0,
|
||||
.sa_handler = SIG_IGN
|
||||
};
|
||||
|
||||
main_thread = pthread_self();
|
||||
|
||||
sigemptyset(&sa_quit.sa_mask);
|
||||
|
||||
ret = sigaction(SIGINT, &sa_quit, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sigaction(SIGTERM, &sa_quit, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sigaction(SIGALRM, &sa_quit, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sigaction(SIGCHLD, &sa_chld, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void killme(int sig)
|
||||
{
|
||||
/* Send only to main thread in case the ID was initilized by signals_init() */
|
||||
|
@ -384,36 +174,3 @@ size_t strlenp(const char *str)
|
|||
|
||||
return sz;
|
||||
}
|
||||
|
||||
char * decolor(char *str)
|
||||
{
|
||||
char *p, *q;
|
||||
bool inseq = false;
|
||||
|
||||
for (p = q = str; *p; p++) {
|
||||
switch (*p) {
|
||||
case 0x1b:
|
||||
if (*(++p) == '[') {
|
||||
inseq = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (inseq) {
|
||||
inseq = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inseq) {
|
||||
*q = *p;
|
||||
q++;
|
||||
}
|
||||
}
|
||||
|
||||
*q = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,14 @@
|
|||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <villas/utils.h>
|
||||
#include <villas/utils.hpp>
|
||||
#include <villas/config.h>
|
||||
|
||||
namespace villas {
|
||||
namespace utils {
|
||||
|
@ -53,5 +59,112 @@ tokenize(std::string s, std::string delimiter)
|
|||
return tokens;
|
||||
}
|
||||
|
||||
void print_copyright()
|
||||
{
|
||||
std::cout << PROJECT_NAME " " << CLR_BLU(PROJECT_BUILD_ID)
|
||||
<< " (built on " CLR_MAG(__DATE__) " " CLR_MAG(__TIME__) ")" << std::endl
|
||||
<< " Copyright 2014-2017, Institute for Automation of Complex Power Systems, EONERC" << std::endl
|
||||
<< " Steffen Vogel <StVogel@eonerc.rwth-aachen.de>" << std::endl;
|
||||
}
|
||||
|
||||
void print_version()
|
||||
{
|
||||
std::cout << PROJECT_BUILD_ID << std::endl;
|
||||
}
|
||||
|
||||
ssize_t read_random(char *buf, size_t len)
|
||||
{
|
||||
int fd;
|
||||
ssize_t bytes;
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
while (len) {
|
||||
bytes = read(fd, buf, len);
|
||||
if (bytes < 0)
|
||||
break;
|
||||
|
||||
len -= bytes;
|
||||
buf += bytes;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* Setup exit handler */
|
||||
int signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx))
|
||||
{
|
||||
int ret;
|
||||
|
||||
info("Initialize signals");
|
||||
|
||||
struct sigaction sa_quit;
|
||||
sa_quit.sa_flags = SA_SIGINFO | SA_NODEFER;
|
||||
sa_quit.sa_sigaction = cb;
|
||||
|
||||
struct sigaction sa_chld;
|
||||
sa_chld.sa_flags = 0;
|
||||
sa_chld.sa_handler = SIG_IGN;
|
||||
|
||||
main_thread = pthread_self();
|
||||
|
||||
sigemptyset(&sa_quit.sa_mask);
|
||||
|
||||
ret = sigaction(SIGINT, &sa_quit, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sigaction(SIGTERM, &sa_quit, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sigaction(SIGALRM, &sa_quit, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sigaction(SIGCHLD, &sa_chld, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * decolor(char *str)
|
||||
{
|
||||
char *p, *q;
|
||||
bool inseq = false;
|
||||
|
||||
for (p = q = str; *p; p++) {
|
||||
switch (*p) {
|
||||
case 0x1b:
|
||||
if (*(++p) == '[') {
|
||||
inseq = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (inseq) {
|
||||
inseq = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inseq) {
|
||||
*q = *p;
|
||||
q++;
|
||||
}
|
||||
}
|
||||
|
||||
*q = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace villas
|
||||
|
|
70
common/lib/version.cpp
Normal file
70
common/lib/version.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/** Version.
|
||||
*
|
||||
* @author Steffen Vogel <github@daniel-krebs.net>
|
||||
* @copyright 2017-2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <villas/log.hpp>
|
||||
#include <villas/utils.hpp>
|
||||
#include <villas/version.hpp>
|
||||
|
||||
using namespace villas::utils;
|
||||
|
||||
Version::Version(const std::string &str)
|
||||
{
|
||||
size_t endpos;
|
||||
|
||||
auto comp = tokenize(str, ".");
|
||||
|
||||
if (comp.size() > 3)
|
||||
throw new std::invalid_argument("Not a valid version string");
|
||||
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
if (i < comp.size()) {
|
||||
components[i] = std::stoi(comp[i], &endpos, 10);
|
||||
|
||||
if (comp[i].begin() + endpos != comp[i].end())
|
||||
throw new std::invalid_argument("Not a valid version string");
|
||||
}
|
||||
else
|
||||
components[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Version::Version(int maj, int min, int pat) :
|
||||
components{maj, min, pat}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Version::cmp(const Version& lhs, const Version& rhs)
|
||||
{
|
||||
int d;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
d = lhs.components[i] - rhs.components[i];
|
||||
if (d)
|
||||
return d;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue