1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

replaced linked list by dynamic array (closes #6)

This commit is contained in:
Steffen Vogel 2015-10-09 12:50:35 +02:00
parent 7b94198158
commit 9439a88877
8 changed files with 127 additions and 177 deletions

View file

@ -14,83 +14,62 @@
#include <pthread.h>
/* Forward declarations */
struct list_elm;
struct node;
struct path;
struct interface;
struct socket;
struct gtfpga;
struct opal;
#define LIST_CHUNKSIZE 16
/** Static list initialization */
#define LIST_INIT(dtor) { \
.head = NULL, \
.tail = NULL, \
.length = 0, \
.lock = PTHREAD_MUTEX_INITIALIZER, \
.destructor = dtor \
#define LIST_INIT(dtor) { \
.start = NULL, \
.end = NULL, \
.length = 0, \
.capacity = 0, \
.lock = PTHREAD_MUTEX_INITIALIZER, \
.destructor = dtor \
}
#define FOREACH(list, elm) \
for ( struct list_elm *elm = (list)->head; \
elm; elm = elm->next )
#define FOREACH_R(list, elm) \
for ( struct list_elm *elm = (list)->tail; \
elm; elm = elm->prev )
#define list_first(list) ((list)->head)
#define list_last(list) ((list)->head)
#define list_length(list) ((list)->length)
#define list_at(list, index) ((list)->length > index ? (list)->start[index] : NULL)
#define list_first(list) list_at(list, 0)
#define list_last(list) list_at(list, (list)->length-1)
#define list_foreach(ptr, list) for (int _i = 0, _p; _p = 1, _i < (list)->length; _i++) \
for (ptr = (list)->start[_i]; _p--; )
/** Callback to destroy list elements.
*
* @param data A pointer to the data which should be freed.
*/
typedef void (*dtor_cb_t)(void *data);
typedef int (*cmp_cb_t)(void *, void *);
typedef void (*dtor_cb_t)(void *);
/** Callback to search or sort a list. */
typedef int (*cmp_cb_t)(const void *, const void *);
struct list {
struct list_elm *head, *tail;
int length;
dtor_cb_t destructor;
pthread_mutex_t lock;
};
struct list_elm {
union {
void *ptr;
struct node *node;
struct node_type *type;
struct path *path;
struct interface *interface;
struct socket *socket;
struct opal *opal;
struct gtfpga *gtfpga;
struct hook *hook;
} /* anonymous */;
int priority;
struct list_elm *prev, *next;
void **start; /**< Array of pointers to list elements */
void **end; /**< Array of pointers to list elements */
size_t capacity; /**< Size of list::start in elements */
size_t length; /**< Number of elements of list::start which are in use */
dtor_cb_t destructor; /**< A destructor which gets called for every list elements during list_destroy() */
pthread_mutex_t lock; /**< A mutex to allow thread-safe accesses */
};
/** Initialize a list */
void list_init(struct list *l, dtor_cb_t dtor);
/** Destroy a list and call destructors for all list elements */
void list_destroy(struct list *l);
/** Append an element to the end of the list */
void list_push(struct list *l, void *p);
void list_insert(struct list *l, int prio, void *p);
/** Search the list for an element whose first element is a character array which matches name.
*
* @see Only possible because of §1424 of http://c0x.coding-guidelines.com/6.7.2.1.html
*/
void * list_lookup(const struct list *l, const char *name);
void * list_lookup(struct list *l, const char *name);
void * list_search(const struct list *l, cmp_cb_t cmp, void *ctx);
void * list_search(struct list *l, cmp_cb_t cmp, void *ctx);
/** Sort the list using the quicksort algorithm of libc */
void list_sort(struct list *l, cmp_cb_t cmp);
#endif /* _LIST_H_ */

View file

