/** Various helper functions. * * @file * @author Steffen Vogel * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLASnode * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * 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 . *********************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C"{ #endif #ifdef __GNUC__ #define LIKELY(x) __builtin_expect((x),1) #define UNLIKELY(x) __builtin_expect((x),0) #else #define LIKELY(x) (x) #define UNLIKELY(x) (x) #endif /* Some color escape codes for pretty log messages */ #define CLR(clr, str) "\e[" XSTR(clr) "m" str "\e[0m" #define CLR_GRY(str) CLR(30, str) /**< Print str in gray */ #define CLR_RED(str) CLR(31, str) /**< Print str in red */ #define CLR_GRN(str) CLR(32, str) /**< Print str in green */ #define CLR_YEL(str) CLR(33, str) /**< Print str in yellow */ #define CLR_BLU(str) CLR(34, str) /**< Print str in blue */ #define CLR_MAG(str) CLR(35, str) /**< Print str in magenta */ #define CLR_CYN(str) CLR(36, str) /**< Print str in cyan */ #define CLR_WHT(str) CLR(37, str) /**< Print str in white */ #define CLR_BLD(str) CLR( 1, str) /**< Print str in bold */ /* Alternate character set * * The suffixed of the BOX_ macro a constructed by * combining the following letters in the written order: * - U for a line facing upwards * - D for a line facing downwards * - L for a line facing leftwards * - R for a line facing rightwards * * E.g. a cross can be constructed by combining all line fragments: * BOX_UDLR */ #define BOX(chr) "\e(0" chr "\e(B" #define BOX_LR BOX("\x71") /**< Boxdrawing: ─ */ #define BOX_UD BOX("\x78") /**< Boxdrawing: │ */ #define BOX_UDR BOX("\x74") /**< Boxdrawing: ├ */ #define BOX_UDLR BOX("\x6E") /**< Boxdrawing: ┼ */ #define BOX_UDL BOX("\x75") /**< Boxdrawing: ┤ */ #define BOX_ULR BOX("\x76") /**< Boxdrawing: ┴ */ #define BOX_UL BOX("\x6A") /**< Boxdrawing: ┘ */ #define BOX_DLR BOX("\x77") /**< Boxdrawing: ┘ */ #define BOX_DL BOX("\x6B") /**< Boxdrawing: ┘ */ /* CPP stringification */ #define XSTR(x) STR(x) #define STR(x) #x #define CONCAT_DETAIL(x, y) x##y #define CONCAT(x, y) CONCAT_DETAIL(x, y) #define UNIQUE(x) CONCAT(x, __COUNTER__) #define ALIGN(x, a) ALIGN_MASK(x, (uintptr_t) (a) - 1) #define ALIGN_MASK(x, m) (((uintptr_t) (x) + (m)) & ~(m)) #define IS_ALIGNED(x, a) (ALIGN(x, a) == (uintptr_t) x) #define SWAP(x,y) do { \ __auto_type _x = x; \ __auto_type _y = y; \ x = _y; \ y = _x; \ } while(0) /** Round-up integer division */ #define CEIL(x, y) (((x) + (y) - 1) / (y)) /** Get nearest up-rounded power of 2 */ #define LOG2_CEIL(x) (1 << (log2i((x) - 1) + 1)) /** Check if the number is a power of 2 */ #define IS_POW2(x) (((x) != 0) && !((x) & ((x) - 1))) /** Calculate the number of elements in an array. */ #define ARRAY_LEN(a) ( sizeof (a) / sizeof (a)[0] ) /* Return the bigger value */ #define MAX(a, b) ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a > _b ? _a : _b; }) /* Return the smaller value */ #define MIN(a, b) ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; }) #ifndef offsetof #define offsetof(type, member) __builtin_offsetof(type, member) #endif #ifndef container_of #define container_of(ptr, type, member) ({ const typeof( ((type *) 0)->member ) *__mptr = (ptr); \ (type *) ( (char *) __mptr - offsetof(type, member) ); \ }) #endif #define BITS_PER_LONGLONG (sizeof(long long) * 8) /* Some helper macros */ #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 * @param s Standard deviation * @return Normal variate random variable (Gaussian) */ double box_muller(float m, float s); /** Double precission uniform random variable */ double randf(); /** Concat formatted string to an existing string. * * This function uses realloc() to resize the destination. * Please make sure to only on dynamic allocated destionations!!! * * @param dest A pointer to a malloc() allocated memory region * @param fmt A format string like for printf() * @param ... Optional parameters like for printf() * @retval The the new value of the dest buffer. */ char * strcatf(char **dest, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); /** Variadic version of strcatf() */ char * vstrcatf(char **dest, const char *fmt, va_list va) __attribute__ ((format(printf, 2, 0))); /** Format string like strcatf() just starting with empty string */ #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); /** Allocate and copy memory. */ 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 { \ if (!EXPECT(exp, 0)) \ error("Assertion failed: '%s' in %s(), %s:%d", \ XSTR(exp), __FUNCTION__, __BASE_FILE__, __LINE__); \ } while (0) #endif /** Fill buffer with random data */ ssize_t read_random(char *buf, size_t len); /** Get CPU timestep counter */ __attribute__((always_inline)) static inline uint64_t rdtsc() { uint64_t tsc; __asm__ ("rdtsc;" "shl $32, %%rdx;" "or %%rdx,%%rax" : "=a" (tsc) : : "%rcx", "%rdx", "memory"); return tsc; } /** Get log2 of long long integers */ static inline int log2i(long long x) { if (x == 0) return 1; return sizeof(x) * 8 - __builtin_clzll(x) - 1; } /** Sleep with rdtsc */ void rdtsc_sleep(uint64_t nanosecs, uint64_t start); /** 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); 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); #ifdef __cplusplus } #endif