2014-07-14 11:49:44 +00:00
|
|
|
/** Various helper functions.
|
2014-06-05 09:34:29 +00:00
|
|
|
*
|
2014-06-28 06:40:52 +00:00
|
|
|
* @file
|
2015-06-02 21:53:04 +02:00
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2017-03-03 20:20:13 -04:00
|
|
|
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
|
2017-04-27 12:56:43 +02:00
|
|
|
* @license GNU General Public License (version 3)
|
|
|
|
*
|
|
|
|
* VILLASnode
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* any later version.
|
2017-05-05 19:24:16 +00:00
|
|
|
*
|
2017-04-27 12:56:43 +02:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2017-05-05 19:24:16 +00:00
|
|
|
*
|
2017-04-27 12:56:43 +02:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2015-06-02 21:53:04 +02:00
|
|
|
*********************************************************************************/
|
2014-06-05 09:34:29 +00:00
|
|
|
|
2017-02-16 09:04:12 -03:00
|
|
|
#pragma once
|
2014-06-05 09:34:29 +00:00
|
|
|
|
2014-06-05 09:34:58 +00:00
|
|
|
#include <stdlib.h>
|
2016-06-13 17:17:23 +02:00
|
|
|
#include <stdint.h>
|
2014-06-10 19:44:22 +00:00
|
|
|
#include <sched.h>
|
2016-06-08 22:31:45 +02:00
|
|
|
#include <assert.h>
|
2017-03-06 19:13:43 -04:00
|
|
|
#include <signal.h>
|
2016-06-14 01:17:58 +02:00
|
|
|
#include <sys/types.h>
|
2015-03-21 18:03:29 +01:00
|
|
|
|
|
|
|
#include "log.h"
|
2014-06-10 19:44:22 +00:00
|
|
|
|
2014-07-18 16:05:46 +00:00
|
|
|
#ifdef __GNUC__
|
2016-06-08 22:32:53 +02:00
|
|
|
#define LIKELY(x) __builtin_expect((x),1)
|
|
|
|
#define UNLIKELY(x) __builtin_expect((x),0)
|
2014-07-18 16:05:46 +00:00
|
|
|
#else
|
2016-06-08 22:32:53 +02:00
|
|
|
#define LIKELY(x) (x)
|
|
|
|
#define UNLIKELY(x) (x)
|
2014-07-18 16:05:46 +00:00
|
|
|
#endif
|
|
|
|
|
2014-06-25 01:53:40 +00:00
|
|
|
/* Some color escape codes for pretty log messages */
|
2015-03-31 14:27:38 +02:00
|
|
|
#define GRY(str) "\e[30m" str "\e[0m" /**< Print str in gray */
|
|
|
|
#define RED(str) "\e[31m" str "\e[0m" /**< Print str in red */
|
|
|
|
#define GRN(str) "\e[32m" str "\e[0m" /**< Print str in green */
|
|
|
|
#define YEL(str) "\e[33m" str "\e[0m" /**< Print str in yellow */
|
|
|
|
#define BLU(str) "\e[34m" str "\e[0m" /**< Print str in blue */
|
|
|
|
#define MAG(str) "\e[35m" str "\e[0m" /**< Print str in magenta */
|
|
|
|
#define CYN(str) "\e[36m" str "\e[0m" /**< Print str in cyan */
|
|
|
|
#define WHT(str) "\e[37m" str "\e[0m" /**< Print str in white */
|
|
|
|
#define BLD(str) "\e[1m" str "\e[0m" /**< Print str in bold */
|
2015-03-20 18:55:14 +01:00
|
|
|
|
2015-03-31 14:27:38 +02:00
|
|
|
/* Alternate character set */
|
|
|
|
#define ACS(chr) "\e(0" chr "\e(B"
|
2015-03-31 15:02:51 +02:00
|
|
|
#define ACS_HORIZONTAL ACS("\x71")
|
2015-03-31 18:13:43 +02:00
|
|
|
#define ACS_VERTICAL ACS("\x78")
|
2015-03-31 15:02:51 +02:00
|
|
|
#define ACS_VERTRIGHT ACS("\x74")
|
|
|
|
|
2015-03-21 12:28:17 +01:00
|
|
|
/* CPP stringification */
|
|
|
|
#define XSTR(x) STR(x)
|
|
|
|
#define STR(x) #x
|
|
|
|
|
2016-06-26 15:33:59 +02:00
|
|
|
#define CONCAT_DETAIL(x, y) x##y
|
|
|
|
#define CONCAT(x, y) CONCAT_DETAIL(x, y)
|
|
|
|
#define UNIQUE(x) CONCAT(x, __COUNTER__)
|
|
|
|
|
2016-06-08 22:32:37 +02:00
|
|
|
#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)
|
|
|
|
|
2017-03-25 21:24:06 +01:00
|
|
|
#define SWAP(x,y) do { \
|
|
|
|
__auto_type _x = x; \
|
|
|
|
__auto_type _y = y; \
|
|
|
|
x = _y; \
|
|
|
|
y = _x; \
|
|
|
|
} while(0)
|
|
|
|
|
2016-10-22 20:44:18 -04:00
|
|
|
/** Round-up integer division */
|
|
|
|
#define CEIL(x, y) (((x) + (y) - 1) / (y))
|
|
|
|
|
|
|
|
/** Get nearest up-rounded power of 2 */
|
2016-10-30 15:21:46 -04:00
|
|
|
#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)))
|
2016-06-08 22:32:37 +02:00
|
|
|
|
2015-03-21 12:28:17 +01:00
|
|
|
/** Calculate the number of elements in an array. */
|
2015-03-20 18:55:14 +01:00
|
|
|
#define ARRAY_LEN(a) ( sizeof (a) / sizeof (a)[0] )
|
2014-12-05 12:39:52 +01:00
|
|
|
|
2015-04-01 13:27:10 +02:00
|
|
|
/* 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; })
|
|
|
|
|
2016-06-08 22:32:53 +02:00
|
|
|
#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
|
|
|
|
|
2016-06-14 01:17:58 +02:00
|
|
|
#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))
|
|
|
|
|
2014-06-25 01:53:44 +00:00
|
|
|
/* Forward declarations */
|
2014-12-05 12:17:27 +01:00
|
|
|
struct timespec;
|
2014-06-05 09:34:46 +00:00
|
|
|
|
2016-01-15 15:25:22 +01:00
|
|
|
/** Print copyright message to screen. */
|
|
|
|
void print_copyright();
|
|
|
|
|
2015-05-19 16:53:39 +02:00
|
|
|
/** 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();
|
|
|
|
|
2015-09-22 12:58:37 +02:00
|
|
|
/** Concat formatted string to an existing string.
|
2015-03-18 15:38:06 +01:00
|
|
|
*
|
2015-09-22 12:58:37 +02:00
|
|
|
* 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.
|
2015-03-18 15:38:06 +01:00
|
|
|
*/
|
2015-09-22 12:58:37 +02:00
|
|
|
char * strcatf(char **dest, const char *fmt, ...)
|
|
|
|
__attribute__ ((format(printf, 2, 3)));
|
2015-03-18 15:38:06 +01:00
|
|
|
|
2016-04-16 21:58:13 +02:00
|
|
|
/** Variadic version of strcatf() */
|
2015-09-22 12:58:37 +02:00
|
|
|
char * vstrcatf(char **dest, const char *fmt, va_list va)
|
|
|
|
__attribute__ ((format(printf, 2, 0)));
|
2015-03-18 15:38:06 +01:00
|
|
|
|
2016-04-16 21:58:13 +02:00
|
|
|
/** Format string like strcatf() just starting with empty string */
|
2016-06-08 22:32:05 +02:00
|
|
|
#define strf(fmt, ...) strcatf(&(char *) { NULL }, fmt, ##__VA_ARGS__)
|
2016-06-19 19:23:19 +02:00
|
|
|
#define vstrf(fmt, va) vstrcatf(&(char *) { NULL }, fmt, va)
|
2016-04-16 21:58:13 +02:00
|
|
|
|
2014-07-14 11:49:44 +00:00
|
|
|
/** Convert integer to cpu_set_t.
|
2014-06-10 19:44:22 +00:00
|
|
|
*
|
2016-06-26 15:33:59 +02:00
|
|
|
* @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);
|
|
|
|
|
2017-03-29 08:10:00 +02:00
|
|
|
/** Convert cpu_set_t to an integer. */
|
|
|
|
void cpuset_to_integer(cpu_set_t *cset, uintmax_t *set);
|
|
|
|
|
2016-06-26 15:33:59 +02:00
|
|
|
/** 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").
|
2014-06-10 19:44:22 +00:00
|
|
|
*/
|
2016-06-26 15:33:59 +02:00
|
|
|
char * cpulist_create(char *str, size_t len, cpu_set_t *set);
|
2015-12-13 00:43:59 +01:00
|
|
|
|
2015-03-17 23:20:47 +01:00
|
|
|
/** Allocate and initialize memory. */
|
|
|
|
void * alloc(size_t bytes);
|
|
|
|
|
2015-10-07 09:12:56 +02:00
|
|
|
/** Allocate and copy memory. */
|
|
|
|
void * memdup(const void *src, size_t bytes);
|
|
|
|
|
2015-03-21 18:03:29 +01:00
|
|
|
/** Call quit() in the main thread. */
|
|
|
|
void die();
|
|
|
|
|
2015-09-17 00:55:20 +02:00
|
|
|
/** Used by version_parse(), version_compare() */
|
|
|
|
struct version {
|
|
|
|
int major;
|
|
|
|
int minor;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Compare two versions. */
|
2016-10-30 18:38:47 -04:00
|
|
|
int version_cmp(struct version *a, struct version *b);
|
2015-09-17 00:55:20 +02:00
|
|
|
|
|
|
|
/** Parse a dotted version string. */
|
|
|
|
int version_parse(const char *s, struct version *v);
|
|
|
|
|
2014-06-05 09:35:41 +00:00
|
|
|
/** Check assertion and exit if failed. */
|
2015-12-04 01:50:21 +01:00
|
|
|
#ifndef assert
|
|
|
|
#define assert(exp) do { \
|
2015-05-06 11:41:14 +02:00
|
|
|
if (!EXPECT(exp, 0)) \
|
|
|
|
error("Assertion failed: '%s' in %s(), %s:%d", \
|
|
|
|
XSTR(exp), __FUNCTION__, __BASE_FILE__, __LINE__); \
|
|
|
|
} while (0)
|
2015-12-04 01:50:21 +01:00
|
|
|
#endif
|
2014-06-05 09:34:45 +00:00
|
|
|
|
2016-06-14 01:17:58 +02:00
|
|
|
/** Fill buffer with random data */
|
2017-02-12 14:36:44 -03:00
|
|
|
ssize_t read_random(char *buf, size_t len);
|
2016-06-14 01:17:58 +02:00
|
|
|
|
|
|
|
/** Get CPU timestep counter */
|
2016-10-19 01:25:05 -04:00
|
|
|
__attribute__((always_inline)) static inline uint64_t rdtsc()
|
2016-06-14 01:17:58 +02:00
|
|
|
{
|
|
|
|
uint64_t tsc;
|
|
|
|
|
2016-10-19 01:25:05 -04:00
|
|
|
__asm__ ("rdtsc;"
|
2016-06-14 01:17:58 +02:00
|
|
|
"shl $32, %%rdx;"
|
|
|
|
"or %%rdx,%%rax"
|
|
|
|
: "=a" (tsc)
|
|
|
|
:
|
|
|
|
: "%rcx", "%rdx", "memory");
|
|
|
|
|
|
|
|
return tsc;
|
|
|
|
}
|
|
|
|
|
2016-10-22 20:44:18 -04:00
|
|
|
/** Get log2 of long long integers */
|
|
|
|
static inline int log2i(long long x) {
|
2016-11-07 22:15:00 -05:00
|
|
|
if (x == 0)
|
|
|
|
return 1;
|
2016-10-22 20:44:18 -04:00
|
|
|
|
|
|
|
return sizeof(x) * 8 - __builtin_clzll(x) - 1;
|
|
|
|
}
|
|
|
|
|
2016-06-14 01:17:58 +02:00
|
|
|
/** Sleep with rdtsc */
|
2017-03-06 19:13:43 -04:00
|
|
|
void rdtsc_sleep(uint64_t nanosecs, uint64_t start);
|
|
|
|
|
|
|
|
/** Register a exit callback for program termination (SIGINT / SIGKILL). */
|
|
|
|
void signals_init(void (*cb)(int signal, siginfo_t *sinfo, void *ctx));
|
2017-03-14 01:46:44 -03:00
|
|
|
|
2017-04-15 18:22:47 +02:00
|
|
|
pid_t spawn(const char* name, char *const argv[]);
|