sd_event *event;
void *userdata;
- sd_prepare_handler_t prepare;
+ sd_event_handler_t prepare;
EventSourceType type:4;
int enabled:3;
union {
struct {
- sd_io_handler_t callback;
+ sd_event_io_handler_t callback;
int fd;
uint32_t events;
uint32_t revents;
bool registered:1;
} io;
struct {
- sd_time_handler_t callback;
+ sd_event_time_handler_t callback;
usec_t next, accuracy;
unsigned earliest_index;
unsigned latest_index;
} time;
struct {
- sd_signal_handler_t callback;
+ sd_event_signal_handler_t callback;
struct signalfd_siginfo siginfo;
int sig;
} signal;
struct {
- sd_child_handler_t callback;
+ sd_event_child_handler_t callback;
siginfo_t siginfo;
pid_t pid;
int options;
} child;
struct {
- sd_defer_handler_t callback;
+ sd_event_handler_t callback;
} defer;
struct {
- sd_quit_handler_t callback;
+ sd_event_handler_t callback;
unsigned prioq_index;
} quit;
};
if (x->time.next < y->time.next)
return -1;
if (x->time.next > y->time.next)
- return -1;
+ return 1;
/* Stability for the rest */
if (x < y)
if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
return -1;
if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
- return -1;
+ return 1;
/* Stability for the rest */
if (x < y)
} else
assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
+ if (s->type == SOURCE_REALTIME) {
+ prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
+ prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
+ } else if (s->type == SOURCE_MONOTONIC) {
+ prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
+ prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
+ }
+
return 0;
}
sd_event *e,
int fd,
uint32_t events,
- sd_io_handler_t callback,
+ sd_event_io_handler_t callback,
void *userdata,
sd_event_source **ret) {
assert_return(e, -EINVAL);
assert_return(fd >= 0, -EINVAL);
- assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP)), -EINVAL);
+ assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(callback, -EINVAL);
assert_return(ret, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
}
/* When we sleep for longer, we try to realign the wakeup to
- the same time wihtin each second, so that events all across
- the system can be coalesced into a single CPU
- wakeup. However, let's take some system-specific randomness
- for this value, so that in a network of systems with synced
- clocks timer events are distributed a bit. Here, we
- calculate a perturbation usec offset from the boot ID. */
+ the same time wihtin each minute/second/250ms, so that
+ events all across the system can be coalesced into a single
+ CPU wakeup. However, let's take some system-specific
+ randomness for this value, so that in a network of systems
+ with synced clocks timer events are distributed a
+ bit. Here, we calculate a perturbation usec offset from the
+ boot ID. */
if (sd_id128_get_boot(&bootid) >= 0)
- e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_SEC;
+ e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE;
*timer_fd = fd;
return 0;
Prioq **latest,
uint64_t usec,
uint64_t accuracy,
- sd_time_handler_t callback,
+ sd_event_time_handler_t callback,
void *userdata,
sd_event_source **ret) {
_public_ int sd_event_add_monotonic(sd_event *e,
uint64_t usec,
uint64_t accuracy,
- sd_time_handler_t callback,
+ sd_event_time_handler_t callback,
void *userdata,
sd_event_source **ret) {
_public_ int sd_event_add_realtime(sd_event *e,
uint64_t usec,
uint64_t accuracy,
- sd_time_handler_t callback,
+ sd_event_time_handler_t callback,
void *userdata,
sd_event_source **ret) {
_public_ int sd_event_add_signal(
sd_event *e,
int sig,
- sd_signal_handler_t callback,
+ sd_event_signal_handler_t callback,
void *userdata,
sd_event_source **ret) {
sd_event *e,
pid_t pid,
int options,
- sd_child_handler_t callback,
+ sd_event_child_handler_t callback,
void *userdata,
sd_event_source **ret) {
_public_ int sd_event_add_defer(
sd_event *e,
- sd_defer_handler_t callback,
+ sd_event_handler_t callback,
void *userdata,
sd_event_source **ret) {
_public_ int sd_event_add_quit(
sd_event *e,
- sd_quit_handler_t callback,
+ sd_event_handler_t callback,
void *userdata,
sd_event_source **ret) {
return NULL;
}
-_public_ sd_event *sd_event_get(sd_event_source *s) {
+_public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
assert_return(s, NULL);
return s->event;
assert_return(s, -EINVAL);
assert_return(s->type == SOURCE_IO, -EDOM);
- assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP)), -EINVAL);
+ assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
}
s->io.events = events;
+ source_set_pending(s, false);
return 0;
}
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
- if (s->time.next == usec)
- return 0;
-
s->time.next = usec;
+
source_set_pending(s, false);
if (s->type == SOURCE_REALTIME) {
if (usec == 0)
usec = DEFAULT_ACCURACY_USEC;
- if (s->time.accuracy == usec)
- return 0;
-
s->time.accuracy = usec;
+ source_set_pending(s, false);
+
if (s->type == SOURCE_REALTIME)
prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
else
return 0;
}
-_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback) {
+_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
int r;
assert_return(s, -EINVAL);
dispatch as much as possible on the entire system.
We implement this by waking up everywhere at the same time
- within any given second if we can, synchronised via the
+ within any given minute if we can, synchronised via the
perturbation value determined from the boot ID. If we can't,
- then we try to find the same spot in every a 250ms
+ then we try to find the same spot in every 1s and then 250ms
step. Otherwise, we pick the last possible time to wake up.
*/
- c = (b / USEC_PER_SEC) * USEC_PER_SEC + e->perturb;
+ c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb;
+ if (c >= b) {
+ if (_unlikely_(c < USEC_PER_MINUTE))
+ return b;
+
+ c -= USEC_PER_MINUTE;
+ }
+
+ if (c >= a)
+ return c;
+
+ c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC);
if (c >= b) {
if (_unlikely_(c < USEC_PER_SEC))
return b;
a = prioq_peek(earliest);
if (!a || a->enabled == SD_EVENT_OFF) {
+ if (timer_fd < 0)
+ return 0;
+
if (*next == (usec_t) -1)
return 0;
if (r < 0)
goto finish;
- if (event_next_pending(e) || e->need_process_child)
- timeout = 0;
+ r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
+ if (r < 0)
+ goto finish;
- if (timeout > 0) {
- r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
- if (r < 0)
- goto finish;
+ r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
+ if (r < 0)
+ goto finish;
- r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
- if (r < 0)
- goto finish;
- }
+ if (event_next_pending(e) || e->need_process_child)
+ timeout = 0;
m = epoll_wait(e->epoll_fd, ev_queue, EPOLL_QUEUE_MAX,
timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));