Commit d0a8fcc9 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Add busyloop trigger (very good timing on multicore systems)

Add controller_mem memory allocation functions.
All periodic data will be allocated in a continuous piece of memory hoping
for optimall cache behaviour with regards to associativity.
(TODO: really allocate continuous memory at the other side of the MMU)
parent 9f728334
......@@ -90,6 +90,18 @@ void log_send(enum log_type type, char *fmt, ...)
va_start(ap, fmt);
/* Unreliably try to see if going further makes sense */
msg = msgs_wr % LOG_MAX_QUEUE;
if (msgs[msg].used) {
/* Give up */
__sync_fetch_and_add(&lost_counter, 1);
sem_getvalue(&queue_wait, &val);
if (!val)
sem_post(&queue_wait);
return;
}
/* And now for real since it might work... */
msg = __sync_fetch_and_add(&msgs_wr, 1);
msg %= LOG_MAX_QUEUE;
......
......@@ -21,6 +21,7 @@
#include <string.h>
#include <controller/controller_block.h>
#include <controller/controller_mem.h>
#include <log/log.h>
/*
......@@ -74,7 +75,8 @@ static struct controller_block * block_decoder_uint32_bool_create(char *name, in
return NULL;
dec->private->n = n;
dec->private->out = calloc(sizeof(bool), n);
dec->private->out = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_WRITE,
n, sizeof(bool));
if (!dec->private->out)
goto err_out;
......
......@@ -22,6 +22,7 @@
#include <string.h>
#include <controller/controller_block.h>
#include <controller/controller_mem.h>
#include <block/block_filter_iir.h>
#include <log/log.h>
......@@ -96,11 +97,12 @@ static int param_set(struct controller_block *iir, int argc, va_list ap)
iir->private->param.zeros = zeros;
if (iir->private->transfer)
free(iir->private->transfer);
controller_mem_free(iir->private->transfer);
iir->private->len = iir->private->param.len + 1;
iir->private->transfer = malloc(sizeof(float[4]) *
iir->private->len);
iir->private->transfer = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_READ | CONTROLLER_MEM_PERIODIC_WRITE,
iir->private->len, sizeof(float[4]));
if (!iir->private->transfer) {
iir->private->len = 0;
return -1;
......
......@@ -27,6 +27,7 @@
#include <controller/controller_block.h>
#include <controller/controller_bus.h>
#include <controller/controller_mem.h>
#include <log/log.h>
#include <linux/joystick.h>
......@@ -140,10 +141,12 @@ static struct controller_block * block_joystick_create(char *name, int argc, va_
if (!(block = controller_block_alloc("joystick", name, sizeof(struct controller_block_private))))
goto err_block;
block->private->axes = calloc(sizeof(float), nr_axes);
block->private->axes = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_WRITE,
nr_axes, sizeof(float));
if (!block->private->axes)
goto err_axes;
block->private->buttons = calloc(sizeof(bool), nr_buttons);
block->private->buttons = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_WRITE,
nr_buttons, sizeof(bool));
if (!block->private->buttons)
goto err_buttons;
......
......@@ -21,6 +21,7 @@
#include <string.h>
#include <controller/controller_block.h>
#include <controller/controller_mem.h>
#include <log/log.h>
/*
......@@ -80,7 +81,8 @@ static struct controller_block * block_multiplexer_create(char *name, int argc,
mul->private->n = n - 1;
mul->private->out = 0.0;
mul->private->in = calloc(sizeof(float*), n);
mul->private->in = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_READ,
n, sizeof(float*));
if (!mul->private->in)
goto err_in;
......
......@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
#include <controller/controller_block.h>
#include <controller/controller_mem.h>
#include <log/log.h>
/*
......@@ -129,7 +130,7 @@ static void ensure_state(struct controller_block *sm, uint32_t state)
memset(priv->state_table + priv->state_nr, 0, sizeof(struct state));
priv->state_table[priv->state_nr].state = state;
priv->state_table[priv->state_nr].out =
calloc(priv->no, sizeof(bool));
controller_mem_calloc(CONTROLLER_MEM_PERIODIC_READ, priv->no, sizeof(bool));
priv->state_nr++;
}
......@@ -179,8 +180,10 @@ static void add_transition(struct controller_block *sm,
priv->state_table[statenr].transitions = realloc(
priv->state_table[statenr].transitions,
sizeof(struct transition) * (nr + 1));
priv->state_table[statenr].transitions[nr].in = calloc(priv->ni, sizeof(bool));
priv->state_table[statenr].transitions[nr].care = calloc(priv->ni, sizeof(bool));
priv->state_table[statenr].transitions[nr].in = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_READ, priv->ni, sizeof(bool));
priv->state_table[statenr].transitions[nr].care = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_READ, priv->ni, sizeof(bool));
priv->state_table[statenr].transitions[nr].to = to_statenr;
for (i = 0; i < priv->ni; i++) {
......@@ -255,11 +258,13 @@ static struct controller_block * block_state_machine_create(char *name, int argc
ensure_state(sm, 0);
sm->private->in = calloc(sizeof(bool*), ni);
sm->private->in = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_READ,
ni, sizeof(bool*));
if (!sm->private->in)
goto err_in;
sm->private->out = calloc(sizeof(bool), no);
sm->private->out = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_WRITE,
no, sizeof(bool));
if (!sm->private->out)
goto err_out;
......
......@@ -23,6 +23,7 @@
#include <controller/controller_block.h>
#include <controller/controller_time.h>
#include <controller/controller_mem.h>
#include <block/block_trajectplayer.h>
#include <log/log.h>
......@@ -160,8 +161,9 @@ static int param_set_traject(struct controller_block *player, int argc, va_list
priv->trajectories = realloc(priv->trajectories,
sizeof(struct block_trajectplayer_param *) *
priv->nr + 1);
priv->trajectories[priv->nr] = calloc(
sizeof(struct block_trajectplayer_param), 1);
priv->trajectories[priv->nr] = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_READ, 1,
sizeof(struct block_trajectplayer_param));
priv->nr++;
priv->trajectories[traject_nr]->nr = traject.nr;
}
......
......@@ -7,6 +7,7 @@ CONTROLLER_SRCS= \
$(DIR)/controller_block_trace.c \
$(DIR)/controller_bus.c \
$(DIR)/controller_command.c \
$(DIR)/controller_mem.c \
$(DIR)/controller_time.c \
$(DIR)/controller_trace.c \
$(DIR)/controller_sample.c \
......
......@@ -24,6 +24,7 @@
#include <pthread.h>
#include <dlfcn.h>
#include <controller/controller_mem.h>
#include <controller/controller_block.h>
#include <controller/controller_sample.h>
#include <controller/controller_bus.h>
......@@ -253,7 +254,6 @@ void controller_block_context_set(char *new_context)
int controller_block_sample_init(void)
{
int i, j, k;
void *tmp;
bool check = true;
/* Sanity check */
......@@ -343,33 +343,25 @@ int controller_block_sample_init(void)
calculates_sub = controller_time_subsample_get();
calculates = calloc(sizeof(struct calculate_func *), calculates_sub);
calculates = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_READ,
calculates_sub, sizeof(struct calculate_func *));
for (sub = 0; sub < calculates_sub; sub++) {
int nr_calculates = 0;
calculates[sub] = calloc(sizeof(struct calculate_func), 1);
for (i = 0; i < nr_blocks; i++) {
if (blocks[i]->calculate && controller_time_subsample_member(blocks[i]->time, sub)) {
// log_send(LOG_T_DEBUG,
// "Block %s has a calculate function",
// blocks[i]->name);
tmp = realloc(calculates[sub],
sizeof(struct calculate_func) * (nr_calculates+2));
if (tmp) {
calculates[sub] = tmp;
calculates[sub][nr_calculates].func =
blocks[i]->calculate;
calculates[sub][nr_calculates].block = blocks[i];
nr_calculates++;
calculates[sub][nr_calculates].block = NULL;
} else {
log_send(LOG_T_ERROR,
"Out of memory allocating memory");
}
} else {
// log_send(LOG_T_DEBUG,
// "Block %s has no calculate function",
// blocks[i]->name);
nr_calculates++;
}
}
calculates[sub] = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_READ,
nr_calculates + 1, sizeof(struct calculate_func));
j = 0;
for (i = 0; i < nr_blocks; i++) {
if (blocks[i]->calculate && controller_time_subsample_member(blocks[i]->time, sub)) {
calculates[sub][j].func = blocks[i]->calculate;
calculates[sub][j].block = blocks[i];
j++;
}
}
for (i = 0; i < sub; i++) {
......@@ -378,7 +370,7 @@ int controller_block_sample_init(void)
!calculates[i][j].block) {
log_send(LOG_T_DEBUG,
"subsample %d is identical to subsample %d", sub, i);
free(calculates[sub]);
controller_mem_free(calculates[sub]);
calculates[sub] = calculates[i];
i = sub;
break;
......@@ -614,7 +606,8 @@ struct controller_block *controller_block_alloc(char *type, char *name,
{
struct controller_block *blk;
blk = calloc(1, sizeof(struct controller_block));
blk = controller_mem_calloc(CONTROLLER_MEM_PERIODIC_READ,
1, sizeof(struct controller_block));
if (!blk)
goto err_calloc;
......@@ -624,7 +617,10 @@ struct controller_block *controller_block_alloc(char *type, char *name,
goto err_name;
if (private_size > 0) {
blk->private = calloc(1, private_size);
blk->private = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_WRITE |
CONTROLLER_MEM_PERIODIC_READ,
1, private_size);
if (!blk->private)
goto err_private;
}
......@@ -636,11 +632,11 @@ struct controller_block *controller_block_alloc(char *type, char *name,
return blk;
err_time:
free(blk->private);
controller_mem_free(blk->private);
err_private:
free(blk->name);
err_name:
free(blk);
controller_mem_free(blk);
err_calloc:
return NULL;
}
......@@ -650,12 +646,12 @@ void controller_block_free(struct controller_block *blk)
if (blk->name)
free(blk->name);
if (blk->private)
free(blk->private);
controller_mem_free(blk->private);
if (blk->input)
free(blk->input);
if (blk->output)
free(blk->output);
free(blk);
controller_mem_free(blk);
}
......@@ -123,7 +123,7 @@ int controller_block_param_list_add(struct controller_block *block,
for (i = 0; list[i].name; i++) {
for (j = 0; list[i].args[j]; j++);
size_t argsize = sizeof(char *) * j;
entry = calloc(sizeof(struct controller_block_param_list) + argsize, 1);
entry = calloc(1, sizeof(struct controller_block_param_list) + argsize);
if (!entry)
return 1;
entry->name = strdup(list[i].name);
......
......@@ -27,6 +27,7 @@
#include <controller/controller_block.h>
#include <controller/controller_time.h>
#include <controller/controller_mem.h>
#include <log/log.h>
static int nr_traces = 0;
......@@ -40,16 +41,11 @@ static struct controller_trace *trace_del_ptr = NULL;
void controller_block_trace_init(int max)
{
int i;
traces = malloc(sizeof(struct controller_trace *) * max);
traces = controller_mem_calloc(
CONTROLLER_MEM_PERIODIC_READ | CONTROLLER_MEM_PERIODIC_WRITE,
max, sizeof(struct controller_trace *));
max_traces = max;
/* touch entire trace list */
for (i = 0; i < max; i++) {
traces[i] = NULL;
}
pthread_mutex_init(&trace_lock, NULL);
sem_init(&trace_sync_sem, 0, 0);
}
......
......@@ -90,7 +90,7 @@ void controller_load_variable_alias_set(char *varname, char *block, char *term)
}
if (!entry) {
entry = calloc(sizeof(struct variable), 1);
entry = calloc(1, sizeof(struct variable));
entry->name = strdup(varname);
entry->next = variables;
......@@ -151,7 +151,7 @@ void controller_load_variable_double_set(char *varname, double val)
}
if (!entry) {
entry = calloc(sizeof(struct variable), 1);
entry = calloc(1, sizeof(struct variable));
entry->name = strdup(varname);
entry->next = variables;
......@@ -176,7 +176,7 @@ void controller_load_variable_int_set(char *varname, int val)
}
if (!entry) {
entry = calloc(sizeof(struct variable), 1);
entry = calloc(1, sizeof(struct variable));
entry->name = strdup(varname);
entry->next = variables;
......@@ -215,7 +215,7 @@ void controller_load_variable_string_set(char *varname, char *val)
}
if (!entry) {
entry = calloc(sizeof(struct variable), 1);
entry = calloc(1, sizeof(struct variable));
entry->name = strdup(varname);
entry->next = variables;
......
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2015
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
(at your option) 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 <controller/controller_mem.h>
#include <log/log.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
static size_t total;
static size_t total_w;
static size_t total_r;
#define BLOCK_SIZE (256*1024)
struct controller_mem_block {
struct controller_mem_block *next;
void *base;
struct controller_mem_chunk *chunks;
};
struct controller_mem_chunk {
struct controller_mem_chunk *next;
size_t off;
size_t len;
bool used;
};
static struct controller_mem_block *blocks;
static struct controller_mem_block *add_block(void)
{
struct controller_mem_block *block, **bptr;
block = calloc(1, sizeof(struct controller_mem_block));
if (!block)
goto err_block;
block->base = calloc(1, BLOCK_SIZE);
if (!block->base)
goto err_base;
block->chunks = calloc(1, sizeof(struct controller_mem_chunk));
if (!block->chunks)
goto err_chunk;
block->chunks->len = BLOCK_SIZE;
for (bptr = &blocks; *bptr; bptr = &((*bptr)->next));
*bptr = block;
return block;
err_chunk:
free(block->base);
err_base:
free(block);
err_block:
return NULL;
}
static struct controller_mem_chunk *new_chunk(void)
{
return calloc(1, sizeof(struct controller_mem_chunk));
}
void *controller_mem_calloc(int flags, size_t nmemb, size_t size)
{
char *ptr = NULL;
size_t sz = nmemb * size;
struct controller_mem_block *block;
struct controller_mem_chunk **chunk;
size_t align;
size_t apad = 0;
/* Not periodicly used or to big, use normal calloc */
if (!flags || sz > BLOCK_SIZE) {
return calloc(nmemb, size);
}
align = size & 15;
if (!align)
align = 16;
total += sz;
if (flags & CONTROLLER_MEM_PERIODIC_WRITE)
total_w += sz;
if (flags & CONTROLLER_MEM_PERIODIC_READ)
total_r += sz;
for (block = blocks; block; block = block->next) {
for (chunk = &block->chunks; *chunk; chunk = &(*chunk)->next) {
apad = (align - ((*chunk)->off & (align-1))) & (align-1);
if (!(*chunk)->used && (*chunk)->len >= sz + apad) {
break;
}
}
if (*chunk)
break;
}
if (!block) {
apad = 0;
block = add_block();
if (block)
chunk = &(block->chunks);
}
if (chunk && *chunk) {
struct controller_mem_chunk *a_chunk, *e_chunk, *r_chunk;
r_chunk = *chunk;
if (apad) {
a_chunk = new_chunk();
if (!a_chunk)
return NULL;
a_chunk->off = r_chunk->off;
a_chunk->len = apad;
r_chunk->off += apad;
r_chunk->len -= apad;
a_chunk->next = r_chunk;
*chunk = a_chunk;
}
if (r_chunk->len > sz) {
e_chunk = new_chunk();
if (!e_chunk)
return NULL;
e_chunk->next = r_chunk->next;
r_chunk->next = e_chunk;
e_chunk->off = r_chunk->off + sz;
e_chunk->len = r_chunk->len - sz;
r_chunk->len -= e_chunk->len;
}
r_chunk->used = true;
ptr = (char *)block->base + r_chunk->off;
memset(ptr, 0, r_chunk->len);
}
return ptr;
}
void controller_mem_free(void *ptr)
{
struct controller_mem_block *block;
struct controller_mem_chunk *chunk;
for (block = blocks; block; block = block->next) {
for (chunk = block->chunks; chunk; chunk = chunk->next) {
if ((char *)block->base + chunk->off == ptr) {
chunk->used = false;
ptr = NULL;
break;
}
}
if (chunk)
break;
}
/* Not found, probably used libc malloc */
if (ptr) {
free(ptr);
return;
}
/* cleanup free chunks */
for (block = blocks; block; block = block->next) {
for (chunk = block->chunks; chunk; chunk = chunk->next) {
if (chunk->used)
continue;
while (chunk->next && !chunk->next->used) {
struct controller_mem_chunk *next;
next = chunk->next;
chunk->len += next->len;
chunk->next = next->next;
free(next);
}
}
}
}
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2015
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
(at your option) 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/>.
*/
#ifndef _INCLUDE_CONTROLLER_MEM_H_
#define _INCLUDE_CONTROLLER_MEM_H_
#include <stdlib.h>
#define CONTROLLER_MEM_PERIODIC_WRITE 1
#define CONTROLLER_MEM_PERIODIC_READ 2
void *controller_mem_calloc(int flags, size_t nmemb, size_t size);
void controller_mem_free(void *);
#endif /* _INCLUDE_CONTROLLER_MEM_H_ */
......@@ -265,7 +265,7 @@ static void *sample_thread(void *arg)
sample_timing_add(&st_end, t_trig, t_end);
sample_timing_add(&st_sample, t_start, t_end);