Browse Source

Move triggers to their own files and directory.

Triggers are now loaded like blocks
Still needs work to cleanup timespec stuff.
beaglebone
Jeroen Vreeken 7 years ago
parent
commit
7db88b568e
8 changed files with 476 additions and 188 deletions
  1. +11
    -2
      controller/build.mk
  2. +65
    -186
      controller/controller/controller_sample.c
  3. +41
    -0
      controller/controller/controller_trigger.h
  4. +5
    -0
      controller/trigger/Makefile
  5. +25
    -0
      controller/trigger/build.mk
  6. +124
    -0
      controller/trigger/trigger_default.c
  7. +64
    -0
      controller/trigger/trigger_immediate.c
  8. +141
    -0
      controller/trigger/trigger_prestart.c

+ 11
- 2
controller/build.mk View File

@ -4,10 +4,14 @@ CLEAN += $(DIR)/lib/.libs
CTRL_BLOCKS :=
CTRL_BLOCK_LIBS :=
CTRL_TESTS :=
CTRL_TRIGGERS :=
CTRL_TRIGGER_LIBS :=
$(eval $(call SUBDIR,controller))
$(eval $(call SUBDIR,shell))
$(eval $(call SUBDIR,block))
$(eval $(call SUBDIR,trigger))
$(eval $(call SUBDIR,ec))
$(eval $(call SUBDIR,dt_azimuth))
$(eval $(call SUBDIR,dt_elevation))
@ -27,18 +31,23 @@ BLOCKS := $(addprefix -Wl$(,)-u -Wl$(,)block_,$(addsuffix _create_struct,$(CTRL_
BLOCKS += $(addprefix -Wl$(,)-u -Wl$(,)block_,$(addsuffix _create,$(CTRL_BLOCKS)))
BLOCKS += $(subst .la,,$(subst lib,-l,$(CTRL_BLOCK_LIBS)))
TRIGGERS := $(addprefix -Wl$(,)-u -Wl$(,)trigger_,$(addsuffix _create_struct,$(CTRL_TRIGGERS)))
TRIGGERS += $(subst .la,,$(subst lib,-l,$(CTRL_TRIGGER_LIBS)))
$(DIR)/dt_ctrl: \
libcontroller.la \
liblog.la \
libshell.la \
$(CTRL_BLOCK_LIBS)
$(CTRL_BLOCK_LIBS) \
$(CTRL_TRIGGER_LIBS)
$(DIR)/dt_ctrl_CFLAGS += -Wall -O3
$(DIR)/dt_ctrl_LDFLAGS += \
-Wl,-E \
-lcontroller \
-llog \
-lshell \
$(BLOCKS)
$(BLOCKS) \
$(TRIGGERS)
$(DIR)/dt_ctrl: $(DT_CTRL_OBJS)
test: dt_ctrl_test


+ 65
- 186
controller/controller/controller_sample.c View File

@ -35,10 +35,13 @@
#include <dirent.h>
#include <ctype.h>
#include <inttypes.h>
#include <dlfcn.h>
#include <controller/controller_block.h>
#include <controller/controller_sample.h>
#include <controller/controller_time.h>
#include <controller/controller_trigger.h>
#include <controller/controller_load.h>
#include <log/log.h>
#include <shell/shell.h>
@ -69,6 +72,11 @@ static int controller_sample_start_hooks_nr = 0;
static uint64_t timestamp_from_timespec(struct timespec *t)
{
return (uint64_t)t->tv_sec * 1000000000 + (uint64_t)t->tv_nsec;
}
static inline void tsnorm(struct timespec *ts)
{
while (ts->tv_nsec >= 1000000000) {
@ -121,25 +129,6 @@ static ssize_t sample_timing_snprintf(struct sample_timing *st,
}
static int sample_timing_sane(uint64_t t_exp, uint64_t t_act)
{
uint64_t n_diff;
if (t_exp > t_act)
n_diff = t_exp - t_act;
else
n_diff = t_act - t_exp;
if (n_diff > nsec_interval * 10) {
log_send(LOG_T_ERROR,
"Time sanity check triggered: %" PRIu64 " nsec difference",
t_act - t_exp);
return -1;
}
return 0;
}
static void alarm_handler(int d)
{
log_send(LOG_T_ERROR, "Sample has been inactive to long!");
@ -222,113 +211,10 @@ static void cpu_bind(void)
#endif
}
static uint64_t timestamp_from_timespec(struct timespec *t)
{
return (uint64_t)t->tv_sec * 1000000000 + (uint64_t)t->tv_nsec;
}
static clockid_t sample_clock;
#ifdef __FreeBSD__
static pthread_condattr_t attr;
static pthread_mutex_t lock;
static pthread_cond_t cv;
#endif
static uint64_t timestamp(void)
{
struct timespec t;
clock_gettime(sample_clock, &t);
return timestamp_from_timespec(&t);
}
static void wait_init_default(struct timespec *t)
{
clock_gettime(sample_clock, t);
t->tv_nsec += nsec_interval - 1;
t->tv_nsec -= t->tv_nsec % nsec_interval;
tsnorm(t);
#ifndef __FreeBSD__
sample_clock = CLOCK_REALTIME;
#else
sample_clock = CLOCK_MONOTONIC;
pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, sample_clock);
pthread_cond_init(&cv, &attr);
pthread_condattr_destroy(&attr);
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
#endif
}
static void wait_next_default(struct timespec *t)
{
uint64_t tnow = timestamp();
if (sample_timing_sane(controller_time_nseconds, tnow)) {
controller_block_skip((int64_t)(tnow - controller_time_nseconds)/nsec_interval);
clock_gettime(sample_clock, t);
t->tv_nsec -= (t->tv_nsec % nsec_interval);
log_send(LOG_T_WARNING,
"Using current time for next sampe: %lld.%09ld",
(long long)t->tv_sec, t->tv_nsec);
}
t->tv_nsec += nsec_interval;
tsnorm(t);
#ifndef __FreeBSD__
clock_nanosleep(sample_clock, TIMER_ABSTIME, t, NULL);
#else
pthread_cond_timedwait(&cv, &lock, t);
#endif
}
static uint64_t prestart = 0;
static void wait_next_prestart(struct timespec *t)
{
#ifndef __FreeBSD__
struct timespec tn;
uint64_t tnow = timestamp();
if (sample_timing_sane(controller_time_nseconds, tnow)) {
controller_block_skip((int64_t)(tnow - controller_time_nseconds)/nsec_interval);
clock_gettime(sample_clock, t);
t->tv_nsec -= (t->tv_nsec % nsec_interval);
log_send(LOG_T_WARNING,
"Using current time for next sampe: %lld.%09ld",
(long long)t->tv_sec, t->tv_nsec);
}
t->tv_nsec += nsec_interval;
tn.tv_sec = t->tv_sec;
tn.tv_nsec = t->tv_nsec;
tn.tv_nsec += prestart;
tsnorm(t);
tsnorm(&tn);
clock_nanosleep(sample_clock, TIMER_ABSTIME, &tn, NULL);
clock_gettime(sample_clock, &tn);
while (tn.tv_sec < t->tv_sec || tn.tv_nsec < t->tv_nsec) {
clock_gettime(sample_clock, &tn);
}
#endif
}
static void (*wait_init)(struct timespec *) = wait_init_default;
static void (*wait_next)(struct timespec *) = wait_next_default;
static void (*wait_init)(struct timespec *, uint64_t nsed_interval) = NULL;
static void (*wait_next)(struct timespec *) = NULL;
static uint64_t (*timestamp)(void) = NULL;
/*
This thread should be realtime....
@ -368,7 +254,7 @@ static void *sample_thread(void *arg)
strerror(errno));
}
wait_init(&t);
wait_init(&t, nsec_interval);
controller_time_nseconds = timestamp_from_timespec(&t);
while (1) {
@ -516,8 +402,6 @@ int controller_sample_start(void)
int i;
nsec_interval = controller_time_sample_period_get() * 1000000000.0;
if (-prestart > nsec_interval / 10)
prestart = -nsec_interval / 10;
log_send(LOG_T_DEBUG, "nsec_interval: %d %f",
nsec_interval, controller_time_sample_frequency_get());
@ -542,70 +426,65 @@ int controller_sample_start(void)
return 0;
}
#define PREFIX "trigger_"
#define POSTFIX "_create_struct"
void wait_next_immediate(struct timespec *t)
{
t->tv_nsec += nsec_interval;
tsnorm(t);
}
static int trigger_default(int argc, va_list ap)
{
log_send(LOG_T_DEBUG, "Default trigger");
wait_init = wait_init_default;
wait_next = wait_next_default;
return 0;
}
static int trigger_prestart(int argc, va_list ap)
int controller_sample_trigger(char *name, int argc, va_list ap)
{
double prestart_d;
void *handle;
struct controller_trigger_create *create;
struct controller_trigger *trigger;
int ret = 0;
char *symbol;
prestart_d = va_arg(ap, double);
prestart = -((1000000000.0 * prestart_d) + 0.5);
log_send(LOG_T_DEBUG, "Prestart trigger: %g sec (%" PRId64 " nsec)",
prestart_d, -prestart);
wait_init = wait_init_default;
wait_next = wait_next_prestart;
return 0;
}
handle = dlopen(NULL, RTLD_NOW);
if (!handle) {
log_send(LOG_T_ERROR,
"Could not get handle from dlopen(): %s", dlerror());
return -1;
}
static int trigger_immediate(int argc, va_list ap)
{
log_send(LOG_T_DEBUG, "Immediate trigger");
asprintf(&symbol, "%s%s%s", PREFIX, name, POSTFIX);
create = dlsym(handle, symbol);
free(symbol);
wait_init = wait_init_default;
wait_next = wait_next_immediate;
return 0;
}
static struct {
char *name;
int (*func)(int argc, va_list ap);
} triggers[] = {
{ "default", trigger_default },
{ "prestart", trigger_prestart },
{ "immediate", trigger_immediate },
};
if (!create) {
log_send(LOG_T_ERROR, "No trigger '%s' available", name);
ret = -1;
} else {
int i;
bool arg_ok = false;
if (create->args[0] == NULL && !argc)
arg_ok = true;
for (i = 0; create->args[i]; i++) {
arg_ok = controller_load_arg_match(create->args[i], argc);
if (arg_ok)
break;
}
if (arg_ok) {
trigger = create->create(argc, ap);
if (!trigger) {
log_send(LOG_T_ERROR, "%s creation failed", name);
ret = -1;
}
wait_init = trigger->init;
wait_next = trigger->next;
timestamp = trigger->timestamp;
} else {
log_send(LOG_T_ERROR,
"%s create function does not expect %d arguments.%s",
name, argc, create->args[0] ? " Use:" : "");
for (i = 0; create->args[i]; i++) {
log_send(LOG_T_ERROR,
"\t{ \"%s\", %s }",
name, create->args[i]);
}
ret = -1;
}
int controller_sample_trigger(char *name, int argc, va_list ap)
{
int i;
for (i = 0; i < sizeof(triggers)/sizeof(triggers[0]); i++) {
if (!strcmp(triggers[i].name, name))
return triggers[i].func(argc, ap);
}
dlclose(handle);
log_send(LOG_T_ERROR, "No trigger '%s' available", name);
return -1;
return ret;
}

+ 41
- 0
controller/controller/controller_trigger.h View File

@ -0,0 +1,41 @@
/*
Copyright Jeroen Vreeken (jeroen@vreeken), 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_TRIGGER_H_
#define _INCLUDE_CONTROLLER_TRIGGER_H_
#include <stddef.h>
#include <inttypes.h>
#include <stdarg.h>
#include <time.h>
struct controller_trigger {
void (*init)(struct timespec *t, uint64_t nsec_interval);
void (*next)(struct timespec *t);
uint64_t (*timestamp)(void);
};
struct controller_trigger_create {
struct controller_trigger *(*create)(int, va_list);
char *args[];
};
#define TRIGGER_CREATE(type) \
struct controller_trigger_create trigger_ ## type ## _create_struct __attribute__((used))
#endif

+ 5
- 0
controller/trigger/Makefile View File

@ -0,0 +1,5 @@
all:
@$(MAKE) --no-print-directory -C ../.. targets_controller/trigger
$(MAKECMDGOALS):
@$(MAKE) --no-print-directory -C ../.. $(MAKECMDGOALS)

+ 25
- 0
controller/trigger/build.mk View File

@ -0,0 +1,25 @@
TRIGGER_TARGETS := $(LIBDIR)/libtrigger.la
TRIGGERS := \
default \
immediate \
prestart
TRIGGER_SRCS := $(addsuffix .c,$(addprefix $(DIR)/trigger_,$(TRIGGERS)))
TRIGGER_OBJS := $(TRIGGER_SRCS:.c=.lo)
$(TRIGGER_OBJS): CFLAGS += -O3 -Wall
$(LIBDIR)/libtrigger.la_LDFLAGS += -lcontroller -llog
$(LIBDIR)/libtrigger.la: libcontroller.la liblog.la
$(LIBDIR)/libtrigger.la: $(TRIGGER_OBJS)
$(LIB_LINK)
CTRL_TRIGGERS += $(TRIGGERS)
CTRL_TRIGGER_LIBS += libtrigger.la
TARGETS += $(TRIGGER_TARGETS)
CLEAN += $(TRIGGER_TARGETS) $(TRIGGER_OBJS) $(TRIGGER_OBJS:.lo=.o)
SRCS += $(TRIGGER_SRCS)

+ 124
- 0
controller/trigger/trigger_default.c View File

@ -0,0 +1,124 @@
#include <controller/controller_trigger.h>
#include <controller/controller_time.h>
#include <controller/controller_block.h>
#include <log/log.h>
static clockid_t sample_clock;
#ifdef __FreeBSD__
static pthread_condattr_t attr;
static pthread_mutex_t lock;
static pthread_cond_t cv;
#endif
static uint64_t interval;
static inline void tsnorm(struct timespec *ts)
{
while (ts->tv_nsec >= 1000000000) {
ts->tv_nsec -= 1000000000;
ts->tv_sec++;
}
}
static uint64_t timestamp_from_timespec(struct timespec *t)
{
return (uint64_t)t->tv_sec * 1000000000 + (uint64_t)t->tv_nsec;
}
static int sample_timing_sane(uint64_t t_exp, uint64_t t_act)
{
uint64_t n_diff;
if (t_exp > t_act)
n_diff = t_exp - t_act;
else
n_diff = t_act - t_exp;
if (n_diff > interval * 10) {
log_send(LOG_T_ERROR,
"Time sanity check triggered: %" PRIu64 " nsec difference",
t_act - t_exp);
return -1;
}
return 0;
}
static uint64_t timestamp(void)
{
struct timespec t;
clock_gettime(sample_clock, &t);
return timestamp_from_timespec(&t);
}
static void wait_init_default(struct timespec *t, uint64_t nsec_interval)
{
interval = nsec_interval;
#ifndef __FreeBSD__
sample_clock = CLOCK_REALTIME;
#else
sample_clock = CLOCK_MONOTONIC;
pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, sample_clock);
pthread_cond_init(&cv, &attr);
pthread_condattr_destroy(&attr);
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
#endif
clock_gettime(sample_clock, t);
t->tv_nsec += interval - 1;
t->tv_nsec -= t->tv_nsec % interval;
tsnorm(t);
}
static void wait_next_default(struct timespec *t)
{
uint64_t tnow = timestamp();
if (sample_timing_sane(controller_time_nseconds, tnow)) {
controller_block_skip((int64_t)(tnow - controller_time_nseconds)/interval);
clock_gettime(sample_clock, t);
t->tv_nsec -= (t->tv_nsec % interval);
log_send(LOG_T_WARNING,
"Using current time for next sampe: %lld.%09ld",
(long long)t->tv_sec, t->tv_nsec);
}
t->tv_nsec += interval;
tsnorm(t);
#ifndef __FreeBSD__
clock_nanosleep(sample_clock, TIMER_ABSTIME, t, NULL);
#else
pthread_cond_timedwait(&cv, &lock, t);
#endif
}
static struct controller_trigger trigger_default = {
wait_init_default,
wait_next_default,
timestamp,
};
struct controller_trigger *trigger_default_create(int argc, va_list ap)
{
log_send(LOG_T_DEBUG, "Default trigger");
return &trigger_default;
}
TRIGGER_CREATE(default) = {
.create = trigger_default_create,
.args = { NULL },
};

+ 64
- 0
controller/trigger/trigger_immediate.c View File

@ -0,0 +1,64 @@
#include <controller/controller_trigger.h>
#include <log/log.h>
static inline void tsnorm(struct timespec *ts)
{
while (ts->tv_nsec >= 1000000000) {
ts->tv_nsec -= 1000000000;
ts->tv_sec++;
}
}
static uint64_t timestamp_from_timespec(struct timespec *t)
{
return (uint64_t)t->tv_sec * 1000000000 + (uint64_t)t->tv_nsec;
}
static uint64_t interval;
static void wait_init_default(struct timespec *t, uint64_t nsec_interval)
{
clock_gettime(CLOCK_REALTIME, t);
interval = nsec_interval;
t->tv_nsec += nsec_interval - 1;
t->tv_nsec -= t->tv_nsec % nsec_interval;
tsnorm(t);
}
void wait_next_immediate(struct timespec *t)
{
t->tv_nsec += interval;
tsnorm(t);
}
static uint64_t timestamp(void)
{
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return timestamp_from_timespec(&t);
}
static struct controller_trigger trigger_default = {
wait_init_default,
wait_next_immediate,
timestamp,
};
struct controller_trigger *trigger_immediate_create(int argc, va_list ap)
{
log_send(LOG_T_DEBUG, "Immediate trigger");
return &trigger_default;
}
TRIGGER_CREATE(immediate) = {
.create = trigger_immediate_create,
.args = { NULL },
};

+ 141
- 0
controller/trigger/trigger_prestart.c View File

@ -0,0 +1,141 @@
#include <controller/controller_trigger.h>
#include <controller/controller_time.h>
#include <controller/controller_block.h>
#include <log/log.h>
static clockid_t sample_clock;
#ifdef __FreeBSD__
static pthread_condattr_t attr;
static pthread_mutex_t lock;
static pthread_cond_t cv;
#endif
static uint64_t interval;
static inline void tsnorm(struct timespec *ts)
{
while (ts->tv_nsec >= 1000000000) {
ts->tv_nsec -= 1000000000;
ts->tv_sec++;
}
}
static uint64_t timestamp_from_timespec(struct timespec *t)
{
return (uint64_t)t->tv_sec * 1000000000 + (uint64_t)t->tv_nsec;
}
static int sample_timing_sane(uint64_t t_exp, uint64_t t_act)
{
uint64_t n_diff;
if (t_exp > t_act)
n_diff = t_exp - t_act;
else
n_diff = t_act - t_exp;
if (n_diff > interval * 10) {
log_send(LOG_T_ERROR,
"Time sanity check triggered: %" PRIu64 " nsec difference",
t_act - t_exp);
return -1;
}
return 0;
}
static uint64_t timestamp(void)
{
struct timespec t;
clock_gettime(sample_clock, &t);
return timestamp_from_timespec(&t);
}
static void wait_init_default(struct timespec *t, uint64_t nsec_interval)
{
interval = nsec_interval;
#ifndef __FreeBSD__
sample_clock = CLOCK_REALTIME;
#else
sample_clock = CLOCK_MONOTONIC;
pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, sample_clock);
pthread_cond_init(&cv, &attr);
pthread_condattr_destroy(&attr);
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
#endif
clock_gettime(sample_clock, t);
t->tv_nsec += interval - 1;
t->tv_nsec -= t->tv_nsec % interval;
tsnorm(t);
}
static int64_t prestart;
static void wait_next_prestart(struct timespec *t)
{
#ifndef __FreeBSD__
struct timespec tn;
uint64_t tnow = timestamp();
if (sample_timing_sane(controller_time_nseconds, tnow)) {
controller_block_skip((int64_t)(tnow - controller_time_nseconds)/interval);
clock_gettime(sample_clock, t);
t->tv_nsec -= (t->tv_nsec % interval);
log_send(LOG_T_WARNING,
"Using current time for next sampe: %lld.%09ld",
(long long)t->tv_sec, t->tv_nsec);
}
t->tv_nsec += interval;
tn.tv_sec = t->tv_sec;
tn.tv_nsec = t->tv_nsec;
tn.tv_nsec += prestart;
tsnorm(t);
tsnorm(&tn);
clock_nanosleep(sample_clock, TIMER_ABSTIME, &tn, NULL);
clock_gettime(sample_clock, &tn);
while (tn.tv_sec < t->tv_sec || tn.tv_nsec < t->tv_nsec) {
clock_gettime(sample_clock, &tn);
}
#endif
}
static struct controller_trigger trigger_prestart = {
wait_init_default,
wait_next_prestart,
timestamp,
};
struct controller_trigger *trigger_prestart_create(int argc, va_list ap)
{
double prestart_d;
prestart_d = va_arg(ap, double);
prestart = -((1000000000.0 * prestart_d) + 0.5);
log_send(LOG_T_DEBUG, "Prestart trigger: %g sec (%" PRId64 " nsec)",
prestart_d, -prestart);
return &trigger_prestart;
}
TRIGGER_CREATE(prestart) = {
.create = trigger_prestart_create,
.args = { "double", NULL },
};

Loading…
Cancel
Save