From 6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Mar 2014 02:49:09 +0100 Subject: [PATCH] sd-event: rework API to support CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM, too --- src/core/job.c | 14 +- src/core/manager.c | 7 +- src/core/mount.c | 7 +- src/core/scope.c | 7 +- src/core/service.c | 14 +- src/core/socket.c | 7 +- src/core/swap.c | 7 +- src/core/timer.c | 14 +- src/journal/journald-server.c | 9 +- src/libsystemd-network/sd-dhcp-client.c | 62 +-- src/libsystemd-network/sd-ipv4ll.c | 17 +- src/libsystemd-network/test-dhcp-client.c | 7 +- src/libsystemd/libsystemd.sym.m4 | 7 +- src/libsystemd/sd-bus/sd-bus.c | 2 +- src/libsystemd/sd-event/sd-event.c | 462 ++++++++++++++-------- src/libsystemd/sd-event/test-event.c | 2 +- src/libsystemd/sd-rtnl/sd-rtnl.c | 2 +- src/login/logind-dbus.c | 7 +- src/login/logind-session.c | 6 +- src/login/logind.c | 7 +- src/systemd/sd-event.h | 8 +- src/timedate/timedate-sntp.c | 7 +- 22 files changed, 443 insertions(+), 239 deletions(-) diff --git a/src/core/job.c b/src/core/job.c index 8e98bd93a..35a9de6ee 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -873,7 +873,12 @@ int job_start_timer(Job *j) { if (j->unit->job_timeout <= 0) return 0; - r = sd_event_add_monotonic(j->manager->event, &j->timer_event_source, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j); + r = sd_event_add_time( + j->manager->event, + &j->timer_event_source, + CLOCK_MONOTONIC, + j->begin_usec + j->unit->job_timeout, 0, + job_dispatch_timer, j); if (r < 0) return r; @@ -1061,7 +1066,12 @@ int job_coldplug(Job *j) { if (j->timer_event_source) j->timer_event_source = sd_event_source_unref(j->timer_event_source); - r = sd_event_add_monotonic(j->manager->event, &j->timer_event_source, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j); + r = sd_event_add_time( + j->manager->event, + &j->timer_event_source, + CLOCK_MONOTONIC, + j->begin_usec + j->unit->job_timeout, 0, + job_dispatch_timer, j); if (r < 0) log_debug("Failed to restart timeout for job: %s", strerror(-r)); diff --git a/src/core/manager.c b/src/core/manager.c index fd22d4863..360a65a49 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -102,7 +102,12 @@ static int manager_watch_jobs_in_progress(Manager *m) { return 0; next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC; - return sd_event_add_monotonic(m->event, &m->jobs_in_progress_event_source, next, 0, manager_dispatch_jobs_in_progress, m); + return sd_event_add_time( + m->event, + &m->jobs_in_progress_event_source, + CLOCK_MONOTONIC, + next, 0, + manager_dispatch_jobs_in_progress, m); } #define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1)) diff --git a/src/core/mount.c b/src/core/mount.c index 21b794294..a97983707 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -163,7 +163,12 @@ static int mount_arm_timer(Mount *m) { return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(m)->manager->event, &m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec, 0, mount_dispatch_timer, m); + return sd_event_add_time( + UNIT(m)->manager->event, + &m->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + m->timeout_usec, 0, + mount_dispatch_timer, m); } static void mount_unwatch_control_pid(Mount *m) { diff --git a/src/core/scope.c b/src/core/scope.c index aa4978de4..e8f9e8dd7 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -83,7 +83,12 @@ static int scope_arm_timer(Scope *s) { return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s); + return sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, + scope_dispatch_timer, s); } static void scope_set_state(Scope *s, ScopeState state) { diff --git a/src/core/service.c b/src/core/service.c index 78a2e06ff..67467b2d6 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -257,7 +257,12 @@ static void service_start_watchdog(Service *s) { r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ONESHOT); } else { - r = sd_event_add_monotonic(UNIT(s)->manager->event, &s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec, 0, service_dispatch_watchdog, s); + r = sd_event_add_time( + UNIT(s)->manager->event, + &s->watchdog_event_source, + CLOCK_MONOTONIC, + s->watchdog_timestamp.monotonic + s->watchdog_usec, 0, + service_dispatch_watchdog, s); if (r < 0) { log_warning_unit(UNIT(s)->id, "%s failed to add watchdog timer: %s", UNIT(s)->id, strerror(-r)); return; @@ -345,7 +350,12 @@ static int service_arm_timer(Service *s, usec_t usec) { return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + usec, 0, service_dispatch_timer, s); + return sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + usec, 0, + service_dispatch_timer, s); } #ifdef HAVE_SYSV_COMPAT diff --git a/src/core/socket.c b/src/core/socket.c index 3708a86f4..7c18a2b75 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -168,7 +168,12 @@ static int socket_arm_timer(Socket *s) { return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s); + return sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + s->timeout_usec, 0, + socket_dispatch_timer, s); } static int socket_instantiate_service(Socket *s) { diff --git a/src/core/swap.c b/src/core/swap.c index 7da742e87..10eed6d25 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -179,7 +179,12 @@ static int swap_arm_timer(Swap *s) { return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, swap_dispatch_timer, s); + return sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + s->timeout_usec, 0, + swap_dispatch_timer, s); } static int swap_add_device_links(Swap *s) { diff --git a/src/core/timer.c b/src/core/timer.c index 8ed0291ee..95416f3e7 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -399,7 +399,12 @@ static void timer_enter_waiting(Timer *t, bool initial) { r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT); } else - r = sd_event_add_monotonic(UNIT(t)->manager->event, &t->monotonic_event_source, t->next_elapse_monotonic, t->accuracy_usec, timer_dispatch, t); + r = sd_event_add_time( + UNIT(t)->manager->event, + &t->monotonic_event_source, + CLOCK_MONOTONIC, + t->next_elapse_monotonic, t->accuracy_usec, + timer_dispatch, t); if (r < 0) goto fail; @@ -421,7 +426,12 @@ static void timer_enter_waiting(Timer *t, bool initial) { r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT); } else - r = sd_event_add_realtime(UNIT(t)->manager->event, &t->realtime_event_source, t->next_elapse_realtime, t->accuracy_usec, timer_dispatch, t); + r = sd_event_add_time( + UNIT(t)->manager->event, + &t->realtime_event_source, + CLOCK_REALTIME, + t->next_elapse_realtime, t->accuracy_usec, + timer_dispatch, t); if (r < 0) goto fail; diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index c2a60d5e8..6da81e7cd 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1377,14 +1377,19 @@ int server_schedule_sync(Server *s, int priority) { if (s->sync_interval_usec > 0) { usec_t when; - r = sd_event_get_now_monotonic(s->event, &when); + r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); if (r < 0) return r; when += s->sync_interval_usec; if (!s->sync_event_source) { - r = sd_event_add_monotonic(s->event, &s->sync_event_source, when, 0, server_dispatch_sync, s); + r = sd_event_add_time( + s->event, + &s->sync_event_source, + CLOCK_MONOTONIC, + when, 0, + server_dispatch_sync, s); if (r < 0) return r; diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 0728a1555..0be6212a4 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -300,7 +300,7 @@ static int client_send_discover(sd_dhcp_client *client) { assert(client); - r = sd_event_get_now_monotonic(client->event, &time_now); + r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now); if (r < 0) return r; assert(time_now >= client->start_time); @@ -427,7 +427,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, assert(client); assert(client->event); - r = sd_event_get_now_monotonic(client->event, &time_now); + r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now); if (r < 0) goto error; @@ -476,11 +476,11 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, client->timeout_resend = sd_event_source_unref(client->timeout_resend); - r = sd_event_add_monotonic(client->event, - &client->timeout_resend, - next_timeout, - 10 * USEC_PER_MSEC, - client_timeout_resend, client); + r = sd_event_add_time(client->event, + &client->timeout_resend, + CLOCK_MONOTONIC, + next_timeout, 10 * USEC_PER_MSEC, + client_timeout_resend, client); if (r < 0) goto error; @@ -560,9 +560,11 @@ static int client_initialize_events(sd_dhcp_client *client, client->timeout_resend = sd_event_source_unref(client->timeout_resend); - r = sd_event_add_monotonic(client->event, - &client->timeout_resend, 0, 0, - client_timeout_resend, client); + r = sd_event_add_time(client->event, + &client->timeout_resend, + CLOCK_MONOTONIC, + 0, 0, + client_timeout_resend, client); if (r < 0) goto error; @@ -806,7 +808,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { if (client->lease->lifetime == 0xffffffff) return 0; - r = sd_event_get_now_monotonic(client->event, &time_now); + r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now); if (r < 0) return r; assert(client->request_sent <= time_now); @@ -856,10 +858,10 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { } /* arm lifetime timeout */ - r = sd_event_add_monotonic(client->event, - &client->timeout_expire, lifetime_timeout, - 10 * USEC_PER_MSEC, - client_timeout_expire, client); + r = sd_event_add_time(client->event, &client->timeout_expire, + CLOCK_MONOTONIC, + lifetime_timeout, 10 * USEC_PER_MSEC, + client_timeout_expire, client); if (r < 0) return r; @@ -877,11 +879,12 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { return 0; /* arm T2 timeout */ - r = sd_event_add_monotonic(client->event, - &client->timeout_t2, - t2_timeout, - 10 * USEC_PER_MSEC, - client_timeout_t2, client); + r = sd_event_add_time(client->event, + &client->timeout_t2, + CLOCK_MONOTONIC, + t2_timeout, + 10 * USEC_PER_MSEC, + client_timeout_t2, client); if (r < 0) return r; @@ -899,11 +902,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { return 0; /* arm T1 timeout */ - r = sd_event_add_monotonic(client->event, - &client->timeout_t1, - t1_timeout, - 10 * USEC_PER_MSEC, - client_timeout_t1, client); + r = sd_event_add_time(client->event, + &client->timeout_t1, + CLOCK_MONOTONIC, + t1_timeout, 10 * USEC_PER_MSEC, + client_timeout_t1, client); if (r < 0) return r; @@ -964,10 +967,11 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, client->state = DHCP_STATE_REQUESTING; client->attempt = 1; - r = sd_event_add_monotonic(client->event, - &client->timeout_resend, 0, - 0, client_timeout_resend, - client); + r = sd_event_add_time(client->event, + &client->timeout_resend, + CLOCK_MONOTONIC, + 0, 0, + client_timeout_resend, client); if (r < 0) goto error; diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 7431af729..a201139b0 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -165,7 +165,7 @@ static int ipv4ll_timer(sd_event_source *s, uint64_t usec, void *userdata) { return 0; } -static void ipv4ll_set_next_wakeup (sd_ipv4ll *ll, int sec, int random_sec) { +static void ipv4ll_set_next_wakeup(sd_ipv4ll *ll, int sec, int random_sec) { usec_t next_timeout = 0; usec_t time_now = 0; @@ -178,7 +178,7 @@ static void ipv4ll_set_next_wakeup (sd_ipv4ll *ll, int sec, int random_sec) { if (random_sec) next_timeout += random_u32() % (random_sec * USEC_PER_SEC); - if (sd_event_get_now_monotonic(ll->event, &time_now) < 0) + if (sd_event_now(ll->event, CLOCK_MONOTONIC, &time_now) < 0) time_now = now(CLOCK_MONOTONIC); ll->next_wakeup = time_now + next_timeout; @@ -278,7 +278,7 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void if (ipv4ll_arp_conflict(ll, in_packet)) { - r = sd_event_get_now_monotonic(ll->event, &time_now); + r = sd_event_now(ll->event, CLOCK_MONOTONIC, &time_now); if (r < 0) goto out; @@ -330,8 +330,8 @@ static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void if (ll->next_wakeup_valid) { ll->timer = sd_event_source_unref(ll->timer); - r = sd_event_add_monotonic(ll->event, &ll->timer, - ll->next_wakeup, 0, ipv4ll_timer, ll); + r = sd_event_add_time(ll->event, &ll->timer, CLOCK_MONOTONIC, + ll->next_wakeup, 0, ipv4ll_timer, ll); if (r < 0) goto out; @@ -530,8 +530,11 @@ int sd_ipv4ll_start (sd_ipv4ll *ll) { if (r < 0) goto out; - r = sd_event_add_monotonic(ll->event, &ll->timer, now(CLOCK_MONOTONIC), 0, - ipv4ll_timer, ll); + r = sd_event_add_time(ll->event, + &ll->timer, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC), 0, + ipv4ll_timer, ll); if (r < 0) goto out; diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index 0f7adac56..2d4d59096 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -466,9 +466,10 @@ static void test_addr_acq(sd_event *e) callback_recv = test_addr_acq_recv_discover; - assert_se(sd_event_add_monotonic(e, &test_hangcheck, - time_now + 2 * USEC_PER_SEC, 0, - test_dhcp_hangcheck, NULL) >= 0); + assert_se(sd_event_add_time(e, &test_hangcheck, + CLOCK_MONOTONIC, + time_now + 2 * USEC_PER_SEC, 0, + test_dhcp_hangcheck, NULL) >= 0); res = sd_dhcp_client_start(client); assert_se(res == 0 || res == -EINPROGRESS); diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4 index 8589d605a..d0ac64386 100644 --- a/src/libsystemd/libsystemd.sym.m4 +++ b/src/libsystemd/libsystemd.sym.m4 @@ -360,8 +360,7 @@ m4_ifdef(`ENABLE_KDBUS', sd_event_ref; sd_event_unref; sd_event_add_io; - sd_event_add_monotonic; - sd_event_add_realtime; + sd_event_add_time; sd_event_add_signal; sd_event_add_child; sd_event_add_defer; @@ -369,11 +368,10 @@ m4_ifdef(`ENABLE_KDBUS', sd_event_run; sd_event_loop; sd_event_exit; + sd_event_now; sd_event_get_state; sd_event_get_tid; sd_event_get_exit_code; - sd_event_get_now_realtime; - sd_event_get_now_monotonic; sd_event_set_watchdog; sd_event_get_watchdog; sd_event_source_ref; @@ -395,6 +393,7 @@ m4_ifdef(`ENABLE_KDBUS', sd_event_source_set_time; sd_event_source_set_time_accuracy; sd_event_source_get_time_accuracy; + sd_event_source_get_time_clock; sd_event_source_get_signal; sd_event_source_get_child_pid; sd_event_source_get_event; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index bbe61a6a8..3929b351e 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -3065,7 +3065,7 @@ _public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) { bus->event_priority = priority; - r = sd_event_add_monotonic(bus->event, &bus->time_event_source, 0, 0, time_callback, bus); + r = sd_event_add_time(bus->event, &bus->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, bus); if (r < 0) goto fail; diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 3bda7f31a..4552f4dad 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -41,16 +41,22 @@ typedef enum EventSourceType { SOURCE_IO, - SOURCE_MONOTONIC, - SOURCE_REALTIME, + SOURCE_TIME_REALTIME, + SOURCE_TIME_MONOTONIC, + SOURCE_TIME_REALTIME_ALARM, + SOURCE_TIME_BOOTTIME_ALARM, SOURCE_SIGNAL, SOURCE_CHILD, SOURCE_DEFER, SOURCE_POST, SOURCE_EXIT, - SOURCE_WATCHDOG + SOURCE_WATCHDOG, + _SOUFCE_EVENT_SOURCE_TYPE_MAX, + _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) + struct sd_event_source { unsigned n_ref; @@ -58,7 +64,7 @@ struct sd_event_source { void *userdata; sd_event_handler_t prepare; - EventSourceType type:4; + EventSourceType type:5; int enabled:3; bool pending:1; bool dispatching:1; @@ -107,30 +113,39 @@ struct sd_event_source { }; }; +struct clock_data { + int fd; + + /* For all clocks we maintain two priority queues each, one + * ordered for the earliest times the events may be + * dispatched, and one ordered by the latest times they must + * have been dispatched. The range between the top entries in + * the two prioqs is the time window we can freely schedule + * wakeups in */ + + Prioq *earliest; + Prioq *latest; + usec_t next; +}; + struct sd_event { unsigned n_ref; int epoll_fd; int signal_fd; - int realtime_fd; - int monotonic_fd; int watchdog_fd; Prioq *pending; Prioq *prepare; - /* For both clocks we maintain two priority queues each, one - * ordered for the earliest times the events may be - * dispatched, and one ordered by the latest times they must - * have been dispatched. The range between the top entries in - * the two prioqs is the time window we can freely schedule - * wakeups in */ - Prioq *monotonic_earliest; - Prioq *monotonic_latest; - Prioq *realtime_earliest; - Prioq *realtime_latest; + /* timerfd_create() only supports these four 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 monotonic; + struct clock_data realtime_alarm; + struct clock_data boottime_alarm; - usec_t realtime_next, monotonic_next; usec_t perturb; sigset_t sigset; @@ -147,6 +162,7 @@ struct sd_event { unsigned iteration; dual_timestamp timestamp; + usec_t timestamp_boottime; int state; bool exit_requested:1; @@ -234,8 +250,8 @@ static int prepare_prioq_compare(const void *a, const void *b) { static int earliest_time_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; - assert(x->type == SOURCE_MONOTONIC || x->type == SOURCE_REALTIME); - assert(y->type == SOURCE_MONOTONIC || y->type == SOURCE_REALTIME); + assert(EVENT_SOURCE_IS_TIME(x->type)); + assert(x->type == y->type); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) @@ -267,8 +283,8 @@ static int earliest_time_prioq_compare(const void *a, const void *b) { static int latest_time_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; - assert((x->type == SOURCE_MONOTONIC && y->type == SOURCE_MONOTONIC) || - (x->type == SOURCE_REALTIME && y->type == SOURCE_REALTIME)); + assert(EVENT_SOURCE_IS_TIME(x->type)); + assert(x->type == y->type); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) @@ -324,6 +340,14 @@ static int exit_prioq_compare(const void *a, const void *b) { return 0; } +static void free_clock_data(struct clock_data *d) { + assert(d); + + safe_close(d->fd); + prioq_free(d->earliest); + prioq_free(d->latest); +} + static void event_free(sd_event *e) { assert(e); assert(e->n_sources == 0); @@ -333,16 +357,15 @@ static void event_free(sd_event *e) { safe_close(e->epoll_fd); safe_close(e->signal_fd); - safe_close(e->realtime_fd); - safe_close(e->monotonic_fd); safe_close(e->watchdog_fd); + free_clock_data(&e->realtime); + free_clock_data(&e->monotonic); + free_clock_data(&e->realtime_alarm); + free_clock_data(&e->boottime_alarm); + prioq_free(e->pending); prioq_free(e->prepare); - prioq_free(e->monotonic_earliest); - prioq_free(e->monotonic_latest); - prioq_free(e->realtime_earliest); - prioq_free(e->realtime_latest); prioq_free(e->exit); free(e->signal_sources); @@ -363,9 +386,10 @@ _public_ int sd_event_new(sd_event** ret) { return -ENOMEM; e->n_ref = 1; - e->signal_fd = e->realtime_fd = e->monotonic_fd = e->watchdog_fd = e->epoll_fd = -1; - e->realtime_next = e->monotonic_next = (usec_t) -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->original_pid = getpid(); + e->perturb = (usec_t) -1; assert_se(sigemptyset(&e->sigset) == 0); @@ -469,6 +493,70 @@ static int source_io_register( return 0; } +static clockid_t event_source_type_to_clock(EventSourceType t) { + + switch (t) { + + case SOURCE_TIME_REALTIME: + return CLOCK_REALTIME; + + case SOURCE_TIME_MONOTONIC: + return CLOCK_MONOTONIC; + + case SOURCE_TIME_REALTIME_ALARM: + return CLOCK_REALTIME_ALARM; + + case SOURCE_TIME_BOOTTIME_ALARM: + return CLOCK_BOOTTIME_ALARM; + + default: + return (clockid_t) -1; + } +} + +static EventSourceType clock_to_event_source_type(clockid_t clock) { + + switch (clock) { + + case CLOCK_REALTIME: + return SOURCE_TIME_REALTIME; + + case CLOCK_MONOTONIC: + return SOURCE_TIME_MONOTONIC; + + case CLOCK_REALTIME_ALARM: + return SOURCE_TIME_REALTIME_ALARM; + + case CLOCK_BOOTTIME_ALARM: + return SOURCE_TIME_BOOTTIME_ALARM; + + default: + return _SOURCE_EVENT_SOURCE_TYPE_INVALID; + } +} + +static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) { + assert(e); + + switch (t) { + + case SOURCE_TIME_REALTIME: + return &e->realtime; + + case SOURCE_TIME_MONOTONIC: + return &e->monotonic; + + case SOURCE_TIME_REALTIME_ALARM: + return &e->realtime_alarm; + + case SOURCE_TIME_BOOTTIME_ALARM: + return &e->boottime_alarm; + + default: + return NULL; + } +} + static void source_free(sd_event_source *s) { assert(s); @@ -483,15 +571,19 @@ static void source_free(sd_event_source *s) { break; - case SOURCE_MONOTONIC: - prioq_remove(s->event->monotonic_earliest, s, &s->time.earliest_index); - prioq_remove(s->event->monotonic_latest, s, &s->time.latest_index); - break; + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + d = event_get_clock_data(s->event, s->type); + assert(d); - case SOURCE_REALTIME: - prioq_remove(s->event->realtime_earliest, s, &s->time.earliest_index); - prioq_remove(s->event->realtime_latest, s, &s->time.latest_index); + prioq_remove(d->earliest, s, &s->time.earliest_index); + prioq_remove(d->latest, s, &s->time.latest_index); break; + } case SOURCE_SIGNAL: if (s->signal.sig > 0) { @@ -531,7 +623,7 @@ static void source_free(sd_event_source *s) { prioq_remove(s->event->exit, s, &s->exit.prioq_index); break; - case SOURCE_WATCHDOG: + default: assert_not_reached("Wut? I shouldn't exist."); } @@ -570,12 +662,14 @@ static int source_set_pending(sd_event_source *s, bool b) { } 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); + if (EVENT_SOURCE_IS_TIME(s->type)) { + struct clock_data *d; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); } return 0; @@ -641,26 +735,25 @@ _public_ int sd_event_add_io( static int event_setup_timer_fd( sd_event *e, - EventSourceType type, - int *timer_fd, - clockid_t id) { + struct clock_data *d, + clockid_t clock) { sd_id128_t bootid = {}; struct epoll_event ev = {}; int r, fd; assert(e); - assert(timer_fd); + assert(d); - if (_likely_(*timer_fd >= 0)) + if (_likely_(d->fd >= 0)) return 0; - fd = timerfd_create(id, TFD_NONBLOCK|TFD_CLOEXEC); + fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC); if (fd < 0) return -errno; ev.events = EPOLLIN; - ev.data.ptr = INT_TO_PTR(type); + ev.data.ptr = INT_TO_PTR(clock_to_event_source_type(clock)); r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev); if (r < 0) { @@ -668,6 +761,8 @@ static int event_setup_timer_fd( return -errno; } + d->fd = fd; + /* When we sleep for longer, we try to realign the wakeup to the same time wihtin each minute/second/250ms, so that events all across the system can be coalesced into a single @@ -677,55 +772,55 @@ static int event_setup_timer_fd( 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_MINUTE; + if (e->perturb == (usec_t) -1) + if (sd_id128_get_boot(&bootid) >= 0) + e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE; - *timer_fd = fd; return 0; } -static int event_add_time_internal( +_public_ int sd_event_add_time( sd_event *e, sd_event_source **ret, - EventSourceType type, - int *timer_fd, - clockid_t id, - Prioq **earliest, - Prioq **latest, + clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata) { + EventSourceType type; sd_event_source *s; + struct clock_data *d; int r; assert_return(e, -EINVAL); - assert_return(callback, -EINVAL); assert_return(ret, -EINVAL); assert_return(usec != (uint64_t) -1, -EINVAL); assert_return(accuracy != (uint64_t) -1, -EINVAL); + assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); - assert(timer_fd); - assert(earliest); - assert(latest); + type = clock_to_event_source_type(clock); + assert_return(type >= 0, -ENOTSUP); + + d = event_get_clock_data(e, type); + assert(d); - if (!*earliest) { - *earliest = prioq_new(earliest_time_prioq_compare); - if (!*earliest) + if (!d->earliest) { + d->earliest = prioq_new(earliest_time_prioq_compare); + if (!d->earliest) return -ENOMEM; } - if (!*latest) { - *latest = prioq_new(latest_time_prioq_compare); - if (!*latest) + if (!d->latest) { + d->latest = prioq_new(latest_time_prioq_compare); + if (!d->latest) return -ENOMEM; } - if (*timer_fd < 0) { - r = event_setup_timer_fd(e, type, timer_fd, id); + if (d->fd < 0) { + r = event_setup_timer_fd(e, d, clock); if (r < 0) return r; } @@ -741,11 +836,11 @@ static int event_add_time_internal( s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; - r = prioq_put(*earliest, s, &s->time.earliest_index); + r = prioq_put(d->earliest, s, &s->time.earliest_index); if (r < 0) goto fail; - r = prioq_put(*latest, s, &s->time.latest_index); + r = prioq_put(d->latest, s, &s->time.latest_index); if (r < 0) goto fail; @@ -757,26 +852,6 @@ fail: return r; } -_public_ int sd_event_add_monotonic(sd_event *e, - sd_event_source **ret, - uint64_t usec, - uint64_t accuracy, - sd_event_time_handler_t callback, - void *userdata) { - - return event_add_time_internal(e, ret, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata); -} - -_public_ int sd_event_add_realtime(sd_event *e, - sd_event_source **ret, - uint64_t usec, - uint64_t accuracy, - sd_event_time_handler_t callback, - void *userdata) { - - return event_add_time_internal(e, ret, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->realtime_latest, usec, accuracy, callback, userdata); -} - static int event_update_signal_fd(sd_event *e) { struct epoll_event ev = {}; bool add_to_epoll; @@ -1244,17 +1319,20 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { s->enabled = m; break; - case SOURCE_MONOTONIC: - s->enabled = m; - prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index); - prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index); - break; + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; - case SOURCE_REALTIME: s->enabled = m; - prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index); - prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index); + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); break; + } case SOURCE_SIGNAL: s->enabled = m; @@ -1288,7 +1366,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { s->enabled = m; break; - case SOURCE_WATCHDOG: + default: assert_not_reached("Wut? I shouldn't exist."); } @@ -1303,17 +1381,20 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { s->enabled = m; break; - case SOURCE_MONOTONIC: - s->enabled = m; - prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index); - prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index); - break; + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; - case SOURCE_REALTIME: s->enabled = m; - prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index); - prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index); + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); break; + } case SOURCE_SIGNAL: s->enabled = m; @@ -1347,7 +1428,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { s->enabled = m; break; - case SOURCE_WATCHDOG: + default: assert_not_reached("Wut? I shouldn't exist."); } } @@ -1364,7 +1445,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { assert_return(s, -EINVAL); assert_return(usec, -EINVAL); - assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *usec = s->time.next; @@ -1372,9 +1453,11 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { } _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { + struct clock_data *d; + assert_return(s, -EINVAL); assert_return(usec != (uint64_t) -1, -EINVAL); - assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); @@ -1382,13 +1465,11 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { source_set_pending(s, false); - 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 { - prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index); - prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index); - } + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); return 0; } @@ -1396,7 +1477,7 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { assert_return(s, -EINVAL); assert_return(usec, -EINVAL); - assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *usec = s->time.accuracy; @@ -1404,9 +1485,11 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use } _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { + struct clock_data *d; + assert_return(s, -EINVAL); assert_return(usec != (uint64_t) -1, -EINVAL); - assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); @@ -1417,11 +1500,21 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec source_set_pending(s, false); - if (s->type == SOURCE_REALTIME) - prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index); - else - prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index); + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->latest, s, &s->time.latest_index); + + return 0; +} + +_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) { + assert_return(s, -EINVAL); + assert_return(clock, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + *clock = event_source_type_to_clock(s->type); return 0; } @@ -1562,10 +1655,7 @@ static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { static int event_arm_timer( sd_event *e, - int timer_fd, - Prioq *earliest, - Prioq *latest, - usec_t *next) { + struct clock_data *d) { struct itimerspec its = {}; sd_event_source *a, *b; @@ -1573,35 +1663,34 @@ static int event_arm_timer( int r; assert(e); - assert(next); + assert(d); - a = prioq_peek(earliest); + a = prioq_peek(d->earliest); if (!a || a->enabled == SD_EVENT_OFF) { - if (timer_fd < 0) + if (d->fd < 0) return 0; - if (*next == (usec_t) -1) + if (d->next == (usec_t) -1) return 0; /* disarm */ - r = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL); + r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); if (r < 0) return r; - *next = (usec_t) -1; - + d->next = (usec_t) -1; return 0; } - b = prioq_peek(latest); + b = prioq_peek(d->latest); assert_se(b && b->enabled != SD_EVENT_OFF); t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy); - if (*next == t) + if (d->next == t) return 0; - assert_se(timer_fd >= 0); + assert_se(d->fd >= 0); if (t == 0) { /* We don' want to disarm here, just mean some time looooong ago. */ @@ -1610,11 +1699,11 @@ static int event_arm_timer( } else timespec_store(&its.it_value, t); - r = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL); + r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); if (r < 0) return -errno; - *next = t; + d->next = t; return 0; } @@ -1666,16 +1755,16 @@ static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) { static int process_timer( sd_event *e, usec_t n, - Prioq *earliest, - Prioq *latest) { + struct clock_data *d) { sd_event_source *s; int r; assert(e); + assert(d); for (;;) { - s = prioq_peek(earliest); + s = prioq_peek(d->earliest); if (!s || s->time.next > n || s->enabled == SD_EVENT_OFF || @@ -1686,8 +1775,8 @@ static int process_timer( if (r < 0) return r; - prioq_reshuffle(earliest, s, &s->time.earliest_index); - prioq_reshuffle(latest, s, &s->time.latest_index); + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); } return 0; @@ -1848,11 +1937,10 @@ static int source_dispatch(sd_event_source *s) { r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata); break; - case SOURCE_MONOTONIC: - r = s->time.callback(s, s->time.next, s->userdata); - break; - - case SOURCE_REALTIME: + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: r = s->time.callback(s, s->time.next, s->userdata); break; @@ -2038,16 +2126,25 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { if (r < 0) goto finish; - r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next); + r = event_arm_timer(e, &e->realtime); + if (r < 0) + goto finish; + + r = event_arm_timer(e, &e->monotonic); + if (r < 0) + goto finish; + + r = event_arm_timer(e, &e->realtime_alarm); if (r < 0) goto finish; - r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next); + r = event_arm_timer(e, &e->boottime_alarm); if (r < 0) goto finish; if (event_next_pending(e) || e->need_process_child) timeout = 0; + ev_queue_max = CLAMP(e->n_sources, 1U, EPOLL_QUEUE_MAX); ev_queue = newa(struct epoll_event, ev_queue_max); @@ -2059,16 +2156,21 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { } dual_timestamp_get(&e->timestamp); + e->timestamp_boottime = now(CLOCK_BOOTTIME); for (i = 0; i < m; i++) { - if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_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_REALTIME)) - r = flush_timer(e, e->realtime_fd, ev_queue[i].events, &e->realtime_next); + 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_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)) + r = flush_timer(e, e->realtime_alarm.fd, ev_queue[i].events, &e->realtime_alarm.next); + else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_TIME_BOOTTIME_ALARM)) + r = flush_timer(e, e->boottime_alarm.fd, ev_queue[i].events, &e->boottime_alarm.next); else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_SIGNAL)) r = process_signal(e, ev_queue[i].events); - else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) + else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL); else r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); @@ -2081,11 +2183,19 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { if (r < 0) goto finish; - r = process_timer(e, e->timestamp.monotonic, e->monotonic_earliest, e->monotonic_latest); + r = process_timer(e, e->timestamp.realtime, &e->realtime); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.monotonic, &e->monotonic); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm); if (r < 0) goto finish; - r = process_timer(e, e->timestamp.realtime, e->realtime_earliest, e->realtime_latest); + r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm); if (r < 0) goto finish; @@ -2162,23 +2272,31 @@ _public_ int sd_event_exit(sd_event *e, int code) { return 0; } -_public_ int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) { +_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { assert_return(e, -EINVAL); assert_return(usec, -EINVAL); - assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA); assert_return(!event_pid_changed(e), -ECHILD); - *usec = e->timestamp.realtime; - return 0; -} + /* If we haven't run yet, just get the actual time */ + if (!dual_timestamp_is_set(&e->timestamp)) + return -ENODATA; -_public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) { - assert_return(e, -EINVAL); - assert_return(usec, -EINVAL); - assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA); - assert_return(!event_pid_changed(e), -ECHILD); + switch (clock) { + + case CLOCK_REALTIME: + case CLOCK_REALTIME_ALARM: + *usec = e->timestamp.realtime; + break; + + case CLOCK_MONOTONIC: + *usec = e->timestamp.monotonic; + break; + + case CLOCK_BOOTTIME_ALARM: + *usec = e->timestamp_boottime; + break; + } - *usec = e->timestamp.monotonic; return 0; } diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index 0b7e2e48c..68bb2b0ca 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -196,7 +196,7 @@ int main(int argc, char *argv[]) { assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0); assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0); - assert_se(sd_event_add_monotonic(e, &z, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); + assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0); assert_se(sd_event_source_set_priority(x, 99) >= 0); diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c index 604265764..a2760d056 100644 --- a/src/libsystemd/sd-rtnl/sd-rtnl.c +++ b/src/libsystemd/sd-rtnl/sd-rtnl.c @@ -838,7 +838,7 @@ int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) { if (r < 0) goto fail; - r = sd_event_add_monotonic(rtnl->event, &rtnl->time_event_source, 0, 0, time_callback, rtnl); + r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl); if (r < 0) goto fail; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 2ef87f72a..0af67148a 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1340,7 +1340,12 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) { r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until); } else - r = sd_event_add_monotonic(m->event, &m->lid_switch_ignore_event_source, until, 0, lid_switch_ignore_handler, m); + r = sd_event_add_time( + m->event, + &m->lid_switch_ignore_event_source, + CLOCK_MONOTONIC, + until, 0, + lid_switch_ignore_handler, m); return r; } diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 8c517f46a..4ca6b5d80 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -682,7 +682,11 @@ void session_release(Session *s) { return; if (!s->timer_event_source) - sd_event_add_monotonic(s->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s); + sd_event_add_time(s->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, + release_timeout_callback, s); } bool session_is_active(Session *s) { diff --git a/src/login/logind.c b/src/login/logind.c index db9882323..86ce7df5d 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -933,7 +933,12 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us if (!m->idle_action_event_source) { - r = sd_event_add_monotonic(m->event, &m->idle_action_event_source, elapse, USEC_PER_SEC*30, manager_dispatch_idle_action, m); + r = sd_event_add_time( + m->event, + &m->idle_action_event_source, + CLOCK_MONOTONIC, + elapse, USEC_PER_SEC*30, + manager_dispatch_idle_action, m); if (r < 0) { log_error("Failed to add idle event source: %s", strerror(-r)); return r; diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h index 45c36086f..c0bd03bcc 100644 --- a/src/systemd/sd-event.h +++ b/src/systemd/sd-event.h @@ -77,8 +77,7 @@ sd_event* sd_event_ref(sd_event *e); sd_event* sd_event_unref(sd_event *e); int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata); -int sd_event_add_monotonic(sd_event *e, sd_event_source **s, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); -int sd_event_add_realtime(sd_event *e, sd_event_source **s, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); +int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); @@ -89,11 +88,11 @@ int sd_event_run(sd_event *e, uint64_t timeout); int sd_event_loop(sd_event *e); int sd_event_exit(sd_event *e, int code); +int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec); + int sd_event_get_state(sd_event *e); int sd_event_get_tid(sd_event *e, pid_t *tid); int sd_event_get_exit_code(sd_event *e, int *code); -int sd_event_get_now_realtime(sd_event *e, uint64_t *usec); -int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec); int sd_event_set_watchdog(sd_event *e, int b); int sd_event_get_watchdog(sd_event *e); @@ -117,6 +116,7 @@ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); int sd_event_source_set_time(sd_event_source *s, uint64_t usec); int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); +int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); int sd_event_source_get_signal(sd_event_source *s); int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); sd_event *sd_event_source_get_event(sd_event_source *s); diff --git a/src/timedate/timedate-sntp.c b/src/timedate/timedate-sntp.c index cb0bf794f..880b467a8 100644 --- a/src/timedate/timedate-sntp.c +++ b/src/timedate/timedate-sntp.c @@ -265,7 +265,12 @@ static int sntp_arm_timer(SNTPContext *sntp, usec_t next) { } e = sd_event_source_get_event(sntp->event_receive); - r = sd_event_add_monotonic(e, &sntp->event_timer, now(CLOCK_MONOTONIC) + next, 0, sntp_timer, sntp); + r = sd_event_add_time( + e, + &sntp->event_timer, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + next, 0, + sntp_timer, sntp); if (r < 0) return r; -- 2.30.2