mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
Merge branch 'infiniband-memory' into infiniband
This commit is contained in:
commit
f3a5b81649
107 changed files with 1648 additions and 471 deletions
|
@ -26,7 +26,11 @@
|
|||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "crypt.h"
|
||||
#include <villas/crypt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
struct advio {
|
||||
CURL *curl;
|
||||
|
@ -81,3 +85,7 @@ void arewind(AFILE *file);
|
|||
int adownload(AFILE *af, int resume);
|
||||
|
||||
int aupload(AFILE *af, int resume);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
#include "api/session.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct lws;
|
||||
struct super_node;
|
||||
|
@ -81,3 +85,7 @@ int api_stop(struct api *a);
|
|||
int api_ws_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
|
||||
|
||||
int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -30,6 +30,10 @@
|
|||
#include <villas/queue.h>
|
||||
#include <villas/buffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
enum api_version {
|
||||
API_VERSION_UNKOWN = 0,
|
||||
API_VERSION_1 = 1
|
||||
|
@ -70,3 +74,7 @@ int api_session_destroy(struct api_session *s);
|
|||
int api_session_run_command(struct api_session *s, json_t *req, json_t **resp);
|
||||
|
||||
char * api_session_name(struct api_session *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#pragma once
|
||||
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
@ -37,4 +39,4 @@ typedef std::atomic<enum state> atomic_state;
|
|||
|
||||
typedef _Atomic enum state atomic_state;
|
||||
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bitset {
|
||||
char *set;
|
||||
size_t dimension;
|
||||
|
@ -62,4 +66,8 @@ int bitset_test(struct bitset *b, size_t bit);
|
|||
int bitset_cmp(struct bitset *a, struct bitset *b);
|
||||
|
||||
/** Return an human readable representation of the bit set */
|
||||
char * bitset_dump(struct bitset *b);
|
||||
char *bitset_dump(struct bitset *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct buffer {
|
||||
enum state state;
|
||||
|
||||
|
||||
char *buf;
|
||||
size_t len;
|
||||
size_t size;
|
||||
|
@ -40,11 +44,15 @@ struct buffer {
|
|||
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);
|
||||
int buffer_append_json(struct buffer *b, json_t *j);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Common states for most objects in VILLASnode (paths, nodes, hooks, plugins) */
|
||||
enum state {
|
||||
STATE_DESTROYED = 0,
|
||||
|
@ -36,3 +40,13 @@ enum state {
|
|||
STATE_UNLOADED = 5, /* alias for STATE_STARTED used by struct plugin */
|
||||
STATE_CLOSED = 5 /* alias for STATE_STARTED used by struct io */
|
||||
};
|
||||
|
||||
/** Callback to destroy list elements.
|
||||
*
|
||||
* @param data A pointer to the data which should be freed.
|
||||
*/
|
||||
typedef int (*dtor_cb_t)(void *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,8 +20,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if JANSSON_VERSION_HEX < 0x020A00
|
||||
size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
|
||||
#endif
|
||||
|
@ -43,3 +49,7 @@ size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
|
|||
#define htobe32(x) OSSwapHostToBigInt32(x)
|
||||
#define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
#endif /* __MACH__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Paths */
|
||||
#define PLUGIN_PATH PREFIX "/share/villas/node/plugins"
|
||||
#define WEB_PATH PREFIX "/share/villas/node/web"
|
||||
|
@ -56,3 +60,7 @@
|
|||
/* Required kernel version */
|
||||
#define KERNEL_VERSION_MAJ 3
|
||||
#define KERNEL_VERSION_MIN 6
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -27,14 +27,18 @@
|
|||
|
||||
#include "sample.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Convert a libconfig object to a jansson object */
|
||||
json_t * config_to_json(config_setting_t *cfg);
|
||||
json_t *config_to_json(config_setting_t *cfg);
|
||||
|
||||
/* Convert a jansson object into a libconfig object. */
|
||||
int json_to_config(json_t *json, config_setting_t *parent);
|
||||
|
||||
/* Create a JSON object from command line parameters. */
|
||||
json_t * json_load_cli(int argc, char *argv[]);
|
||||
json_t *json_load_cli(int argc, char *argv[]);
|
||||
|
||||
int json_object_extend_str(json_t *orig, const char *str);
|
||||
|
||||
|
@ -42,3 +46,7 @@ void json_object_extend_key_value(json_t *obj, const char *key, const char *valu
|
|||
|
||||
/* Merge two JSON objects recursively. */
|
||||
int json_object_extend(json_t *orig, json_t *merge);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,9 +25,17 @@
|
|||
#include <stdio.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** Calculate SHA1 hash of complete file \p f and place it into \p sha1.
|
||||
*
|
||||
* @param sha1[out] Must be SHA_DIGEST_LENGTH (20) in size.
|
||||
* @retval 0 Everything was okay.
|
||||
*/
|
||||
int sha1sum(FILE *f, unsigned char *sha1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
struct io;
|
||||
|
@ -104,3 +108,7 @@ struct format_type {
|
|||
};
|
||||
|
||||
struct format_type * format_type_lookup(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Forward declarations. */
|
||||
struct sample;
|
||||
|
||||
|
@ -32,3 +35,7 @@ void csv_header(struct io *io);
|
|||
|
||||
int csv_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt);
|
||||
int csv_sprint(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
struct io;
|
||||
|
@ -33,3 +37,7 @@ int json_reserve_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, str
|
|||
|
||||
int json_reserve_print(struct io *io, struct sample *smps[], unsigned cnt);
|
||||
int json_reserve_scan(struct io *io, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
||||
|
@ -32,3 +36,7 @@ int json_sscan(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
|
|||
|
||||
int json_print(struct io *io, struct sample *smps[], unsigned cnt);
|
||||
int json_scan(struct io *io, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declaration */
|
||||
struct msg;
|
||||
struct sample;
|
||||
|
@ -53,3 +57,7 @@ int msg_to_sample(struct msg *msg, struct sample *smp);
|
|||
|
||||
/** Copy fields form \p smp into \p msg. */
|
||||
int msg_from_sample(struct msg *msg, struct sample *smp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** The current version number for the message format */
|
||||
#define MSG_VERSION 2
|
||||
|
||||
|
@ -90,3 +94,7 @@ struct msg
|
|||
uint32_t i; /**< Integer values. */
|
||||
} data[];
|
||||
} __attribute__((packed));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
||||
|
@ -33,3 +37,7 @@ int protobuf_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct
|
|||
|
||||
/** Read struct sample's from buffer \p buf into samples \p smps. */
|
||||
int protobuf_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
||||
|
@ -58,3 +62,7 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
|
|||
|
||||
/** Read struct sample's from buffer \p buf into samples \p smps. */
|
||||
int raw_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations. */
|
||||
struct sample;
|
||||
struct msg;
|
||||
|
@ -39,3 +43,7 @@ int villas_binary_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, s
|
|||
|
||||
/** Read struct sample's from buffer \p buf into samples \p smps. */
|
||||
int villas_binary_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct io;
|
||||
struct sample;
|
||||
|
@ -33,3 +37,7 @@ void villas_human_header(struct io *io);
|
|||
|
||||
int villas_human_print(struct io *io, struct sample *smps[], unsigned cnt);
|
||||
int villas_human_scan(struct io *io, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
85
include/villas/hash_table.h
Normal file
85
include/villas/hash_table.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/** A generic hash table
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017-2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct hash_table_entry {
|
||||
void *key;
|
||||
void *data;
|
||||
|
||||
struct hash_table_entry *next;
|
||||
};
|
||||
|
||||
/** A thread-safe hash table using separate chaing with linked lists. */
|
||||
struct hash_table {
|
||||
enum state state;
|
||||
|
||||
struct hash_table_entry **table;
|
||||
|
||||
size_t size;
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
/** Initialize a new hash table.
|
||||
*
|
||||
*/
|
||||
int hash_table_init(struct hash_table *ht, size_t size);
|
||||
|
||||
/** Destroy a hash table.
|
||||
*
|
||||
*
|
||||
*/
|
||||
int hash_table_destroy(struct hash_table *ht, dtor_cb_t dtor, bool release);
|
||||
|
||||
/** Insert a new key/value pair into the hash table.
|
||||
*
|
||||
*/
|
||||
int hash_table_insert(struct hash_table *ht, void *key, void *data);
|
||||
|
||||
/** Delete a key from the hash table.
|
||||
*
|
||||
*
|
||||
*/
|
||||
int hash_table_delete(struct hash_table *ht, void *key);
|
||||
|
||||
/** Perform a lookup in the hash table.
|
||||
*
|
||||
* @retval != NULL The value for the given key.
|
||||
* @retval NULL The given key is not stored in the hash table.
|
||||
*/
|
||||
void * hash_table_lookup(struct hash_table *ht, void *key);
|
||||
|
||||
/** Dump the contents of the hash table in a human readable format to stdout. */
|
||||
void hash_table_dump(struct hash_table *ht);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HIST_HEIGHT (LOG_WIDTH - 55)
|
||||
#define HIST_SEQ 17
|
||||
|
||||
|
@ -103,3 +107,7 @@ int hist_dump_json(struct hist *h, FILE *f);
|
|||
|
||||
/** Build a libjansson / JSON object of the histogram. */
|
||||
json_t * hist_json(struct hist *h);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -34,8 +34,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hook_type.h"
|
||||
#include "common.h"
|
||||
#include <villas/hook_type.h>
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct path;
|
||||
|
@ -96,3 +100,7 @@ int hook_cmp_priority(const void *a, const void *b);
|
|||
* }
|
||||
*/
|
||||
int hook_parse_list(struct list *list, json_t *cfg, struct path *p, struct node *n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct hook;
|
||||
struct sample;
|
||||
|
@ -74,3 +78,6 @@ struct hook_type {
|
|||
|
||||
struct hook_type * hook_type_lookup(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -23,9 +23,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "advio.h"
|
||||
#include "common.h"
|
||||
#include "node.h"
|
||||
#include <villas/advio.h>
|
||||
#include <villas/common.h>
|
||||
#include <villas/node.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
@ -134,3 +138,7 @@ int io_sscan(struct io *io, char *buf, size_t len, size_t *rbytes, struct sample
|
|||
* @retval <0 Something went wrong.
|
||||
*/
|
||||
int io_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
#include <villas/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#define IF_IRQ_MAX 3 /**< Maxmimal number of IRQs of an interface */
|
||||
|
||||
#ifndef SO_MARK
|
||||
|
@ -121,4 +125,8 @@ int if_get_irqs(struct interface *i);
|
|||
*/
|
||||
int if_set_affinity(struct interface *i, int affinity);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct version;
|
||||
|
||||
|
@ -85,6 +89,10 @@ int kernel_get_page_size();
|
|||
int kernel_get_hugepage_size();
|
||||
|
||||
/** Set SMP affinity of IRQ */
|
||||
int kernel_irq_setaffinity(unsigned irq, uintmax_t new, uintmax_t *old);
|
||||
int kernel_irq_setaffinity(unsigned irq, uintmax_t new , uintmax_t *old );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SCH_NETEM_ATTR_DIST 0x2000
|
||||
|
||||
struct rtnl_netem_corr
|
||||
|
@ -43,3 +47,7 @@ struct rtnl_netem
|
|||
};
|
||||
|
||||
void *rtnl_tc_data(struct rtnl_tc *tc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
#include <netlink/route/route.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Get index of outgoing interface for given destination address.
|
||||
*
|
||||
* @retval >=0 Interface index of outgoing interface.
|
||||
|
@ -37,9 +41,13 @@
|
|||
int nl_get_egress(struct nl_addr *addr);
|
||||
|
||||
/** Get or create global netlink socket. */
|
||||
struct nl_sock * nl_init();
|
||||
struct nl_sock *nl_init();
|
||||
|
||||
/** Close and free global netlink socket. */
|
||||
void nl_shutdown();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int rt_init(int priority, int affinity);
|
||||
|
||||
int rt_set_affinity(int affinity);
|
||||
|
@ -43,4 +47,8 @@ int rt_lock_memory();
|
|||
*/
|
||||
int rt_is_preemptible();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
typedef uint32_t tc_hdl_t;
|
||||
|
||||
struct interface;
|
||||
|
@ -72,4 +76,8 @@ int tc_prio(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl
|
|||
*/
|
||||
int tc_mark(struct interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
typedef uint32_t tc_hdl_t;
|
||||
|
||||
struct interface;
|
||||
|
@ -70,4 +74,8 @@ int tc_netem(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hd
|
|||
|
||||
int tc_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -8,7 +8,22 @@
|
|||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 20177, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
@ -17,7 +32,11 @@
|
|||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#define LIST_CHUNKSIZE 16
|
||||
|
||||
|
@ -46,12 +65,6 @@ __attribute__((destructor(105))) static void UNIQUE(__dtor)() { \
|
|||
#define list_first(list) list_at(list, 0)
|
||||
#define list_last(list) list_at(list, (list)->length-1)
|
||||
|
||||
/** Callback to destroy list elements.
|
||||
*
|
||||
* @param data A pointer to the data which should be freed.
|
||||
*/
|
||||
typedef int (*dtor_cb_t)(void *);
|
||||
|
||||
/** Callback to search or sort a list. */
|
||||
typedef int (*cmp_cb_t)(const void *, const void *);
|
||||
|
||||
|
@ -120,3 +133,7 @@ int list_set(struct list *l, int index, void *value);
|
|||
* @retval >=0 Entry \p value was found at returned index.
|
||||
*/
|
||||
ssize_t list_index(struct list *l, void *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,9 +29,18 @@ struct log;
|
|||
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** Parse logging configuration. */
|
||||
int log_parse(struct log *l, json_t *cfg);
|
||||
|
||||
/** Print configuration error and exit. */
|
||||
void jerror(json_error_t *err, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -25,9 +25,13 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#include "stats.h"
|
||||
#include "common.h"
|
||||
#include "list.h"
|
||||
#include <villas/stats.h>
|
||||
#include <villas/common.h>
|
||||
#include <villas/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct stats;
|
||||
|
@ -93,3 +97,7 @@ int mapping_parse(struct mapping_entry *e, json_t *cfg, struct list *nodes);
|
|||
int mapping_parse_str(struct mapping_entry *e, const char *str, struct list *nodes);
|
||||
|
||||
int mapping_parse_list(struct list *l, json_t *cfg, struct list *nodes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,57 +21,50 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#define HUGEPAGESIZE (1 << 21)
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct memtype;
|
||||
#include <villas/memory_type.h>
|
||||
|
||||
typedef void *(*memzone_allocator_t)(struct memtype *mem, size_t len, size_t alignment);
|
||||
typedef int (*memzone_deallocator_t)(struct memtype *mem, void *ptr, size_t len);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum memtype_flags {
|
||||
MEMORY_MMAP = (1 << 0),
|
||||
MEMORY_DMA = (1 << 1),
|
||||
MEMORY_HUGEPAGE = (1 << 2),
|
||||
MEMORY_HEAP = (1 << 3)
|
||||
};
|
||||
|
||||
struct memtype {
|
||||
const char *name;
|
||||
int flags;
|
||||
|
||||
size_t alignment;
|
||||
|
||||
memzone_allocator_t alloc;
|
||||
memzone_deallocator_t free;
|
||||
|
||||
void *_vd; /**<Virtual data for possible state */
|
||||
};
|
||||
|
||||
enum memblock_flags {
|
||||
MEMBLOCK_USED = 1,
|
||||
};
|
||||
/* Forward declarations */
|
||||
struct node;
|
||||
|
||||
/** Descriptor of a memory block. Associated block always starts at
|
||||
* &m + sizeof(struct memblock). */
|
||||
struct memblock {
|
||||
struct memblock* prev;
|
||||
struct memblock* next;
|
||||
size_t len; /**<Length of the block; doesn't include the descriptor itself */
|
||||
int flags;
|
||||
* &m + sizeof(struct memory_block). */
|
||||
struct memory_block {
|
||||
struct memory_block *prev;
|
||||
struct memory_block *next;
|
||||
size_t length; /**< Length of the block; doesn't include the descriptor itself */
|
||||
bool used;
|
||||
};
|
||||
|
||||
/** @todo Unused for now */
|
||||
struct memzone {
|
||||
struct memtype * const type;
|
||||
struct memory_allocation {
|
||||
struct memory_type *type;
|
||||
|
||||
void *addr;
|
||||
uintptr_t physaddr;
|
||||
size_t len;
|
||||
struct memory_allocation *parent;
|
||||
|
||||
void *address;
|
||||
size_t alignment;
|
||||
size_t length;
|
||||
|
||||
union {
|
||||
#ifdef WITH_NODE_INFINIBAND
|
||||
struct {
|
||||
struct ibv_mr *mr;
|
||||
} ib;
|
||||
#endif
|
||||
struct {
|
||||
struct memory_block *block;
|
||||
} managed;
|
||||
};
|
||||
};
|
||||
|
||||
/** Initilialize memory subsystem */
|
||||
|
@ -82,13 +75,12 @@ int memory_init(int hugepages);
|
|||
* @retval NULL If allocation failed.
|
||||
* @retval <>0 If allocation was successful.
|
||||
*/
|
||||
void * memory_alloc(struct memtype *m, size_t len);
|
||||
void * memory_alloc(struct memory_type *m, size_t len);
|
||||
|
||||
void * memory_alloc_aligned(struct memtype *m, size_t len, size_t alignment);
|
||||
void * memory_alloc_aligned(struct memory_type *m, size_t len, size_t alignment);
|
||||
|
||||
int memory_free(struct memtype *m, void *ptr, size_t len);
|
||||
int memory_free(void *ptr);
|
||||
|
||||
struct memtype * memtype_managed_init(void *ptr, size_t len);
|
||||
|
||||
extern struct memtype memtype_heap;
|
||||
extern struct memtype memtype_hugepage;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
70
include/villas/memory_type.h
Normal file
70
include/villas/memory_type.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/** Memory allocators.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declaratio */
|
||||
struct memory_type;
|
||||
|
||||
typedef struct memory_allocation * (*memory_allocator_t)(struct memory_type *mem, size_t len, size_t alignment);
|
||||
typedef int (*memory_deallocator_t)(struct memory_type *mem, struct memory_allocation * ma);
|
||||
|
||||
enum memory_type_flags {
|
||||
MEMORY_MMAP = (1 << 0),
|
||||
MEMORY_DMA = (1 << 1),
|
||||
MEMORY_HUGEPAGE = (1 << 2),
|
||||
MEMORY_HEAP = (1 << 3)
|
||||
};
|
||||
|
||||
struct memory_type {
|
||||
const char *name;
|
||||
int flags;
|
||||
|
||||
size_t alignment;
|
||||
|
||||
memory_allocator_t alloc;
|
||||
memory_deallocator_t free;
|
||||
|
||||
void *_vd; /**< Virtual data for internal state */
|
||||
};
|
||||
|
||||
extern struct memory_type memory_type_heap;
|
||||
extern struct memory_type memory_hugepage;
|
||||
|
||||
struct ibv_mr * memory_type_ib_mr(void *ptr);
|
||||
|
||||
struct node;
|
||||
|
||||
struct memory_type * memory_ib(struct node *n, struct memory_type *parent);
|
||||
struct memory_type * memory_managed(void *ptr, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -32,11 +32,15 @@
|
|||
#include <netinet/in.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "node_type.h"
|
||||
#include "sample.h"
|
||||
#include "list.h"
|
||||
#include "queue.h"
|
||||
#include "common.h"
|
||||
#include <villas/node_type.h>
|
||||
#include <villas/sample.h>
|
||||
#include <villas/list.h>
|
||||
#include <villas/queue.h>
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
struct node_direction {
|
||||
int enabled;
|
||||
|
@ -158,7 +162,10 @@ int node_write(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
|
||||
int node_fd(struct node *n);
|
||||
|
||||
struct memtype * node_memtype(struct node *n, struct memtype *parent);
|
||||
struct memory_type * node_memory_type(struct node *n, struct memory_type *parent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* @{
|
||||
*********************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jansson.h>
|
||||
|
@ -85,6 +89,14 @@ struct node_type {
|
|||
*/
|
||||
int (*parse)(struct node *n, json_t *cfg);
|
||||
|
||||
/** Check the current node configuration for plausability and errors.
|
||||
*
|
||||
* @param n A pointer to the node object.
|
||||
* @retval 0 Success. Node configuration is good.
|
||||
* @retval <0 Error. The node configuration is bogus.
|
||||
*/
|
||||
int (*check)(struct node *n);
|
||||
|
||||
/** Parse node from command line arguments. */
|
||||
int (*parse_cli)(struct node *n, int argc, char *argv[]);
|
||||
|
||||
|
@ -152,7 +164,7 @@ struct node_type {
|
|||
int (*fd)(struct node *n);
|
||||
|
||||
/** */
|
||||
struct memtype * (*memtype)(struct node *n, struct memtype *parent);
|
||||
struct memory_type * (*memory_type)(struct node *n, struct memory_type *parent);
|
||||
};
|
||||
|
||||
/** Initialize all registered node type subsystems.
|
||||
|
@ -172,4 +184,8 @@ const char * node_type_name(struct node_type *vt);
|
|||
|
||||
struct node_type * node_type_lookup(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include <villas/list.h>
|
||||
#include <villas/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct format_type;
|
||||
|
||||
|
@ -81,4 +85,8 @@ int amqp_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
/** @see node_type::write */
|
||||
int amqp_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
#include <villas/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declaration */
|
||||
struct cbuilder;
|
||||
|
||||
|
@ -65,4 +69,8 @@ struct cbuilder {
|
|||
int eventfd; /**< Eventfd for synchronizing cbuilder_read() / cbuilder_write() access. */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include <villas/list.h>
|
||||
#include <villas/timing.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// whether to use read() or mmap() kernel interface
|
||||
#define COMEDI_USE_READ (1)
|
||||
//#define COMEDI_USE_READ (0)
|
||||
|
@ -45,20 +49,19 @@ struct comedi_chanspec {
|
|||
};
|
||||
|
||||
struct comedi_direction {
|
||||
int subdevice; ///< Comedi subdevice
|
||||
int buffer_size; ///< Comedi's kernel buffer size in kB
|
||||
int sample_size; ///< Size of a single measurement sample
|
||||
int sample_rate_hz; ///< Sample rate in Hz
|
||||
bool present; ///< Config present
|
||||
bool enabled; ///< Card is started successfully
|
||||
bool running; ///< Card is actively transfering samples
|
||||
struct timespec started; ///< Timestamp when sampling started
|
||||
struct timespec last_debug; ///< Timestamp of last debug output
|
||||
size_t counter; ///< Number of villas samples transfered
|
||||
int subdevice; ///< Comedi subdevice
|
||||
int buffer_size; ///< Comedi's kernel buffer size in kB
|
||||
int sample_size; ///< Size of a single measurement sample
|
||||
int sample_rate_hz; ///< Sample rate in Hz
|
||||
bool present; ///< Config present
|
||||
bool enabled; ///< Card is started successfully
|
||||
bool running; ///< Card is actively transfering samples
|
||||
struct timespec started; ///< Timestamp when sampling started
|
||||
struct timespec last_debug; ///< Timestamp of last debug output
|
||||
size_t counter; ///< Number of villas samples transfered
|
||||
struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels
|
||||
unsigned *chanlist; ///< Channel list in comedi's packed format
|
||||
size_t chanlist_len; ///< Number of channels for this direction
|
||||
|
||||
unsigned *chanlist; ///< Channel list in comedi's packed format
|
||||
size_t chanlist_len; ///< Number of channels for this direction
|
||||
|
||||
char* buffer;
|
||||
char* bufptr;
|
||||
|
@ -70,8 +73,8 @@ struct comedi {
|
|||
comedi_t *dev;
|
||||
|
||||
#if COMEDI_USE_READ
|
||||
char* buf;
|
||||
char* bufptr;
|
||||
char *buf;
|
||||
char *bufptr;
|
||||
#else
|
||||
char *map;
|
||||
size_t bufpos;
|
||||
|
@ -100,3 +103,7 @@ int comedi_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int comedi_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include <villas/node.h>
|
||||
#include <villas/task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FILE_MAX_PATHLEN 512
|
||||
|
||||
struct file {
|
||||
|
@ -85,3 +89,7 @@ int file_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int file_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
#include <villas/node.h>
|
||||
#include <villas/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
enum iec61850_type {
|
||||
/* According to IEC 61850-7-2 */
|
||||
IEC61850_TYPE_BOOLEAN,
|
||||
|
@ -107,4 +111,8 @@ int iec61850_receiver_stop(struct iec61850_receiver *r);
|
|||
|
||||
int iec61850_receiver_destroy(struct iec61850_receiver *r);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
#include <villas/list.h>
|
||||
#include <villas/nodes/iec61850.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
struct iec61850_sv {
|
||||
char *interface;
|
||||
int app_id;
|
||||
|
@ -97,4 +101,8 @@ int iec61850_sv_write(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
|
||||
int iec61850_sv_fd(struct node *n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
#include <villas/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct node;
|
||||
struct sample;
|
||||
|
@ -63,4 +67,8 @@ int influxdb_close(struct node *n);
|
|||
/** @see node_type::write */
|
||||
int influxdb_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include <villas/queue_signalled.h>
|
||||
#include <villas/pool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct node;
|
||||
struct sample;
|
||||
|
@ -64,4 +68,8 @@ int loopback_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
/** @see node_type::write */
|
||||
int loopback_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include <villas/io.h>
|
||||
#include <villas/queue_signalled.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct format_type;
|
||||
struct mosquitto;
|
||||
|
@ -96,4 +100,8 @@ int mqtt_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
/** @see node_type::write */
|
||||
int mqtt_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include <villas/list.h>
|
||||
#include <villas/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** The maximum length of a packet which contains stuct msg. */
|
||||
#define NANOMSG_MAX_PACKET_LEN 1500
|
||||
|
||||
|
@ -72,4 +76,8 @@ int nanomsg_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
/** @see node_type::write */
|
||||
int nanomsg_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
#include <villas/node.h>
|
||||
#include <villas/task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct node;
|
||||
|
||||
struct ngsi {
|
||||
|
@ -95,3 +99,7 @@ int ngsi_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int ngsi_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "node.h"
|
||||
#include "msg.h"
|
||||
#include <villas/node.h>
|
||||
#include <villas/msg.h>
|
||||
|
||||
/* Define RTLAB before including OpalPrint.h for messages to be sent
|
||||
* to the OpalDisplay. Otherwise stdout will be used. */
|
||||
|
@ -41,6 +41,10 @@
|
|||
#include "AsyncApi.h"
|
||||
#include "OpalGenAsyncParamCtrl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct opal {
|
||||
int reply;
|
||||
int mode;
|
||||
|
@ -85,4 +89,8 @@ int opal_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
/** @see node_type::write */
|
||||
int opal_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include <villas/config.h>
|
||||
#include <villas/shmem.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Node-type for shared memory communication.
|
||||
* @see node_type
|
||||
*/
|
||||
|
@ -66,3 +70,7 @@ int shmem_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int shmem_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include <villas/timing.h>
|
||||
#include <villas/task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct node;
|
||||
struct sample;
|
||||
|
@ -90,3 +94,7 @@ int signal_generator_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
enum signal_generator_type signal_generator_lookup_type(const char *type);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
|
||||
#include <villas/node.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct format_type;
|
||||
|
||||
|
@ -155,3 +159,7 @@ int socket_parse_addr(const char *str, struct sockaddr *sa, enum socket_layer la
|
|||
int socket_compare_addr(struct sockaddr *x, struct sockaddr *y);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
#include <villas/task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct node;
|
||||
struct sample;
|
||||
|
@ -51,7 +55,7 @@ struct stats_node {
|
|||
int stats_node_init(struct super_node *sn);
|
||||
|
||||
/** @see node_type::print */
|
||||
char * stats_node_print(struct node *n);
|
||||
char *stats_node_print(struct node *n);
|
||||
|
||||
/** @see node_type::parse */
|
||||
int stats_node_parse(struct node *n, json_t *cfg);
|
||||
|
@ -65,4 +69,8 @@ int stats_node_stop(struct node *n);
|
|||
/** @see node_type::read */
|
||||
int stats_node_read(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include <villas/io.h>
|
||||
#include <villas/task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct test_rtt;
|
||||
struct node;
|
||||
|
@ -81,3 +85,7 @@ int test_rtt_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int test_rtt_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
#include <villas/io.h>
|
||||
#include <villas/config.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WEBSOCKET_QUEUELEN (DEFAULT_QUEUELEN * 64)
|
||||
#define DEFAULT_WEBSOCKET_SAMPLELEN DEFAULT_SAMPLELEN
|
||||
|
||||
|
@ -114,3 +118,7 @@ int websocket_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int websocket_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include <villas/list.h>
|
||||
#include <villas/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if ZMQ_BUILD_DRAFT_API && (ZMQ_VERSION_MAJOR > 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 2))
|
||||
#define ZMQ_BUILD_DISH 1
|
||||
#endif
|
||||
|
@ -104,3 +108,7 @@ int zeromq_read(struct node *n, struct sample *smps[], unsigned cnt);
|
|||
int zeromq_write(struct node *n, struct sample *smps[], unsigned cnt);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -32,14 +32,18 @@
|
|||
#include <pthread.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "queue.h"
|
||||
#include "pool.h"
|
||||
#include "bitset.h"
|
||||
#include "common.h"
|
||||
#include "hook.h"
|
||||
#include "mapping.h"
|
||||
#include "task.h"
|
||||
#include <villas/list.h>
|
||||
#include <villas/queue.h>
|
||||
#include <villas/pool.h>
|
||||
#include <villas/bitset.h>
|
||||
#include <villas/common.h>
|
||||
#include <villas/hook.h>
|
||||
#include <villas/mapping.h>
|
||||
#include <villas/task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct stats;
|
||||
|
@ -169,3 +173,7 @@ int path_uses_node(struct path *p, struct node *n);
|
|||
int path_parse(struct path *p, json_t *cfg, struct list *nodes);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,21 @@
|
|||
#include "node_type.h"
|
||||
#include "format_type.h"
|
||||
|
||||
/** @todo This is ugly as hell and broken on OS X / Clang anyway. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** (De-)Register a plugin by adding it to the global plugin list.
|
||||
*
|
||||
* We make use of GCC's / Clang's constructor/destructor function
|
||||
* attributes to let the following code be executed by the loader.
|
||||
* This works only when we compile libvillas as a shared library!
|
||||
*
|
||||
* The __attribute__((constructor)) / __attribute__((destructor))
|
||||
* is currently only supported by GCC and Clang
|
||||
*
|
||||
* See: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
|
||||
*/
|
||||
#define REGISTER_PLUGIN(p) \
|
||||
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {\
|
||||
if (plugins.state == STATE_DESTROYED) \
|
||||
|
@ -95,3 +109,7 @@ void plugin_dump(enum plugin_type type);
|
|||
|
||||
/** Find registered and loaded plugin with given name and type. */
|
||||
struct plugin * plugin_lookup(enum plugin_type type, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,19 +28,21 @@
|
|||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "common.h"
|
||||
#include "memory.h"
|
||||
#include <villas/queue.h>
|
||||
#include <villas/common.h>
|
||||
#include <villas/memory.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** A thread-safe memory pool */
|
||||
struct pool {
|
||||
off_t buffer_off; /**< Offset from the struct address to the underlying memory area */
|
||||
struct memtype *mem;
|
||||
|
||||
enum state state;
|
||||
|
||||
size_t len; /**< Length of the underlying memory area */
|
||||
|
||||
size_t blocksz; /**< Length of a block in bytes */
|
||||
size_t alignment; /**< Alignment of a block in bytes */
|
||||
|
||||
|
@ -58,7 +60,7 @@ struct pool {
|
|||
* @retval 0 The pool has been successfully initialized.
|
||||
* @retval <>0 There was an error during the pool initialization.
|
||||
*/
|
||||
int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memtype *mem);
|
||||
int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memory_type *mem);
|
||||
|
||||
/** Destroy and release memory used by pool. */
|
||||
int pool_destroy(struct pool *p);
|
||||
|
@ -92,3 +94,7 @@ INLINE int pool_put(struct pool *p, void *buf)
|
|||
{
|
||||
return queue_push(&p->queue, buf);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,16 +33,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "atomic.h"
|
||||
#include "common.h"
|
||||
#include <villas/atomic.h>
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct memtype;
|
||||
struct memory_type;
|
||||
|
||||
#define CACHELINE_SIZE 64
|
||||
typedef char cacheline_pad_t[CACHELINE_SIZE];
|
||||
|
@ -58,7 +61,6 @@ struct queue {
|
|||
|
||||
atomic_state state;
|
||||
|
||||
struct memtype *mem;
|
||||
size_t buffer_mask;
|
||||
off_t buffer_off; /**< Relative pointer to struct queue_cell[] */
|
||||
|
||||
|
@ -74,7 +76,7 @@ struct queue {
|
|||
};
|
||||
|
||||
/** Initialize MPMC queue */
|
||||
int queue_init(struct queue *q, size_t size, struct memtype *mem);
|
||||
int queue_init(struct queue *q, size_t size, struct memory_type *mem);
|
||||
|
||||
/** Desroy MPMC queue and release memory */
|
||||
int queue_destroy(struct queue *q);
|
||||
|
@ -112,3 +114,7 @@ int queue_pull_many(struct queue *q, void *ptr[], size_t cnt);
|
|||
* @return -1 on failure.
|
||||
*/
|
||||
int queue_close(struct queue *q);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
#include "queue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
enum queue_signalled_flags {
|
||||
/* Mode */
|
||||
QUEUE_SIGNALLED_AUTO = (0 << 0), /**< We will choose the best method available on the platform */
|
||||
|
@ -64,7 +68,7 @@ struct queue_signalled {
|
|||
|
||||
#define queue_signalled_available(q) queue_available(&((q)->queue))
|
||||
|
||||
int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memtype *mem, int flags);
|
||||
int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_type *mem, int flags);
|
||||
|
||||
int queue_signalled_destroy(struct queue_signalled *qs);
|
||||
|
||||
|
@ -80,3 +84,7 @@ int queue_signalled_close(struct queue_signalled *qs);
|
|||
|
||||
/** Returns a file descriptor which can be used with poll / select to wait for new data */
|
||||
int queue_signalled_fd(struct queue_signalled *qs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,11 +23,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <villas/atomic.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -35,6 +31,10 @@ extern "C" {
|
|||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct pool;
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct list;
|
||||
struct node;
|
||||
|
@ -46,3 +50,7 @@ int signal_parse(struct signal *s, json_t *cfg);
|
|||
int signal_parse_list(struct list *list, json_t *cfg);
|
||||
|
||||
int signal_get_offset(const char *str, struct node *n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,13 +21,16 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#ifndef _STATS_H_
|
||||
#define _STATS_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "hist.h"
|
||||
#include <villas/hist.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
@ -86,4 +89,6 @@ void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose);
|
|||
|
||||
enum stats_id stats_lookup_id(const char *name);
|
||||
|
||||
#endif /* _STATS_H_ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,11 +23,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "list.h"
|
||||
#include "api.h"
|
||||
#include "web.h"
|
||||
#include "log.h"
|
||||
#include "common.h"
|
||||
#include <villas/list.h>
|
||||
#include <villas/api.h>
|
||||
#include <villas/web.h>
|
||||
#include <villas/log.h>
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Global configuration */
|
||||
struct super_node {
|
||||
|
@ -83,3 +87,7 @@ int super_node_stop(struct super_node *sn);
|
|||
|
||||
/** Desctroy configuration object. */
|
||||
int super_node_destroy(struct super_node *sn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct table_column {
|
||||
int width; /**< Width of the column. */
|
||||
char *title; /**< The title as shown in the table header. */
|
||||
|
@ -55,3 +61,7 @@ void table_row(struct table *t, ...);
|
|||
void table_footer(struct table *t);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** We can choose between two periodic task implementations */
|
||||
//#define PERIODIC_TASK_IMPL NANOSLEEP
|
||||
#define TIMERFD 1
|
||||
|
@ -73,3 +77,7 @@ int task_set_rate(struct task *t, double rate);
|
|||
* Note: currently not supported on all platforms.
|
||||
*/
|
||||
int task_fd(struct task *t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/** Get delta between two timespec structs */
|
||||
struct timespec time_diff(const struct timespec *start, const struct timespec *end);
|
||||
|
||||
|
@ -45,3 +49,7 @@ double time_to_double(const struct timespec *ts);
|
|||
|
||||
/** Convert double containing seconds after 1970 to timespec. */
|
||||
struct timespec time_from_double(double secs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
#include <villas/config.h>
|
||||
#include <villas/log.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define LIKELY(x) __builtin_expect((x),1)
|
||||
#define UNLIKELY(x) __builtin_expect((x),0)
|
||||
|
@ -275,3 +280,8 @@ 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
|
|
@ -25,7 +25,11 @@
|
|||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <villas/common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct api;
|
||||
|
@ -60,3 +64,7 @@ int web_stop(struct web *w);
|
|||
|
||||
/** Parse HTTPd and WebSocket related options */
|
||||
int web_parse(struct web *w, json_t *cfg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,7 @@ LIBEXT = $(BUILDDIR)/$(LIBEXT_NAME).so.$(LIBEXT_ABI_VERSION)
|
|||
|
||||
LIBEXT_SRCS += $(addprefix lib/, sample.c queue.c queue_signalled.c \
|
||||
memory.c log.c shmem.c utils.c kernel/kernel.c list.c \
|
||||
timing.c pool.c log_helper.c \
|
||||
timing.c pool.c log_helper.c hash_table.c memory/managed.c \
|
||||
)
|
||||
|
||||
LIBEXT_LDFLAGS = -shared
|
||||
|
|
|
@ -26,11 +26,13 @@ LIB = $(BUILDDIR)/$(LIB_NAME).so.$(LIB_ABI_VERSION)
|
|||
|
||||
# Object files for libvillas
|
||||
LIB_SRCS += $(addprefix lib/kernel/, kernel.c rt.c) \
|
||||
$(addprefix lib/memory/, heap.c hugepage.c managed.c) \
|
||||
$(addprefix lib/, sample.c path.c node.c hook.c log.c log_config.c \
|
||||
utils.c super_node.c hist.c timing.c pool.c list.c queue.c \
|
||||
queue_signalled.c memory.c memory_ib.c advio.c plugin.c node_type.c stats.c \
|
||||
queue_signalled.c memory.c advio.c plugin.c node_type.c stats.c \
|
||||
mapping.c shmem.c config_helper.c crypt.c compat.c \
|
||||
log_helper.c task.c buffer.c table.c bitset.c signal.c \
|
||||
hash_table.c \
|
||||
)
|
||||
|
||||
LIB_LDFLAGS += -shared
|
||||
|
|
|
@ -272,7 +272,7 @@ int api_init(struct api *a, struct super_node *sn)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = queue_signalled_init(&a->pending, 1024, &memtype_heap, 0);
|
||||
ret = queue_signalled_init(&a->pending, 1024, &memory_type_heap, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -40,11 +40,11 @@ int api_session_init(struct api_session *s, enum api_mode m)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = queue_init(&s->request.queue, 128, &memtype_heap);
|
||||
ret = queue_init(&s->request.queue, 128, &memory_type_heap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = queue_init(&s->response.queue, 128, &memtype_heap);
|
||||
ret = queue_init(&s->response.queue, 128, &memory_type_heap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
202
lib/hash_table.c
Normal file
202
lib/hash_table.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
/** A generic hash table
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017-2018, 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <villas/utils.h>
|
||||
#include <villas/hash_table.h>
|
||||
|
||||
static int hash_table_hash(struct hash_table *ht, void *key)
|
||||
{
|
||||
uintptr_t ptr = (uintptr_t) key;
|
||||
|
||||
return ptr % ht->size;
|
||||
}
|
||||
|
||||
int hash_table_init(struct hash_table *ht, size_t size)
|
||||
{
|
||||
int ret;
|
||||
size_t len = sizeof(struct hash_table_entry *) * size;
|
||||
|
||||
assert(ht->state == STATE_DESTROYED);
|
||||
|
||||
ret = pthread_mutex_init(&ht->lock, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ht->table = alloc(len);
|
||||
|
||||
memset(ht->table, 0, len);
|
||||
|
||||
ht->size = size;
|
||||
ht->state = STATE_INITIALIZED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_table_destroy(struct hash_table *ht, dtor_cb_t dtor, bool release)
|
||||
{
|
||||
int ret;
|
||||
struct hash_table_entry *cur, *next;
|
||||
|
||||
assert(ht->state == STATE_INITIALIZED);
|
||||
|
||||
pthread_mutex_lock(&ht->lock);
|
||||
|
||||
for (int i = 0; i < ht->size; i++) {
|
||||
for (cur = ht->table[i]; cur; cur = next) {
|
||||
if (dtor)
|
||||
dtor(cur->data);
|
||||
|
||||
if (release)
|
||||
free(cur->data);
|
||||
|
||||
next = cur->next;
|
||||
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ht->lock);
|
||||
|
||||
ret = pthread_mutex_destroy(&ht->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
free(ht->table);
|
||||
|
||||
ht->state = STATE_DESTROYED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_table_insert(struct hash_table *ht, void *key, void *data)
|
||||
{
|
||||
int ret, ikey = hash_table_hash(ht, key);
|
||||
struct hash_table_entry *hte, *cur;
|
||||
|
||||
assert(ht->state == STATE_INITIALIZED);
|
||||
|
||||
pthread_mutex_lock(&ht->lock);
|
||||
|
||||
/* Check that the key is not already in the table */
|
||||
for (cur = ht->table[ikey];
|
||||
cur && cur->key != key;
|
||||
cur = cur->next);
|
||||
|
||||
if (cur)
|
||||
ret = -1;
|
||||
else {
|
||||
hte = alloc(sizeof(struct hash_table_entry));
|
||||
if (hte) {
|
||||
hte->key = key;
|
||||
hte->data = data;
|
||||
hte->next = NULL;
|
||||
|
||||
if ((cur = ht->table[ikey]))
|
||||
hte->next = ht->table[ikey];
|
||||
|
||||
ht->table[ikey] = hte;
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ht->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int hash_table_delete(struct hash_table *ht, void *key)
|
||||
{
|
||||
int ret, ikey = hash_table_hash(ht, key);
|
||||
struct hash_table_entry *cur, *prev;
|
||||
|
||||
assert(ht->state == STATE_INITIALIZED);
|
||||
|
||||
pthread_mutex_lock(&ht->lock);
|
||||
|
||||
for (prev = NULL,
|
||||
cur = ht->table[ikey];
|
||||
cur && cur->key != key;
|
||||
prev = cur,
|
||||
cur = cur->next);
|
||||
|
||||
if (cur) {
|
||||
if (prev)
|
||||
prev->next = cur->next;
|
||||
else
|
||||
ht->table[ikey] = cur->next;
|
||||
|
||||
free(cur);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
ret = -1; /* not found */
|
||||
|
||||
pthread_mutex_unlock(&ht->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void * hash_table_lookup(struct hash_table *ht, void *key)
|
||||
{
|
||||
int ikey = hash_table_hash(ht, key);
|
||||
struct hash_table_entry *hte;
|
||||
|
||||
assert(ht->state == STATE_INITIALIZED);
|
||||
|
||||
pthread_mutex_lock(&ht->lock);
|
||||
|
||||
for (hte = ht->table[ikey];
|
||||
hte && hte->key != key;
|
||||
hte = hte->next);
|
||||
|
||||
void *data = hte ? hte->data : NULL;
|
||||
|
||||
pthread_mutex_unlock(&ht->lock);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void hash_table_dump(struct hash_table *ht)
|
||||
{
|
||||
struct hash_table_entry *hte;
|
||||
|
||||
assert(ht->state == STATE_INITIALIZED);
|
||||
|
||||
pthread_mutex_lock(&ht->lock);
|
||||
|
||||
for (int i = 0; i < ht->size; i++) {
|
||||
printf("%i: ", i);
|
||||
for (hte = ht->table[i]; hte; hte = hte->next)
|
||||
printf("%p->%p ", hte->key, hte->data);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ht->lock);
|
||||
}
|
276
lib/memory.c
276
lib/memory.c
|
@ -25,26 +25,29 @@
|
|||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Required to allocate hugepages on Apple OS X */
|
||||
#ifdef __MACH__
|
||||
#include <mach/vm_statistics.h>
|
||||
#elif defined(__linux__)
|
||||
#include <villas/kernel/kernel.h>
|
||||
#endif
|
||||
|
||||
#include <villas/log.h>
|
||||
#include <villas/memory.h>
|
||||
#include <villas/utils.h>
|
||||
#include <villas/hash_table.h>
|
||||
#include <villas/kernel/kernel.h>
|
||||
|
||||
static struct hash_table allocations = { .state = STATE_DESTROYED };
|
||||
|
||||
int memory_init(int hugepages)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (allocations.state == STATE_DESTROYED) {
|
||||
ret = hash_table_init(&allocations, 100);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
int ret, pagecnt, pagesz;
|
||||
int pagecnt, pagesz;
|
||||
struct rlimit l;
|
||||
|
||||
info("Initialize memory sub-system");
|
||||
|
@ -77,252 +80,41 @@ int memory_init(int hugepages)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void * memory_alloc(struct memtype *m, size_t len)
|
||||
void * memory_alloc(struct memory_type *m, size_t len)
|
||||
{
|
||||
void *ptr = m->alloc(m, len, sizeof(void *));
|
||||
|
||||
debug(LOG_MEM | 5, "Allocated %#zx bytes of %s memory: %p", len, m->name, ptr);
|
||||
|
||||
return ptr;
|
||||
return memory_alloc_aligned(m, len, sizeof(void *));
|
||||
}
|
||||
|
||||
void * memory_alloc_aligned(struct memtype *m, size_t len, size_t alignment)
|
||||
void * memory_alloc_aligned(struct memory_type *m, size_t len, size_t alignment)
|
||||
{
|
||||
void *ptr = m->alloc(m, len, alignment);
|
||||
struct memory_allocation *ma = m->alloc(m, len, alignment);
|
||||
|
||||
debug(LOG_MEM | 5, "Allocated %#zx bytes of %#zx-byte-aligned %s memory: %p", len, alignment, m->name, ptr);
|
||||
hash_table_insert(&allocations, ma->address, ma);
|
||||
|
||||
return ptr;
|
||||
debug(LOG_MEM | 5, "Allocated %#zx bytes of %#zx-byte-aligned %s memory: %p", ma->length, ma->alignment, ma->type->name, ma->address);
|
||||
|
||||
return ma->address;
|
||||
}
|
||||
|
||||
int memory_free(struct memtype *m, void *ptr, size_t len)
|
||||
int memory_free(void *ptr)
|
||||
{
|
||||
debug(LOG_MEM | 5, "Releasing %#zx bytes of %s memory", len, m->name);
|
||||
|
||||
return m->free(m, ptr, len);
|
||||
}
|
||||
|
||||
static void * memory_heap_alloc(struct memtype *m, size_t len, size_t alignment)
|
||||
{
|
||||
void *ptr;
|
||||
int ret;
|
||||
|
||||
if (alignment < sizeof(void *))
|
||||
alignment = sizeof(void *);
|
||||
/* Find corresponding memory allocation entry */
|
||||
struct memory_allocation *ma = (struct memory_allocation *) hash_table_lookup(&allocations, ptr);
|
||||
if (!ma)
|
||||
return -1;
|
||||
|
||||
ret = posix_memalign(&ptr, alignment, len);
|
||||
debug(LOG_MEM | 5, "Releasing %#zx bytes of %s memory", ma->length, ma->type->name);
|
||||
|
||||
return ret ? NULL : ptr;
|
||||
}
|
||||
ret = ma->type->free(ma->type, ma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
int memory_heap_free(struct memtype *m, void *ptr, size_t len)
|
||||
{
|
||||
free(ptr);
|
||||
/* Remove allocation entry */
|
||||
ret = hash_table_delete(&allocations, ma->address);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Allocate memory backed by hugepages with malloc() like interface */
|
||||
static void * memory_hugepage_alloc(struct memtype *m, size_t len, size_t alignment)
|
||||
{
|
||||
void *ret;
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
|
||||
#ifdef __MACH__
|
||||
flags |= VM_FLAGS_SUPERPAGE_SIZE_2MB;
|
||||
#elif defined(__linux__)
|
||||
flags |= MAP_HUGETLB;
|
||||
|
||||
if (getuid() == 0)
|
||||
flags |= MAP_LOCKED;
|
||||
#endif
|
||||
|
||||
ret = mmap(NULL, len, prot, flags, -1, 0);
|
||||
if (ret == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_hugepage_free(struct memtype *m, void *ptr, size_t len)
|
||||
{
|
||||
len = ALIGN(len, HUGEPAGESIZE); /* ugly see: https://lkml.org/lkml/2015/3/27/171 */
|
||||
|
||||
return munmap(ptr, len);
|
||||
}
|
||||
|
||||
void* memory_managed_alloc(struct memtype *m, size_t len, size_t alignment)
|
||||
{
|
||||
/* Simple first-fit allocation */
|
||||
struct memblock *first = (struct memblock *) m->_vd;
|
||||
struct memblock *block;
|
||||
|
||||
for (block = first; block != NULL; block = block->next) {
|
||||
if (block->flags & MEMBLOCK_USED)
|
||||
continue;
|
||||
|
||||
char* cptr = (char *) block + sizeof(struct memblock);
|
||||
size_t avail = block->len;
|
||||
uintptr_t uptr = (uintptr_t) cptr;
|
||||
|
||||
/* Check alignment first; leave a gap at start of block to assure
|
||||
* alignment if necessary */
|
||||
uintptr_t rem = uptr % alignment;
|
||||
uintptr_t gap = 0;
|
||||
if (rem != 0) {
|
||||
gap = alignment - rem;
|
||||
if (gap > avail)
|
||||
continue; /* Next aligned address isn't in this block anymore */
|
||||
|
||||
cptr += gap;
|
||||
avail -= gap;
|
||||
}
|
||||
|
||||
if (avail >= len) {
|
||||
if (gap > sizeof(struct memblock)) {
|
||||
/* The alignment gap is big enough to fit another block.
|
||||
* The original block descriptor is already at the correct
|
||||
* position, so we just change its len and create a new block
|
||||
* descriptor for the actual block we're handling. */
|
||||
block->len = gap - sizeof(struct memblock);
|
||||
struct memblock *newblock = (struct memblock *) (cptr - sizeof(struct memblock));
|
||||
newblock->prev = block;
|
||||
newblock->next = block->next;
|
||||
block->next = newblock;
|
||||
newblock->flags = 0;
|
||||
newblock->len = len;
|
||||
block = newblock;
|
||||
}
|
||||
else {
|
||||
/* The gap is too small to fit another block descriptor, so we
|
||||
* must account for the gap length in the block length. */
|
||||
block->len = len + gap;
|
||||
}
|
||||
|
||||
if (avail > len + sizeof(struct memblock)) {
|
||||
/* Imperfect fit, so create another block for the remaining part */
|
||||
struct memblock *newblock = (struct memblock *) (cptr + len);
|
||||
newblock->prev = block;
|
||||
newblock->next = block->next;
|
||||
block->next = newblock;
|
||||
if (newblock->next)
|
||||
newblock->next->prev = newblock;
|
||||
newblock->flags = 0;
|
||||
newblock->len = avail - len - sizeof(struct memblock);
|
||||
}
|
||||
else {
|
||||
/* If this block was larger than the requested length, but only
|
||||
* by less than sizeof(struct memblock), we may have wasted
|
||||
* memory by previous assignments to block->len. */
|
||||
block->len = avail;
|
||||
}
|
||||
|
||||
block->flags |= MEMBLOCK_USED;
|
||||
|
||||
return (void *) cptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* No suitable block found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int memory_managed_free(struct memtype *m, void *ptr, size_t len)
|
||||
{
|
||||
struct memblock *first = (struct memblock *) m->_vd;
|
||||
struct memblock *block;
|
||||
char *cptr = ptr;
|
||||
|
||||
for (block = first; block != NULL; block = block->next) {
|
||||
if (!(block->flags & MEMBLOCK_USED))
|
||||
continue;
|
||||
|
||||
/* Since we may waste some memory at the start of a block to ensure
|
||||
* alignment, ptr may not actually be the start of the block */
|
||||
if ((char *) block + sizeof(struct memblock) <= cptr &&
|
||||
cptr < (char *) block + sizeof(struct memblock) + block->len) {
|
||||
/* Try to merge it with neighbouring free blocks */
|
||||
if (block->prev && !(block->prev->flags & MEMBLOCK_USED) &&
|
||||
block->next && !(block->next->flags & MEMBLOCK_USED)) {
|
||||
/* Special case first: both previous and next block are unused */
|
||||
block->prev->len += block->len + block->next->len + 2 * sizeof(struct memblock);
|
||||
block->prev->next = block->next->next;
|
||||
if (block->next->next)
|
||||
block->next->next->prev = block->prev;
|
||||
}
|
||||
else if (block->prev && !(block->prev->flags & MEMBLOCK_USED)) {
|
||||
block->prev->len += block->len + sizeof(struct memblock);
|
||||
block->prev->next = block->next;
|
||||
if (block->next)
|
||||
block->next->prev = block->prev;
|
||||
}
|
||||
else if (block->next && !(block->next->flags & MEMBLOCK_USED)) {
|
||||
block->len += block->next->len + sizeof(struct memblock);
|
||||
block->next = block->next->next;
|
||||
if (block->next)
|
||||
block->next->prev = block;
|
||||
}
|
||||
else {
|
||||
/* no neighbouring free block, so just mark it as free */
|
||||
block->flags &= ~MEMBLOCK_USED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct memtype * memtype_managed_init(void *ptr, size_t len)
|
||||
{
|
||||
struct memtype *mt = ptr;
|
||||
struct memblock *mb;
|
||||
char *cptr = ptr;
|
||||
|
||||
if (len < sizeof(struct memtype) + sizeof(struct memblock)) {
|
||||
info("memtype_managed_init: passed region too small");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize memtype */
|
||||
mt->name = "managed";
|
||||
mt->flags = 0;
|
||||
mt->alloc = memory_managed_alloc;
|
||||
mt->free = memory_managed_free;
|
||||
mt->alignment = 1;
|
||||
|
||||
cptr += ALIGN(sizeof(struct memtype), sizeof(void *));
|
||||
|
||||
/* Initialize first free memblock */
|
||||
mb = (struct memblock *) cptr;
|
||||
mb->prev = NULL;
|
||||
mb->next = NULL;
|
||||
mb->flags = 0;
|
||||
|
||||
cptr += ALIGN(sizeof(struct memblock), sizeof(void *));
|
||||
|
||||
mb->len = len - (cptr - (char *) ptr);
|
||||
|
||||
mt->_vd = (void *) mb;
|
||||
|
||||
return mt;
|
||||
}
|
||||
|
||||
/* List of available memory types */
|
||||
struct memtype memtype_heap = {
|
||||
.name = "heap",
|
||||
.flags = MEMORY_HEAP,
|
||||
.alloc = memory_heap_alloc,
|
||||
.free = memory_heap_free,
|
||||
.alignment = 1
|
||||
};
|
||||
|
||||
struct memtype memtype_hugepage = {
|
||||
.name = "mmap_hugepages",
|
||||
.flags = MEMORY_MMAP | MEMORY_HUGEPAGE,
|
||||
.alloc = memory_hugepage_alloc,
|
||||
.free = memory_hugepage_free,
|
||||
.alignment = 21 /* 2 MiB hugepage */
|
||||
};
|
||||
|
|
67
lib/memory/heap.c
Normal file
67
lib/memory/heap.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/** Memory allocators.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <villas/utils.h>
|
||||
#include <villas/memory.h>
|
||||
|
||||
static struct memory_allocation * memory_heap_alloc(struct memory_type *m, size_t len, size_t alignment)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct memory_allocation *ma = alloc(sizeof(struct memory_allocation));
|
||||
if (!ma)
|
||||
return NULL;
|
||||
|
||||
ma->alignment = alignment;
|
||||
ma->type = m;
|
||||
ma->length = len;
|
||||
|
||||
if (ma->alignment < sizeof(void *))
|
||||
ma->alignment = sizeof(void *);
|
||||
|
||||
ret = posix_memalign(&ma->address, ma->alignment, ma->length);
|
||||
if (ret) {
|
||||
free(ma);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ma;
|
||||
}
|
||||
|
||||
static int memory_heap_free(struct memory_type *m, struct memory_allocation *ma)
|
||||
{
|
||||
free(ma->address);
|
||||
free(ma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* List of available memory types */
|
||||
struct memory_type memory_type_heap = {
|
||||
.name = "heap",
|
||||
.flags = MEMORY_HEAP,
|
||||
.alloc = memory_heap_alloc,
|
||||
.free = memory_heap_free,
|
||||
.alignment = 1
|
||||
};
|
101
lib/memory/hugepage.c
Normal file
101
lib/memory/hugepage.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/** Hugepage memory allocator.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Required to allocate hugepages on Apple OS X */
|
||||
#ifdef __MACH__
|
||||
#include <mach/vm_statistics.h>
|
||||
#elif defined(__linux__)
|
||||
#include <villas/kernel/kernel.h>
|
||||
#endif
|
||||
|
||||
#include <villas/log.h>
|
||||
#include <villas/memory.h>
|
||||
#include <villas/utils.h>
|
||||
|
||||
#define HUGEPAGESIZE (1 << 22) /* 2 MiB */
|
||||
|
||||
/** Allocate memory backed by hugepages with malloc() like interface */
|
||||
static struct memory_allocation * memory_hugepage_alloc(struct memory_type *m, size_t len, size_t alignment)
|
||||
{
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
|
||||
#ifdef __MACH__
|
||||
flags |= VM_FLAGS_SUPERPAGE_SIZE_2MB;
|
||||
#elif defined(__linux__)
|
||||
flags |= MAP_HUGETLB;
|
||||
|
||||
if (getuid() == 0)
|
||||
flags |= MAP_LOCKED;
|
||||
#endif
|
||||
|
||||
struct memory_allocation *ma = alloc(sizeof(struct memory_allocation));
|
||||
if (!ma)
|
||||
return NULL;
|
||||
|
||||
/** We must make sure that len is a multiple of the hugepage size
|
||||
*
|
||||
* See: https://lkml.org/lkml/2014/10/22/925
|
||||
*/
|
||||
ma->length = ALIGN(len, HUGEPAGESIZE);
|
||||
ma->alignment = alignment;
|
||||
ma->type = m;
|
||||
|
||||
ma->address = mmap(NULL, len, prot, flags, -1, 0);
|
||||
if (ma->address == MAP_FAILED) {
|
||||
free(ma);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ma;
|
||||
}
|
||||
|
||||
static int memory_hugepage_free(struct memory_type *m, struct memory_allocation *ma)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = munmap(ma->address, ma->length);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
free(ma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct memory_type memory_hugepage = {
|
||||
.name = "mmap_hugepages",
|
||||
.flags = MEMORY_MMAP | MEMORY_HUGEPAGE,
|
||||
.alloc = memory_hugepage_alloc,
|
||||
.free = memory_hugepage_free,
|
||||
.alignment = 21 /* 2 MiB hugepage */
|
||||
};
|
|
@ -21,9 +21,15 @@
|
|||
*********************************************************************************/
|
||||
|
||||
#include <villas/nodes/infiniband.h>
|
||||
#include <villas/memory_ib.h>
|
||||
#include <villas/memory.h>
|
||||
#include <villas/utils.h>
|
||||
#include <rdma/rdma_cma.h>
|
||||
|
||||
struct memory_ib {
|
||||
struct ibv_pd *pd;
|
||||
struct memory_type *parent;
|
||||
};
|
||||
|
||||
struct ibv_mr * memory_ib_mr(void *ptr)
|
||||
{
|
||||
struct ibv_mr *mr = (struct ibv_mr *) ptr;
|
||||
|
@ -31,41 +37,51 @@ struct ibv_mr * memory_ib_mr(void *ptr)
|
|||
return (mr - 1);
|
||||
}
|
||||
|
||||
void * memory_ib_alloc(struct memtype *m, size_t len, size_t alignment)
|
||||
static struct memory_allocation * memory_ib_alloc(struct memory_type *m, size_t len, size_t alignment)
|
||||
{
|
||||
struct memory_ib *mi = (struct memory_ib *) m->_vd;
|
||||
|
||||
struct ibv_mr **mr = memory_alloc_aligned(mi->parent, len + sizeof(struct ibv_mr *), alignment);
|
||||
char *ptr = (char *) (mr + 1);
|
||||
struct memory_allocation *ma = alloc(sizeof(struct memory_allocation));
|
||||
if (!ma)
|
||||
return NULL;
|
||||
|
||||
*mr = ibv_reg_mr(mi->pd, ptr, len, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE);
|
||||
if(!*mr) {
|
||||
free(ptr);
|
||||
ma->type = m;
|
||||
ma->length = len;
|
||||
ma->alignment = alignment;
|
||||
|
||||
ma->parent = mi->parent->alloc(mi->parent, len + sizeof(struct ibv_mr *), alignment);
|
||||
ma->address = ma->parent->address;
|
||||
|
||||
ma->ib.mr = ibv_reg_mr(mi->pd, ma->address, ma->length, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE);
|
||||
if(!ma->ib.mr) {
|
||||
mi->parent->free(mi->parent, ma->parent);
|
||||
free(ma);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return ma;
|
||||
}
|
||||
|
||||
int memory_ib_free(struct memtype *m, void *ptr, size_t len)
|
||||
static int memory_ib_free(struct memory_type *m, struct memory_allocation *ma)
|
||||
{
|
||||
int ret;
|
||||
struct memory_ib *mi = (struct memory_ib *) m->_vd;
|
||||
struct ibv_mr *mr = memory_ib_mr(ptr);
|
||||
|
||||
ibv_dereg_mr(mr);
|
||||
ibv_dereg_mr(ma->ib.mr);
|
||||
|
||||
ptr -= sizeof(struct ibv_mr *);
|
||||
len += sizeof(struct ibv_mr *);
|
||||
ret = mi->parent->free(mi->parent, ma->parent);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memory_free(mi->parent, ptr, len);
|
||||
free(ma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct memtype * ib_memtype(struct node *n, struct memtype *parent)
|
||||
struct memory_type * memory_ib(struct node *n, struct memory_type *parent)
|
||||
{
|
||||
struct infiniband *i = (struct infiniband *) n->_vd;
|
||||
struct memtype *mt = malloc(sizeof(struct memtype));
|
||||
struct memory_type *mt = malloc(sizeof(struct memory_type));
|
||||
|
||||
mt->name = "ib";
|
||||
mt->flags = 0;
|
193
lib/memory/managed.c
Normal file
193
lib/memory/managed.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/** Memory allocators.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <villas/log.h>
|
||||
#include <villas/memory.h>
|
||||
#include <villas/utils.h>
|
||||
|
||||
static struct memory_allocation * memory_managed_alloc(struct memory_type *m, size_t len, size_t alignment)
|
||||
{
|
||||
/* Simple first-fit allocation */
|
||||
struct memory_block *first = (struct memory_block *) m->_vd;
|
||||
struct memory_block *block;
|
||||
|
||||
for (block = first; block != NULL; block = block->next) {
|
||||
if (block->used)
|
||||
continue;
|
||||
|
||||
char* cptr = (char *) block + sizeof(struct memory_block);
|
||||
size_t avail = block->length;
|
||||
uintptr_t uptr = (uintptr_t) cptr;
|
||||
|
||||
/* Check alignment first; leave a gap at start of block to assure
|
||||
* alignment if necessary */
|
||||
uintptr_t rem = uptr % alignment;
|
||||
uintptr_t gap = 0;
|
||||
if (rem != 0) {
|
||||
gap = alignment - rem;
|
||||
if (gap > avail)
|
||||
continue; /* Next aligned address isn't in this block anymore */
|
||||
|
||||
cptr += gap;
|
||||
avail -= gap;
|
||||
}
|
||||
|
||||
if (avail >= len) {
|
||||
if (gap > sizeof(struct memory_block)) {
|
||||
/* The alignment gap is big enough to fit another block.
|
||||
* The original block descriptor is already at the correct
|
||||
* position, so we just change its len and create a new block
|
||||
* descriptor for the actual block we're handling. */
|
||||
block->length = gap - sizeof(struct memory_block);
|
||||
struct memory_block *newblock = (struct memory_block *) (cptr - sizeof(struct memory_block));
|
||||
newblock->prev = block;
|
||||
newblock->next = block->next;
|
||||
block->next = newblock;
|
||||
newblock->used = false;
|
||||
newblock->length = len;
|
||||
block = newblock;
|
||||
}
|
||||
else {
|
||||
/* The gap is too small to fit another block descriptor, so we
|
||||
* must account for the gap length in the block length. */
|
||||
block->length = len + gap;
|
||||
}
|
||||
|
||||
if (avail > len + sizeof(struct memory_block)) {
|
||||
/* Imperfect fit, so create another block for the remaining part */
|
||||
struct memory_block *newblock = (struct memory_block *) (cptr + len);
|
||||
newblock->prev = block;
|
||||
newblock->next = block->next;
|
||||
block->next = newblock;
|
||||
|
||||
if (newblock->next)
|
||||
newblock->next->prev = newblock;
|
||||
|
||||
newblock->used = false;
|
||||
newblock->length = avail - len - sizeof(struct memory_block);
|
||||
}
|
||||
else {
|
||||
/* If this block was larger than the requested length, but only
|
||||
* by less than sizeof(struct memory_block), we may have wasted
|
||||
* memory by previous assignments to block->length. */
|
||||
block->length = avail;
|
||||
}
|
||||
|
||||
block->used = true;
|
||||
|
||||
struct memory_allocation *ma = alloc(sizeof(struct memory_allocation));
|
||||
if (!ma)
|
||||
return NULL;
|
||||
|
||||
ma->address = cptr;
|
||||
ma->type = m;
|
||||
ma->alignment = alignment;
|
||||
ma->length = len;
|
||||
ma->managed.block = block;
|
||||
|
||||
return ma;
|
||||
}
|
||||
}
|
||||
|
||||
/* No suitable block found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int memory_managed_free(struct memory_type *m, struct memory_allocation *ma)
|
||||
{
|
||||
struct memory_block *block = ma->managed.block;
|
||||
|
||||
/* Try to merge it with neighbouring free blocks */
|
||||
if (block->prev && !block->prev->used &&
|
||||
block->next && !block->next->used) {
|
||||
/* Special case first: both previous and next block are unused */
|
||||
block->prev->length += block->length + block->next->length + 2 * sizeof(struct memory_block);
|
||||
block->prev->next = block->next->next;
|
||||
if (block->next->next)
|
||||
block->next->next->prev = block->prev;
|
||||
}
|
||||
else if (block->prev && !block->prev->used) {
|
||||
block->prev->length += block->length + sizeof(struct memory_block);
|
||||
block->prev->next = block->next;
|
||||
if (block->next)
|
||||
block->next->prev = block->prev;
|
||||
}
|
||||
else if (block->next && !block->next->used) {
|
||||
block->length += block->next->length + sizeof(struct memory_block);
|
||||
block->next = block->next->next;
|
||||
if (block->next)
|
||||
block->next->prev = block;
|
||||
}
|
||||
else {
|
||||
/* no neighbouring free block, so just mark it as free */
|
||||
block->used = false;
|
||||
}
|
||||
|
||||
free(ma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct memory_type * memory_managed(void *ptr, size_t len)
|
||||
{
|
||||
struct memory_type *mt = ptr;
|
||||
struct memory_block *mb;
|
||||
char *cptr = ptr;
|
||||
|
||||
if (len < sizeof(struct memory_type) + sizeof(struct memory_block)) {
|
||||
info("memory_managed: passed region too small");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize memory_type */
|
||||
mt->name = "managed";
|
||||
mt->flags = 0;
|
||||
mt->alloc = memory_managed_alloc;
|
||||
mt->free = memory_managed_free;
|
||||
mt->alignment = 1;
|
||||
|
||||
cptr += ALIGN(sizeof(struct memory_type), sizeof(void *));
|
||||
|
||||
/* Initialize first free memory block */
|
||||
mb = (struct memory_block *) cptr;
|
||||
mb->prev = NULL;
|
||||
mb->next = NULL;
|
||||
mb->used = false;
|
||||
|
||||
cptr += ALIGN(sizeof(struct memory_block), sizeof(void *));
|
||||
|
||||
mb->length = len - (cptr - (char *) ptr);
|
||||
|
||||
mt->_vd = (void *) mb;
|
||||
|
||||
return mt;
|
||||
}
|
|
@ -309,6 +309,10 @@ int node_check(struct node *n)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = n->_vt->check ? n->_vt->check(n) : 0;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
n->state = STATE_CHECKED;
|
||||
|
||||
return 0;
|
||||
|
@ -545,9 +549,9 @@ int node_fd(struct node *n)
|
|||
return n->_vt->fd ? n->_vt->fd(n) : -1;
|
||||
}
|
||||
|
||||
struct memtype * node_memtype(struct node *n, struct memtype *parent)
|
||||
struct memory_type * node_memory_type(struct node *n, struct memory_type *parent)
|
||||
{
|
||||
return n->_vt->memtype(n, parent) ? n->_vt->memtype(n, parent) : &memtype_hugepage;
|
||||
return n->_vt->memory_type ? n->_vt->memory_type(n, parent) : &memory_hugepage;
|
||||
}
|
||||
|
||||
int node_parse_list(struct list *list, json_t *cfg, struct list *all)
|
||||
|
|
|
@ -159,6 +159,7 @@ endif
|
|||
# Enable Infiniband support
|
||||
ifeq ($(WITH_NODE_INFINIBAND),1)
|
||||
LIB_SRCS += lib/nodes/infiniband.c
|
||||
LIB_SRCS += lib/memory/ib.c
|
||||
LIB_NODES += infiniband
|
||||
LIB_LDLIBS += -libverbs
|
||||
LIB_LDLIBS += -lrdmacm
|
||||
|
|
|
@ -294,11 +294,11 @@ int iec61850_sv_start(struct node *n)
|
|||
SVReceiver_addSubscriber(i->subscriber.receiver, i->subscriber.subscriber);
|
||||
|
||||
/* Initialize pool and queue to pass samples between threads */
|
||||
ret = pool_init(&i->subscriber.pool, 1024, SAMPLE_LEN(n->samplelen), &memtype_hugepage);
|
||||
ret = pool_init(&i->subscriber.pool, 1024, SAMPLE_LEN(n->samplelen), &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = queue_signalled_init(&i->subscriber.queue, 1024, &memtype_hugepage, 0);
|
||||
ret = queue_signalled_init(&i->subscriber.queue, 1024, &memory_hugepage, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <villas/format_type.h>
|
||||
#include <villas/memory.h>
|
||||
#include <villas/pool.h>
|
||||
#include <villas/memory_ib.h>
|
||||
#include <villas/memory.h>
|
||||
|
||||
#include <rdma/rdma_cma.h>
|
||||
|
||||
|
@ -239,7 +239,7 @@ static void ib_build_ibv(struct node *n)
|
|||
pool_init(&ib->mem.p_recv,
|
||||
ib->qp_init.cap.max_recv_wr,
|
||||
SAMPLE_DATA_LEN(DEFAULT_SAMPLELEN),
|
||||
&memtype_heap);
|
||||
&memory_type_heap);
|
||||
if(ret)
|
||||
{
|
||||
error("Failed to init recv memory pool of node %s: %s",
|
||||
|
@ -270,7 +270,7 @@ static void ib_build_ibv(struct node *n)
|
|||
pool_init(&ib->mem.p_send,
|
||||
ib->qp_init.cap.max_send_wr,
|
||||
sizeof(double),
|
||||
&memtype_heap);
|
||||
&memory_type_heap);
|
||||
if(ret)
|
||||
{
|
||||
error("Failed to init send memory of node %s: %s",
|
||||
|
@ -840,7 +840,7 @@ static struct plugin p = {
|
|||
.read = ib_read,
|
||||
.write = ib_write,
|
||||
.fd = ib_fd,
|
||||
.memtype = ib_memtype
|
||||
.memory_type = memory_ib
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -50,11 +50,11 @@ int loopback_open(struct node *n)
|
|||
int ret;
|
||||
struct loopback *l = (struct loopback *) n->_vd;
|
||||
|
||||
ret = pool_init(&l->pool, l->queuelen, SAMPLE_LEN(n->samplelen), &memtype_hugepage);
|
||||
ret = pool_init(&l->pool, l->queuelen, SAMPLE_LEN(n->samplelen), &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return queue_signalled_init(&l->queue, l->queuelen, &memtype_hugepage, QUEUE_SIGNALLED_EVENTFD);
|
||||
return queue_signalled_init(&l->queue, l->queuelen, &memory_hugepage, QUEUE_SIGNALLED_EVENTFD);
|
||||
}
|
||||
|
||||
int loopback_close(struct node *n)
|
||||
|
|
|
@ -301,11 +301,11 @@ int mqtt_start(struct node *n)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pool_init(&m->pool, 1024, SAMPLE_LEN(n->samplelen), &memtype_hugepage);
|
||||
ret = pool_init(&m->pool, 1024, SAMPLE_LEN(n->samplelen), &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = queue_signalled_init(&m->queue, 1024, &memtype_hugepage, 0);
|
||||
ret = queue_signalled_init(&m->queue, 1024, &memory_hugepage, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ static int websocket_connection_init(struct websocket_connection *c)
|
|||
|
||||
c->_name = NULL;
|
||||
|
||||
ret = queue_init(&c->queue, DEFAULT_QUEUELEN, &memtype_hugepage);
|
||||
ret = queue_init(&c->queue, DEFAULT_QUEUELEN, &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -400,11 +400,11 @@ int websocket_start(struct node *n)
|
|||
int ret;
|
||||
struct websocket *w = (struct websocket *) n->_vd;
|
||||
|
||||
ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUELEN, SAMPLE_LEN(DEFAULT_WEBSOCKET_SAMPLELEN), &memtype_hugepage);
|
||||
ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUELEN, SAMPLE_LEN(DEFAULT_WEBSOCKET_SAMPLELEN), &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = queue_signalled_init(&w->queue, DEFAULT_WEBSOCKET_QUEUELEN, &memtype_hugepage, 0);
|
||||
ret = queue_signalled_init(&w->queue, DEFAULT_WEBSOCKET_QUEUELEN, &memory_hugepage, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ static int path_source_init(struct path_source *ps)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = pool_init(&ps->pool, MAX(DEFAULT_QUEUELEN, ps->node->in.vectorize), SAMPLE_LEN(ps->node->samplelen), &memtype_hugepage);
|
||||
ret = pool_init(&ps->pool, MAX(DEFAULT_QUEUELEN, ps->node->in.vectorize), SAMPLE_LEN(ps->node->samplelen), &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -148,7 +148,7 @@ static int path_destination_init(struct path_destination *pd, int queuelen)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = queue_init(&pd->queue, queuelen, &memtype_hugepage);
|
||||
ret = queue_init(&pd->queue, queuelen, &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -430,7 +430,7 @@ int path_init2(struct path *p)
|
|||
if (!p->samplelen)
|
||||
p->samplelen = DEFAULT_SAMPLELEN;
|
||||
|
||||
ret = pool_init(&p->pool, MAX(1, list_length(&p->destinations)) * p->queuelen, SAMPLE_LEN(p->samplelen), &memtype_hugepage);
|
||||
ret = pool_init(&p->pool, MAX(1, list_length(&p->destinations)) * p->queuelen, SAMPLE_LEN(p->samplelen), &memory_hugepage);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <villas/memory.h>
|
||||
#include <villas/kernel/kernel.h>
|
||||
|
||||
int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memtype *m)
|
||||
int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memory_type *m)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -35,7 +35,6 @@ int pool_init(struct pool *p, size_t cnt, size_t blocksz, struct memtype *m)
|
|||
p->alignment = kernel_get_cacheline_size();
|
||||
p->blocksz = p->alignment * CEIL(blocksz, p->alignment);
|
||||
p->len = cnt * p->blocksz;
|
||||
p->mem = m;
|
||||
|
||||
void *buffer = memory_alloc_aligned(m, p->len, p->alignment);
|
||||
if (!buffer)
|
||||
|
@ -66,7 +65,7 @@ int pool_destroy(struct pool *p)
|
|||
queue_destroy(&p->queue);
|
||||
|
||||
void *buffer = (char*) p + p->buffer_off;
|
||||
ret = memory_free(p->mem, buffer, p->len);
|
||||
ret = memory_free(buffer);
|
||||
if (ret == 0)
|
||||
p->state = STATE_DESTROYED;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <villas/memory.h>
|
||||
|
||||
/** Initialize MPMC queue */
|
||||
int queue_init(struct queue *q, size_t size, struct memtype *mem)
|
||||
int queue_init(struct queue *q, size_t size, struct memory_type *m)
|
||||
{
|
||||
assert(q->state == STATE_DESTROYED);
|
||||
|
||||
|
@ -47,9 +47,8 @@ int queue_init(struct queue *q, size_t size, struct memtype *mem)
|
|||
warn("A queue size was changed from %lu to %lu", old_size, size);
|
||||
}
|
||||
|
||||
q->mem = mem;
|
||||
q->buffer_mask = size - 1;
|
||||
struct queue_cell *buffer = (struct queue_cell *) memory_alloc(q->mem, sizeof(struct queue_cell) * size);
|
||||
struct queue_cell *buffer = (struct queue_cell *) memory_alloc(m, sizeof(struct queue_cell) * size);
|
||||
if (!buffer)
|
||||
return -2;
|
||||
|
||||
|
@ -74,8 +73,7 @@ int queue_destroy(struct queue *q)
|
|||
if (q->state == STATE_DESTROYED)
|
||||
return 0;
|
||||
|
||||
ret = memory_free(q->mem, buffer, (q->buffer_mask + 1) * sizeof(struct queue_cell));
|
||||
|
||||
ret = memory_free(buffer);
|
||||
if (ret == 0)
|
||||
q->state = STATE_DESTROYED;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static void queue_signalled_cleanup(void *p)
|
|||
pthread_mutex_unlock(&qs->pthread.mutex);
|
||||
}
|
||||
|
||||
int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memtype *mem, int flags)
|
||||
int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_type *mem, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
12
lib/shmem.c
12
lib/shmem.c
|
@ -35,8 +35,8 @@
|
|||
|
||||
size_t shmem_total_size(int queuelen, int samplelen)
|
||||
{
|
||||
/* We have the constant const of the memtype header */
|
||||
return sizeof(struct memtype)
|
||||
/* We have the constant const of the memory_type header */
|
||||
return sizeof(struct memory_type)
|
||||
/* and the shared struct itself */
|
||||
+ sizeof(struct shmem_shared)
|
||||
/* the size of the actual queue and the queue for the pool */
|
||||
|
@ -44,7 +44,7 @@ size_t shmem_total_size(int queuelen, int samplelen)
|
|||
/* the size of the pool */
|
||||
+ queuelen * kernel_get_cacheline_size() * CEIL(SAMPLE_LEN(samplelen), kernel_get_cacheline_size())
|
||||
/* a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) */
|
||||
+ 4 * sizeof(struct memblock)
|
||||
+ 4 * sizeof(struct memory_block)
|
||||
/* and some extra buffer for alignment */
|
||||
+ 1024;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ int shmem_int_open(const char *wname, const char* rname, struct shmem_int *shm,
|
|||
int fd, ret;
|
||||
size_t len;
|
||||
void *base;
|
||||
struct memtype *manager;
|
||||
struct memory_type *manager;
|
||||
struct shmem_shared *shared;
|
||||
struct stat stat_buf;
|
||||
sem_t *sem_own, *sem_other;
|
||||
|
@ -92,7 +92,7 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600);
|
|||
|
||||
close(fd);
|
||||
|
||||
manager = memtype_managed_init(base, len);
|
||||
manager = memory_managed(base, len);
|
||||
shared = memory_alloc(manager, sizeof(struct shmem_shared));
|
||||
if (!shared) {
|
||||
errno = ENOMEM;
|
||||
|
@ -144,7 +144,7 @@ retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600);
|
|||
if (base == MAP_FAILED)
|
||||
return -10;
|
||||
|
||||
cptr = (char *) base + sizeof(struct memtype) + sizeof(struct memblock);
|
||||
cptr = (char *) base + sizeof(struct memory_type) + sizeof(struct memory_block);
|
||||
shared = (struct shmem_shared *) cptr;
|
||||
shm->read.base = base;
|
||||
shm->read.name = rname;
|
||||
|
|
|
@ -78,7 +78,7 @@ RUN dnf -y install \
|
|||
libiec61850-devel \
|
||||
librabbitmq-devel \
|
||||
mosquitto-devel \
|
||||
comedilib-devel
|
||||
comedilib-devel comedilib
|
||||
|
||||
# IB Verbs Dependencies
|
||||
RUN dnf -y install \
|
||||
|
|
|
@ -14,7 +14,7 @@ BuildRequires: gcc pkgconfig make
|
|||
|
||||
Requires: iproute module-init-tools
|
||||
|
||||
BuildRequires: openssl-devel libconfig-devel libnl3-devel libcurl-devel jansson-devel libwebsockets-devel zeromq-devel nanomsg-devel libiec61850-devel librabbitmq-devel mosquitto-devel comedilib-devel
|
||||
BuildRequires: openssl-devel libconfig-devel libnl3-devel libcurl-devel jansson-devel libwebsockets-devel zeromq-devel nanomsg-devel libiec61850-devel librabbitmq-devel mosquitto-devel comedilib-devel comedilib
|
||||
Requires: openssl libconfig libnl3 libcurl jansson libwebsockets zeromq nanomsg libiec61850 librabbitmq mosquitto comedilib
|
||||
|
||||
%description
|
||||
|
|
|
@ -182,7 +182,7 @@ check: if (optarg == endptr)
|
|||
|
||||
smps = alloc(cnt * sizeof(struct sample *));
|
||||
|
||||
ret = pool_init(&q, 10 * cnt, SAMPLE_LEN(DEFAULT_SAMPLELEN), &memtype_hugepage);
|
||||
ret = pool_init(&q, 10 * cnt, SAMPLE_LEN(DEFAULT_SAMPLELEN), &memory_hugepage);
|
||||
if (ret)
|
||||
error("Failed to initilize memory pool");
|
||||
|
||||
|
|
|
@ -132,7 +132,8 @@ static void * send_loop(void *ctx)
|
|||
struct sample *smps[node->out.vectorize];
|
||||
|
||||
/* Initialize memory */
|
||||
ret = pool_init(&sendd.pool, MAX(16384, 2*LOG2_CEIL(node->out.vectorize)), SAMPLE_LEN(DEFAULT_SAMPLELEN), node_memtype(node, &memtype_heap));
|
||||
ret = pool_init(&sendd.pool, MAX(16384, 2*LOG2_CEIL(node->out.vectorize)), SAMPLE_LEN(DEFAULT_SAMPLELEN), node_memory_type(node, &memory_type_heap));
|
||||
|
||||
if (ret < 0)
|
||||
error("Failed to allocate memory for receive pool.");
|
||||
|
||||
|
@ -196,7 +197,7 @@ static void * recv_loop(void *ctx)
|
|||
struct sample *smps[node->in.vectorize];
|
||||
|
||||
/* Initialize memory */
|
||||
ret = pool_init(&recvv.pool, MAX(16*8192, 2*LOG2_CEIL(node->in.vectorize)), SAMPLE_LEN(DEFAULT_SAMPLELEN), node_memtype(node, &memtype_heap));
|
||||
ret = pool_init(&recvv.pool, MAX(16*8192, 2*LOG2_CEIL(node->in.vectorize)), SAMPLE_LEN(DEFAULT_SAMPLELEN), node_memory_type(node, &memory_type_heap));
|
||||
|
||||
if (ret < 0)
|
||||
error("Failed to allocate memory for receive pool.");
|
||||
|
|
|
@ -155,7 +155,7 @@ int main(int argc, char *argv[])
|
|||
if (ret)
|
||||
error("Failed to verify node configuration");
|
||||
|
||||
ret = pool_init(&q, 16, SAMPLE_LEN(n.samplelen), &memtype_heap);
|
||||
ret = pool_init(&q, 16, SAMPLE_LEN(n.samplelen), &memory_type_heap);
|
||||
if (ret)
|
||||
error("Failed to initialize pool");
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue