From 4f3727641485e1cd76caccd4f4f8c4060c2b55fc Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Wed, 27 Dec 2023 18:31:02 -0500 Subject: [PATCH] Use separate timers for each schedule slot --- include/hexagram/schedule.h | 18 ++-- src/schedule.c | 165 ++++++++++++++++++++---------------- 2 files changed, 101 insertions(+), 82 deletions(-) diff --git a/include/hexagram/schedule.h b/include/hexagram/schedule.h index 338eab3..0d8847f 100644 --- a/include/hexagram/schedule.h +++ b/include/hexagram/schedule.h @@ -17,18 +17,18 @@ typedef struct _hexagram_schedule_slot { hexagram_schedule_handler handler; } hexagram_schedule_slot; -typedef struct _hexagram_schedule { +typedef struct _hexagram_schedule_timer { + timer_t id; struct sigevent ev; struct itimerspec ts; - timer_t timer; - - size_t current, - count; - - hexagram_schedule_slot *table; - + hexagram_schedule_slot *slot; void *ctx; int error; +} hexagram_schedule_timer; + +typedef struct _hexagram_schedule { + hexagram_schedule_slot *table; + size_t count; } hexagram_schedule; hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table, @@ -37,8 +37,6 @@ hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table, void hexagram_schedule_destroy(hexagram_schedule *schedule); -void hexagram_schedule_reset(hexagram_schedule *schedule); - int hexagram_schedule_run(hexagram_schedule *schedule); int hexagram_schedule_stop(hexagram_schedule *schedule); diff --git a/src/schedule.c b/src/schedule.c index 78773d9..fd78a34 100644 --- a/src/schedule.c +++ b/src/schedule.c @@ -5,63 +5,40 @@ #include -static int _slot_cmp(const void *item_a, const void *item_b) { - hexagram_schedule_slot *a = (hexagram_schedule_slot *)item_a, - *b = (hexagram_schedule_slot *)item_b; - - return a->interval_us < b->interval_us? -1: - a->interval_us > b->interval_us? 1: 0; -} - -static inline hexagram_schedule_slot *_slot(hexagram_schedule *schedule, size_t i) { - return ((hexagram_schedule_slot **)(schedule + 1))[i]; +static inline hexagram_schedule_timer *_timer(hexagram_schedule *schedule, size_t i) { + return &((hexagram_schedule_timer *)(schedule + 1))[i]; }; -static inline time_t _slot_interval_ns(hexagram_schedule *schedule, size_t i) { - return 1000 * _slot(schedule, i)->interval_us; +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 _set_interval(hexagram_schedule *schedule, time_t int_nsec) { - schedule->ts.it_value.tv_sec = 0; - schedule->ts.it_value.tv_nsec = int_nsec; - schedule->ts.it_interval.tv_sec = 0; - schedule->ts.it_interval.tv_nsec = int_nsec; +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(schedule->timer, 0, &schedule->ts, NULL); + return timer_settime(timer->id, 0, &timer->ts, NULL); } -static inline int _slot_set_interval(hexagram_schedule *schedule, size_t i) { - return _set_interval(schedule, _slot_interval_ns(schedule, i)); +static inline int _timer_stop(hexagram_schedule_timer *timer) { + return _timer_set(timer, 0); } static void _ev_notify(union sigval sv) { - hexagram_schedule *schedule = sv.sival_ptr; - time_t last = -1; + hexagram_schedule_timer *timer = sv.sival_ptr; + hexagram_schedule_slot *slot = timer->slot; - while (schedule->current < schedule->count) { - hexagram_schedule_slot *slot = _slot(schedule, schedule->current); - time_t delay = slot->interval_us; + if (slot->handler(&slot->frame, timer->ctx) < 0) { + timer->error = errno; - if (slot->handler(&slot->frame, schedule->ctx) < 0) { - schedule->error = errno; - - break; - } - - schedule->current++; - - if (last >= 0 && last != delay) { - _slot_set_interval(schedule, schedule->current); - - return; - } - - last = delay; + _timer_stop(timer); } - - schedule->current = 0; - - _slot_set_interval(schedule, schedule->current); } hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table, @@ -70,35 +47,42 @@ hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table, hexagram_schedule *schedule; size_t i; - if ((schedule = malloc(sizeof(*schedule) + count * sizeof(void *))) == 0) { + if ((schedule = malloc(sizeof(*schedule) + count * sizeof(hexagram_schedule_timer))) == 0) { goto error_malloc_schedule; } - memset(&schedule->ev, '\0', sizeof(struct sigevent)); - - schedule->ev.sigev_notify = SIGEV_THREAD; - schedule->ev.sigev_notify_function = _ev_notify; - schedule->ev.sigev_value.sival_ptr = schedule; - - schedule->current = 0; - schedule->count = count; - schedule->table = table; - schedule->ctx = ctx; - schedule->error = 0; - - if (timer_create(CLOCK_REALTIME, &schedule->ev, &schedule->timer) < 0) { - goto error_timer_create; - } + schedule->table = table; + schedule->count = count; for (i=0; iev, '\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; + } } - qsort(schedule + 1, count, sizeof(hexagram_schedule_slot *), _slot_cmp); + qsort(schedule + 1, count, sizeof(hexagram_schedule_timer), _timer_cmp); return schedule; error_timer_create: + while (--i) { + hexagram_schedule_timer *timer = _timer(schedule, i); + + timer_delete(timer->id); + } + free(schedule); error_malloc_schedule: @@ -106,26 +90,63 @@ error_malloc_schedule: } void hexagram_schedule_destroy(hexagram_schedule *schedule) { - if (schedule->timer) { - timer_delete(schedule->timer); + size_t i; + + for (i=0; icount; i++) { + hexagram_schedule_timer *timer = _timer(schedule, i); + + _timer_stop(timer); + + timer_delete(timer->id); } free(schedule); } -void hexagram_schedule_reset(hexagram_schedule *schedule) { - schedule->current = 0; - schedule->error = 0; -} - int hexagram_schedule_run(hexagram_schedule *schedule) { - return _slot_set_interval(schedule, schedule->current); + size_t i; + + for (i=0; icount; 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) { - return _set_interval(schedule, 0); + size_t i; + + for (i=0; icount; 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) { - return schedule->error; + size_t i; + + for (i=0; icount; i++) { + hexagram_schedule_timer *timer = _timer(schedule, i); + + if (timer->error != 0) { + return timer->error; + } + } + + return 0; }