typedef enum EventSourceType {
SOURCE_IO,
SOURCE_TIME_REALTIME,
+ SOURCE_TIME_BOOTTIME,
SOURCE_TIME_MONOTONIC,
SOURCE_TIME_REALTIME_ALARM,
SOURCE_TIME_BOOTTIME_ALARM,
_SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
} EventSourceType;
-#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
+#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
struct sd_event_source {
unsigned n_ref;
Prioq *earliest;
Prioq *latest;
usec_t next;
+
+ bool needs_rearm:1;
};
struct sd_event {
Prioq *pending;
Prioq *prepare;
- /* timerfd_create() only supports these four clocks so far. We
+ /* timerfd_create() only supports these five clocks so far. We
* can add support for more clocks when the kernel learns to
* deal with them, too. */
struct clock_data realtime;
+ struct clock_data boottime;
struct clock_data monotonic;
struct clock_data realtime_alarm;
struct clock_data boottime_alarm;
safe_close(e->watchdog_fd);
free_clock_data(&e->realtime);
+ free_clock_data(&e->boottime);
free_clock_data(&e->monotonic);
free_clock_data(&e->realtime_alarm);
free_clock_data(&e->boottime_alarm);
return -ENOMEM;
e->n_ref = 1;
- e->signal_fd = e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
- e->realtime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = (usec_t) -1;
+ e->signal_fd = e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
+ e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY;
e->original_pid = getpid();
- e->perturb = (usec_t) -1;
+ e->perturb = USEC_INFINITY;
assert_se(sigemptyset(&e->sigset) == 0);
case SOURCE_TIME_REALTIME:
return CLOCK_REALTIME;
+ case SOURCE_TIME_BOOTTIME:
+ return CLOCK_BOOTTIME;
+
case SOURCE_TIME_MONOTONIC:
return CLOCK_MONOTONIC;
case CLOCK_REALTIME:
return SOURCE_TIME_REALTIME;
+ case CLOCK_BOOTTIME:
+ return SOURCE_TIME_BOOTTIME;
+
case CLOCK_MONOTONIC:
return SOURCE_TIME_MONOTONIC;
case SOURCE_TIME_REALTIME:
return &e->realtime;
+ case SOURCE_TIME_BOOTTIME:
+ return &e->boottime;
+
case SOURCE_TIME_MONOTONIC:
return &e->monotonic;
break;
case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM: {
prioq_remove(d->earliest, s, &s->time.earliest_index);
prioq_remove(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
break;
}
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
}
return 0;
s->n_ref = 1;
s->event = e;
+ s->floating = floating;
s->type = type;
s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
- s->floating = floating;
if (!floating)
sd_event_ref(e);
r = source_io_register(s, s->enabled, events);
if (r < 0) {
source_free(s);
- return -errno;
+ return r;
}
if (ret)
bit. Here, we calculate a perturbation usec offset from the
boot ID. */
- if (_likely_(e->perturb != (usec_t) -1))
+ if (_likely_(e->perturb != USEC_INFINITY))
return;
if (sd_id128_get_boot(&bootid) >= 0)
s->userdata = userdata;
s->enabled = SD_EVENT_ONESHOT;
+ d->needs_rearm = true;
+
r = prioq_put(d->earliest, s, &s->time.earliest_index);
if (r < 0)
goto fail;
r = event_update_signal_fd(e);
if (r < 0) {
source_free(s);
- return -errno;
+ return r;
}
}
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
- if (s->io.events == events)
+ /* edge-triggered updates are never skipped, so we can reset edges */
+ if (s->io.events == events && !(events & EPOLLET))
return 0;
if (s->enabled != SD_EVENT_OFF) {
break;
case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM: {
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
break;
}
break;
case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM: {
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
break;
}
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
return 0;
}
assert(d);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
return 0;
}
assert(e);
assert(d);
+ if (!d->needs_rearm)
+ return 0;
+ else
+ d->needs_rearm = false;
+
a = prioq_peek(d->earliest);
if (!a || a->enabled == SD_EVENT_OFF) {
if (d->fd < 0)
return 0;
- if (d->next == (usec_t) -1)
+ if (d->next == USEC_INFINITY)
return 0;
/* disarm */
if (r < 0)
return r;
- d->next = (usec_t) -1;
+ d->next = USEC_INFINITY;
return 0;
}
return -EIO;
if (next)
- *next = (usec_t) -1;
+ *next = USEC_INFINITY;
return 0;
}
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
+ d->needs_rearm = true;
}
return 0;
int r;
assert(e);
- assert(e->signal_sources);
assert_return(events == EPOLLIN, -EIO);
for (;;) {
struct signalfd_siginfo si;
ssize_t ss;
- sd_event_source *s;
+ sd_event_source *s = NULL;
ss = read(e->signal_fd, &si, sizeof(si));
if (ss < 0) {
read_one = true;
- s = e->signal_sources[si.ssi_signo];
if (si.ssi_signo == SIGCHLD) {
r = process_child(e);
if (r < 0)
return r;
- if (r > 0 || !s)
+ if (r > 0)
continue;
- } else
- if (!s)
- return -EIO;
+ }
+
+ if (e->signal_sources)
+ s = e->signal_sources[si.ssi_signo];
+
+ if (!s)
+ continue;
s->signal.siginfo = si;
r = source_set_pending(s, true);
break;
case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM:
unsigned ev_queue_max;
sd_event_source *p;
int r, i, m;
+ bool timedout;
assert_return(e, -EINVAL);
assert_return(!event_pid_changed(e), -ECHILD);
if (r < 0)
goto finish;
+ r = event_arm_timer(e, &e->boottime);
+ if (r < 0)
+ goto finish;
+
r = event_arm_timer(e, &e->monotonic);
if (r < 0)
goto finish;
goto finish;
}
+ timedout = m == 0;
+
dual_timestamp_get(&e->timestamp);
e->timestamp_boottime = now(CLOCK_BOOTTIME);
if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_REALTIME))
r = flush_timer(e, e->realtime.fd, ev_queue[i].events, &e->realtime.next);
+ else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_BOOTTIME))
+ r = flush_timer(e, e->boottime.fd, ev_queue[i].events, &e->boottime.next);
else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_MONOTONIC))
r = flush_timer(e, e->monotonic.fd, ev_queue[i].events, &e->monotonic.next);
else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_REALTIME_ALARM))
if (r < 0)
goto finish;
+ r = process_timer(e, e->timestamp_boottime, &e->boottime);
+ if (r < 0)
+ goto finish;
+
r = process_timer(e, e->timestamp.monotonic, &e->monotonic);
if (r < 0)
goto finish;
p = event_next_pending(e);
if (!p) {
- r = 1;
+ r = !timedout;
goto finish;
}
*usec = e->timestamp.monotonic;
break;
+ case CLOCK_BOOTTIME:
case CLOCK_BOOTTIME_ALARM:
*usec = e->timestamp_boottime;
break;