#include #include #include #include #include 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); } 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); } } hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table, size_t count, void *ctx) { hexagram_schedule *schedule; size_t i; if ((schedule = malloc(sizeof(*schedule) + count * sizeof(hexagram_schedule_timer))) == 0) { goto error_malloc_schedule; } 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_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: return NULL; } void hexagram_schedule_destroy(hexagram_schedule *schedule) { size_t i; for (i=0; icount; i++) { hexagram_schedule_timer *timer = _timer(schedule, i); _timer_stop(timer); timer_delete(timer->id); } free(schedule); } int hexagram_schedule_run(hexagram_schedule *schedule) { 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) { 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) { size_t i; for (i=0; icount; i++) { hexagram_schedule_timer *timer = _timer(schedule, i); if (timer->error != 0) { return timer->error; } } return 0; }