hexagram/src/schedule.c

153 lines
3.7 KiB
C
Raw Normal View History

2023-12-24 00:11:00 -05:00
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
2023-12-24 00:11:00 -05:00
#include <hexagram/schedule.h>
static inline hexagram_schedule_timer *_timer(hexagram_schedule *schedule, size_t i) {
return &((hexagram_schedule_timer *)(schedule + 1))[i];
};
static int _timer_cmp(const void *item_a, const void *item_b) {
hexagram_schedule_timer *a = (hexagram_schedule_timer *)item_a,
*b = (hexagram_schedule_timer *)item_b;
return a->slot->interval_us < b->slot->interval_us? -1:
a->slot->interval_us > b->slot->interval_us? 1: 0;
}
static inline int _timer_set(hexagram_schedule_timer *timer, time_t nsec) {
timer->ts.it_value.tv_sec = 0;
timer->ts.it_value.tv_nsec = nsec;
timer->ts.it_interval.tv_sec = 0;
timer->ts.it_interval.tv_nsec = nsec;
return timer_settime(timer->id, 0, &timer->ts, NULL);
}
static inline int _timer_stop(hexagram_schedule_timer *timer) {
return _timer_set(timer, 0);
}
2023-12-27 13:19:19 -05:00
static void _ev_notify(union sigval sv) {
hexagram_schedule_timer *timer = sv.sival_ptr;
hexagram_schedule_slot *slot = timer->slot;
if (slot->handler(&slot->frame, timer->ctx) < 0) {
timer->error = errno;
_timer_stop(timer);
2023-12-24 00:11:00 -05:00
}
}
hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
2023-12-27 14:14:25 -05:00
size_t count,
void *ctx) {
hexagram_schedule *schedule;
size_t i;
if ((schedule = malloc(sizeof(*schedule) + count * sizeof(hexagram_schedule_timer))) == 0) {
2023-12-27 14:14:25 -05:00
goto error_malloc_schedule;
}
schedule->table = table;
schedule->count = count;
2023-12-27 14:16:33 -05:00
for (i=0; i<count; i++) {
hexagram_schedule_timer *timer = _timer(schedule, i);
memset(&timer->ev, '\0', sizeof(struct sigevent));
timer->ev.sigev_notify = SIGEV_THREAD;
timer->ev.sigev_notify_function = _ev_notify;
timer->ev.sigev_value.sival_ptr = timer;
timer->slot = &table[i];
timer->ctx = ctx;
timer->error = 0;
if (timer_create(CLOCK_REALTIME, &timer->ev, &timer->id) < 0) {
goto error_timer_create;
}
2023-12-24 00:11:00 -05:00
}
qsort(schedule + 1, count, sizeof(hexagram_schedule_timer), _timer_cmp);
2023-12-27 14:14:25 -05:00
return schedule;
error_timer_create:
while (--i) {
hexagram_schedule_timer *timer = _timer(schedule, i);
timer_delete(timer->id);
}
2023-12-27 14:14:25 -05:00
free(schedule);
2023-12-24 00:11:00 -05:00
error_malloc_schedule:
return NULL;
}
void hexagram_schedule_destroy(hexagram_schedule *schedule) {
size_t i;
for (i=0; i<schedule->count; i++) {
hexagram_schedule_timer *timer = _timer(schedule, i);
_timer_stop(timer);
timer_delete(timer->id);
2023-12-24 00:11:00 -05:00
}
free(schedule);
}
int hexagram_schedule_run(hexagram_schedule *schedule) {
size_t i;
for (i=0; i<schedule->count; i++) {
hexagram_schedule_timer *timer = _timer(schedule, i);
if (_timer_set(timer, 1000 * timer->slot->interval_us) < 0) {
goto error_timer_set;
}
}
return 0;
error_timer_set:
return -1;
}
int hexagram_schedule_stop(hexagram_schedule *schedule) {
size_t i;
for (i=0; i<schedule->count; i++) {
hexagram_schedule_timer *timer = _timer(schedule, i);
if (_timer_stop(timer) < 0) {
goto error_timer_stop;
}
}
return 0;
error_timer_stop:
return -1;
}
int hexagram_schedule_error(hexagram_schedule *schedule) {
size_t i;
for (i=0; i<schedule->count; i++) {
hexagram_schedule_timer *timer = _timer(schedule, i);
if (timer->error != 0) {
return timer->error;
}
}
return 0;
}