@ -117,7 +117,7 @@ int config_parse_path(config_setting_t *cfg,
config_parse_nodelist(cfg_out, &p->destinations, nodes);
if (list_length(&p->destinations) >= 1)
p->out = list_first(&p->destinations)->node;
p->out = (struct node *) list_first(&p->destinations);
else
cerror(cfg, "Missing output node for path");
@ -141,9 +141,9 @@ int config_parse_path(config_setting_t *cfg,
p->in->refcnt++;
p->in->vt->refcnt++;
FOREACH(&p->destinations, it) {
it->node->refcnt++;
it->node->vt->refcnt++;
list_foreach(struct node *node, &p->destinations) {
node->refcnt++;
node->vt->refcnt++;
}
if (reverse) {

View file

@ -58,7 +58,7 @@ void if_destroy(struct interface *i)
int if_start(struct interface *i, int affinity)
{
info("Starting interface '%s' which is used by %u sockets", rtnl_link_get_name(i->nl_link), list_length(&i->sockets));
info("Starting interface '%s' which is used by %zu sockets", rtnl_link_get_name(i->nl_link), list_length(&i->sockets));
{ INDENT
/* Set affinity for network interfaces (skip _loopback_ dev) */
@ -66,8 +66,7 @@ int if_start(struct interface *i, int affinity)
/* Assign fwmark's to socket nodes which have netem options */
int ret, mark = 0;
FOREACH(&i->sockets, it) {
struct socket *s = it->socket;
list_foreach(struct socket *s, &i->sockets) {
if (s->tc_qdisc)
s->mark = 1 + mark++;
}
@ -90,8 +89,7 @@ int if_start(struct interface *i, int affinity)
error("Failed to setup priority queuing discipline: %s", nl_geterror(ret));
/* Create netem qdisks and appropriate filter per netem node */
FOREACH(&i->sockets, it) {
struct socket *s = it->socket;
list_foreach(struct socket *s, &i->sockets) {
if (s->tc_qdisc) {
ret = tc_mark(i, &s->tc_classifier, TC_HANDLE(1, s->mark), s->mark);
if (ret)
@ -210,9 +208,9 @@ int if_set_affinity(struct interface *i, int affinity)
struct interface * if_lookup_index(int index)
{
FOREACH(&interfaces, it) {
if (rtnl_link_get_ifindex(it->interface->nl_link) == index)
return it->interface;
list_foreach(struct interface *i, &interfaces) {
if (rtnl_link_get_ifindex(i->nl_link) == index)
return i;
}
return NULL;

View file

@ -8,9 +8,9 @@
* Unauthorized copying of this file, via any medium is strictly prohibited.
*********************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "list.h"
void list_init(struct list *l, dtor_cb_t dtor)
@ -19,24 +19,28 @@ void list_init(struct list *l, dtor_cb_t dtor)
l->destructor = dtor;
l->length = 0;
l->head = NULL;
l->tail = NULL;
l->capacity = 0;
l->start = NULL;
l->end = NULL;
}
void list_destroy(struct list *l)
{
pthread_mutex_lock(&l->lock);
struct list_elm *elm = l->head;
while (elm) {
struct list_elm *tmp = elm;
elm = elm->next;
if (l->destructor)
l->destructor(tmp->ptr);
free(tmp);
if (l->destructor) {
for (void *e = l->start; e != l->end; e++)
l->destructor(e);
}
free(l->start);
l->start =
l->end = NULL;
l->length =
l->capacity = 0;
pthread_mutex_unlock(&l->lock);
pthread_mutex_destroy(&l->lock);
@ -44,83 +48,54 @@ void list_destroy(struct list *l)
void list_push(struct list *l, void *p)
{
struct list_elm *e = alloc(sizeof(struct list_elm));
pthread_mutex_lock(&l->lock);
e->ptr = p;
e->prev = l->tail;
e->next = NULL;
if (l->tail)
l->tail->next = e;
if (l->head)
l->head->prev = e;
else
l->head = e;
l->tail = e;
/* Resize array if out of capacity */
if (l->end == l->start + l->capacity) {
l->capacity += LIST_CHUNKSIZE;
l->start = realloc(l->start, l->capacity * sizeof(void *));
}
l->start[l->length] = p;
l->length++;
l->end = &l->start[l->length];
pthread_mutex_unlock(&l->lock);
}
void list_insert(struct list *l, int prio, void *p)
void * list_lookup(struct list *l, const char *name)
{
struct list_elm *d;
struct list_elm *e = alloc(sizeof(struct list_elm));
int cmp(const void *a, const void *b) {
return strcmp(*(char **) a, b);
}
e->priority = prio;
e->ptr = p;
return list_search(l, cmp, (void *) name);
}
void * list_search(struct list *l, cmp_cb_t cmp, void *ctx)
{
pthread_mutex_lock(&l->lock);
void *e;
list_foreach(e, l) {
if (!cmp(e, ctx))
goto out;
}
e = NULL; /* not found */
out: pthread_mutex_unlock(&l->lock);
return e;
}
void list_sort(struct list *l, cmp_cb_t cmp)
{
int cmp_helper(const void *a, const void *b) {
return cmp(*(void **) a, *(void **) b);
}
pthread_mutex_lock(&l->lock);
/* Search for first entry with higher priority */
for (d = l->head; d && d->priority < prio; d = d->next);
/* Insert new element in front of d */
e->next = d;
if (d) { /* Between or Head */
e->prev = d->prev;
if (d == l->head) /* Head */
l->head = e;
else /* Between */
d->prev = e;
}
else { /* Tail or Head */
e->prev = l->tail;
if (l->length == 0) /* List was empty */
l->head = e;
else
l->tail->next = e;
l->tail = e;
}
l->length++;
qsort(l->start, l->length, sizeof(void *), cmp_helper);
pthread_mutex_unlock(&l->lock);
}
void * list_lookup(const struct list *l, const char *name)
{
FOREACH(l, it) {
if (!strcmp(*(char **) it->ptr, name))
return it->ptr;
}
return NULL;
}
void * list_search(const struct list *l, cmp_cb_t cmp, void *ctx)
{
FOREACH(l, it) {
if (!cmp(it->ptr, ctx))
return it->ptr;
}
return NULL;
}
}

View file

@ -35,8 +35,7 @@ struct list node_types = LIST_INIT(NULL);
int node_init(int argc, char *argv[], struct settings *set)
{ INDENT
FOREACH(&node_types, it) {
const struct node_type *vt = it->type;
list_foreach(const struct node_type *vt, &node_types) {
if (vt->refcnt) {
info("Initializing '%s' node type", vt->name);
vt->init(argc, argv, set);
@ -49,8 +48,7 @@ int node_init(int argc, char *argv[], struct settings *set)
int node_deinit()
{ INDENT
/* De-initialize node types */
FOREACH(&node_types, it) {
struct node_type *vt = it->type;
list_foreach(const struct node_type *vt, &node_types) {
if (vt->refcnt) {
info("De-initializing '%s' node type", vt->name);
vt->deinit();

View file

@ -23,16 +23,16 @@ extern struct settings settings;
static void path_write(struct path *p)
{
FOREACH(&p->destinations, it) {
list_foreach(struct node *n, &p->destinations) {
int sent = node_write(
it->node, /* Destination node */
p->pool, /* Pool of received messages */
p->poolsize, /* Size of the pool */
p->received - it->node->combine,/* Index of the first message which should be sent */
it->node->combine /* Number of messages which should be sent */
n, /* Destination node */
p->pool, /* Pool of received messages */
p->poolsize, /* Size of the pool */
p->received - n->combine,/* Index of the first message which should be sent */
n->combine /* Number of messages which should be sent */
);
debug(1, "Sent %u messages to node '%s'", sent, it->node->name);
debug(1, "Sent %u messages to node '%s'", sent, n->name);
p->sent += sent;
clock_gettime(CLOCK_REALTIME, &p->ts_sent);
@ -42,8 +42,9 @@ static void path_write(struct path *p)
int path_run_hook(struct path *p, enum hook_type t)
{
int ret = 0;
FOREACH(&p->hooks[t], it)
ret += ((hook_cb_t) it->ptr)(p);
list_foreach(struct hook *h, &p->hooks) {
}
return ret;
}
@ -177,8 +178,8 @@ char * path_print(struct path *p)
if (list_length(&p->destinations) > 1) {
strcatf(&buf, " [");
FOREACH(&p->destinations, it)
strcatf(&buf, " %s", it->node->name);
list_foreach(struct node *n, &p->destinations)
strcatf(&buf, " %s", n->name);
strcatf(&buf, " ]");
}
else

View file

@ -38,12 +38,12 @@ static config_t config;
static void quit()
{
info("Stopping paths");
FOREACH(&paths, it)
path_stop(it->path);
list_foreach(struct path *p, &paths)
path_stop(p);
info("Stopping nodes");
FOREACH(&nodes, it)
node_stop(it->node);
list_foreach(struct node *n, &nodes)
node_stop(n);
info("De-initializing node types");
node_deinit();
@ -185,21 +185,21 @@ int main(int argc, char *argv[])
node_init(argc, argv, &settings);
info("Starting nodes");
FOREACH(&nodes, it)
node_start(it->node);
list_foreach(struct node *n, &nodes)
node_start(n);
info("Starting paths");
FOREACH(&paths, it)
path_start(it->path);
list_foreach(struct path *p, &paths)
path_start(p);
/* Run! */
if (settings.stats > 0) {
stats_header();
for (;;) FOREACH(&paths, it) {
do list_foreach(struct path *p, &paths) {
usleep(settings.stats * 1e6);
path_run_hook(it->path, HOOK_PERIODIC);
}
path_run_hook(p, HOOK_PERIODIC);
} while (1);
}
else
pause();

View file

@ -47,8 +47,7 @@ int socket_init(int argc, char * argv[], struct settings *set)
list_init(&interfaces, (dtor_cb_t) if_destroy);
/* Gather list of used network interfaces */
FOREACH(&sockets, it) {
struct socket *s = it->socket;
list_foreach(struct socket *s, &sockets) {
struct rtnl_link *link;
/* Determine outgoing interface */
@ -67,16 +66,16 @@ int socket_init(int argc, char * argv[], struct settings *set)
}
/** @todo Improve mapping of NIC IRQs per path */
FOREACH(&interfaces, it)
if_start(it->interface, set->affinity);
list_foreach(struct interface *i, &interfaces)
if_start(i, set->affinity);
return 0;
}
int socket_deinit()
{ INDENT
FOREACH(&interfaces, it)
if_stop(it->interface);
list_foreach(struct interface *i, &interfaces)
if_stop(i);
list_destroy(&interfaces);