diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-11-23 21:37:58 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-11-23 21:37:58 +0100 |
commit | 36697dc0199e25f09b78090fcf5f1cf8a3648ffd (patch) | |
tree | 7caef3bc1761327c366fc4a93a138e53fc692712 /src/core | |
parent | 8a1175118e7a2e60a6ec42624f915e26e821f4e8 (diff) |
timer: implement calendar time events
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dbus-timer.c | 6 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/core/load-fragment.c | 29 | ||||
-rw-r--r-- | src/core/mount.c | 12 | ||||
-rw-r--r-- | src/core/service.c | 13 | ||||
-rw-r--r-- | src/core/socket.c | 15 | ||||
-rw-r--r-- | src/core/swap.c | 6 | ||||
-rw-r--r-- | src/core/timer.c | 196 | ||||
-rw-r--r-- | src/core/timer.h | 16 | ||||
-rw-r--r-- | src/core/unit.c | 10 | ||||
-rw-r--r-- | src/core/unit.h | 2 |
11 files changed, 206 insertions, 100 deletions
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c index 84b823c9a4..11d18cbd83 100644 --- a/src/core/dbus-timer.c +++ b/src/core/dbus-timer.c @@ -79,7 +79,8 @@ static int bus_timer_append_timers(DBusMessageIter *i, const char *property, voi /* s/Sec/USec/ */ l = strlen(t); - if (!(buf = new(char, l+2))) + buf = new(char, l+2); + if (!buf) return -ENOMEM; memcpy(buf, t, l-3); @@ -121,7 +122,8 @@ static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_resu static const BusProperty bus_timer_properties[] = { { "Unit", bus_timer_append_unit, "s", 0 }, { "Timers", bus_timer_append_timers, "a(stt)", 0 }, - { "NextElapseUSec", bus_property_append_usec, "t", offsetof(Timer, next_elapse) }, + { "NextElapseUSec", bus_property_append_usec, "t", offsetof(Timer, next_elapse_monotonic) }, + { "NextElapseUSecRealtime", bus_property_append_usec, "t", offsetof(Timer, next_elapse_realtime) }, { "Result", bus_timer_append_timer_result,"s", offsetof(Timer, result) }, { NULL, } }; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index be16ba93c8..7212053ca7 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -234,6 +234,7 @@ Swap.TimeoutSec, config_parse_usec, 0, EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl m4_dnl +Timer.OnCalendar, config_parse_timer, 0, 0 Timer.OnActiveSec, config_parse_timer, 0, 0 Timer.OnBootSec, config_parse_timer, 0, 0 Timer.OnStartupSec, config_parse_timer, 0, 0 diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 6933e1a21e..e35fdbc5ec 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1136,30 +1136,47 @@ int config_parse_timer( void *userdata) { Timer *t = data; - usec_t u; + usec_t u = 0; TimerValue *v; TimerBase b; + CalendarSpec *c = NULL; + clockid_t id; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if ((b = timer_base_from_string(lvalue)) < 0) { + b = timer_base_from_string(lvalue); + if (b < 0) { log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue); return 0; } - if (parse_usec(rvalue, &u) < 0) { - log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue); - return 0; + if (b == TIMER_CALENDAR) { + if (calendar_spec_from_string(rvalue, &c) < 0) { + log_error("[%s:%u] Failed to parse calendar specification, ignoring: %s", filename, line, rvalue); + return 0; + } + + id = CLOCK_REALTIME; + } else { + if (parse_usec(rvalue, &u) < 0) { + log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue); + return 0; + } + + id = CLOCK_MONOTONIC; } - if (!(v = new0(TimerValue, 1))) + v = new0(TimerValue, 1); + if (!v) return -ENOMEM; v->base = b; + v->clock_id = id; v->value = u; + v->calendar_spec = c; LIST_PREPEND(TimerValue, value, t->values, v); diff --git a/src/core/mount.c b/src/core/mount.c index 14f4863dc6..09a5d286d3 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -741,10 +741,12 @@ static int mount_coldplug(Unit *u) { if (m->control_pid <= 0) return -EBADMSG; - if ((r = unit_watch_pid(UNIT(m), m->control_pid)) < 0) + r = unit_watch_pid(UNIT(m), m->control_pid); + if (r < 0) return r; - if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0) + r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch); + if (r < 0) return r; } @@ -800,7 +802,8 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { assert(c); assert(_pid); - if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0) + r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch); + if (r < 0) goto fail; if ((r = exec_spawn(c, @@ -900,7 +903,8 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) { } if (wait_for_exit) { - if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0) + r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch); + if (r < 0) goto fail; mount_set_state(m, state); diff --git a/src/core/service.c b/src/core/service.c index 34d24ffa92..25a568f70b 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -249,7 +249,7 @@ static void service_handle_watchdog(Service *s) { return; } - r = unit_watch_timer(UNIT(s), s->watchdog_usec - offset, &s->watchdog_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->watchdog_usec - offset, &s->watchdog_watch); if (r < 0) log_warning("%s failed to install watchdog timer: %s", UNIT(s)->id, strerror(-r)); } @@ -1599,7 +1599,8 @@ static int service_coldplug(Unit *u) { k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_start_usec; - if ((r = unit_watch_timer(UNIT(s), k, &s->timer_watch)) < 0) + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, k, &s->timer_watch); + if (r < 0) return r; } } @@ -1744,7 +1745,7 @@ static int service_spawn( } if (timeout && s->timeout_start_usec) { - r = unit_watch_timer(UNIT(s), s->timeout_start_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_start_usec, &s->timer_watch); if (r < 0) goto fail; } else @@ -1899,7 +1900,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status))) ) { - r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch); if (r < 0) goto fail; @@ -2012,7 +2013,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f if (wait_for_exit) { if (s->timeout_stop_usec > 0) { - r = unit_watch_timer(UNIT(s), s->timeout_stop_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch); if (r < 0) goto fail; } @@ -2262,7 +2263,7 @@ static void service_enter_restart(Service *s) { /* Don't restart things if we are going down anyway */ log_info("Stop job pending for unit, delaying automatic restart."); - r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch); if (r < 0) goto fail; diff --git a/src/core/socket.c b/src/core/socket.c index 3d5791b114..9b5bcb6e7b 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1146,10 +1146,12 @@ static int socket_coldplug(Unit *u) { if (s->control_pid <= 0) return -EBADMSG; - if ((r = unit_watch_pid(UNIT(s), s->control_pid)) < 0) + r = unit_watch_pid(UNIT(s), s->control_pid); + if (r < 0) return r; - if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0) + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch); + if (r < 0) return r; } @@ -1181,10 +1183,12 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { assert(c); assert(_pid); - if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0) + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch); + if (r < 0) goto fail; - if (!(argv = unit_full_printf_strv(UNIT(s), c->argv))) { + argv = unit_full_printf_strv(UNIT(s), c->argv); + if (!argv) { r = -ENOMEM; goto fail; } @@ -1306,7 +1310,8 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) { } if (wait_for_exit) { - if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0) + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch); + if (r < 0) goto fail; socket_set_state(s, state); diff --git a/src/core/swap.c b/src/core/swap.c index 97145a9974..bd40516c99 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -521,7 +521,7 @@ static int swap_coldplug(Unit *u) { if (r < 0) return r; - r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch); if (r < 0) return r; } @@ -584,7 +584,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { assert(c); assert(_pid); - r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch); if (r < 0) goto fail; @@ -689,7 +689,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { } if (wait_for_exit) { - r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch); + r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch); if (r < 0) goto fail; diff --git a/src/core/timer.c b/src/core/timer.c index 7080b32c6b..54c0d0b330 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -42,7 +42,10 @@ static void timer_init(Unit *u) { assert(u); assert(u->load_state == UNIT_STUB); - t->next_elapse = (usec_t) -1; + t->next_elapse_monotonic = (usec_t) -1; + t->next_elapse_realtime = (usec_t) -1; + watch_init(&t->monotonic_watch); + watch_init(&t->realtime_watch); } static void timer_done(Unit *u) { @@ -53,10 +56,15 @@ static void timer_done(Unit *u) { while ((v = t->values)) { LIST_REMOVE(TimerValue, value, t->values, v); + + if (v->calendar_spec) + calendar_spec_free(v->calendar_spec); + free(v); } - unit_unwatch_timer(u, &t->timer_watch); + unit_unwatch_timer(u, &t->monotonic_watch); + unit_unwatch_timer(u, &t->realtime_watch); unit_ref_unset(&t->unit); } @@ -81,10 +89,12 @@ static int timer_add_default_dependencies(Timer *t) { assert(t); if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) { - if ((r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true)) < 0) + r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true); + if (r < 0) return r; - if ((r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0) + r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); + if (r < 0) return r; } @@ -98,7 +108,8 @@ static int timer_load(Unit *u) { assert(u); assert(u->load_state == UNIT_STUB); - if ((r = unit_load_fragment_and_dropin(u)) < 0) + r = unit_load_fragment_and_dropin(u); + if (r < 0) return r; if (u->load_state == UNIT_LOADED) { @@ -117,9 +128,11 @@ static int timer_load(Unit *u) { if (r < 0) return r; - if (UNIT(t)->default_dependencies) - if ((r = timer_add_default_dependencies(t)) < 0) + if (UNIT(t)->default_dependencies) { + r = timer_add_default_dependencies(t); + if (r < 0) return r; + } } return timer_verify(t); @@ -128,8 +141,6 @@ static int timer_load(Unit *u) { static void timer_dump(Unit *u, FILE *f, const char *prefix) { Timer *t = TIMER(u); TimerValue *v; - char - timespan1[FORMAT_TIMESPAN_MAX]; fprintf(f, "%sTimer State: %s\n" @@ -139,12 +150,28 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) { prefix, timer_result_to_string(t->result), prefix, UNIT_DEREF(t->unit)->id); - LIST_FOREACH(value, v, t->values) - fprintf(f, - "%s%s: %s\n", - prefix, - timer_base_to_string(v->base), - strna(format_timespan(timespan1, sizeof(timespan1), v->value))); + LIST_FOREACH(value, v, t->values) { + + if (v->base == TIMER_CALENDAR) { + _cleanup_free_ char *p = NULL; + + calendar_spec_to_string(v->calendar_spec, &p); + + fprintf(f, + "%s%s: %s\n", + prefix, + timer_base_to_string(v->base), + strna(p)); + } else { + char timespan1[FORMAT_TIMESPAN_MAX]; + + fprintf(f, + "%s%s: %s\n", + prefix, + timer_base_to_string(v->base), + strna(format_timespan(timespan1, sizeof(timespan1), v->value))); + } + } } static void timer_set_state(Timer *t, TimerState state) { @@ -154,8 +181,10 @@ static void timer_set_state(Timer *t, TimerState state) { old_state = t->state; t->state = state; - if (state != TIMER_WAITING) - unit_unwatch_timer(UNIT(t), &t->timer_watch); + if (state != TIMER_WAITING) { + unit_unwatch_timer(UNIT(t), &t->monotonic_watch); + unit_unwatch_timer(UNIT(t), &t->realtime_watch); + } if (state != old_state) log_debug("%s changed %s -> %s", @@ -196,79 +225,117 @@ static void timer_enter_dead(Timer *t, TimerResult f) { static void timer_enter_waiting(Timer *t, bool initial) { TimerValue *v; - usec_t base = 0, delay, n; - bool found = false; + usec_t base = 0; + dual_timestamp ts; + bool found_monotonic = false, found_realtime = false; int r; - n = now(CLOCK_MONOTONIC); + dual_timestamp_get(&ts); + t->next_elapse_monotonic = t->next_elapse_realtime = 0; LIST_FOREACH(value, v, t->values) { if (v->disabled) continue; - switch (v->base) { + if (v->base == TIMER_CALENDAR) { + + r = calendar_spec_next_usec(v->calendar_spec, ts.realtime, &v->next_elapse); + if (r < 0) + continue; + + if (!initial && v->next_elapse < ts.realtime) { + v->disabled = true; + continue; + } - case TIMER_ACTIVE: - if (state_translation_table[t->state] == UNIT_ACTIVE) - base = UNIT(t)->inactive_exit_timestamp.monotonic; + if (!found_realtime) + t->next_elapse_realtime = v->next_elapse; else - base = n; - break; + t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse); - case TIMER_BOOT: - /* CLOCK_MONOTONIC equals the uptime on Linux */ - base = 0; - break; + found_realtime = true; - case TIMER_STARTUP: - base = UNIT(t)->manager->userspace_timestamp.monotonic; - break; + } else { + switch (v->base) { - case TIMER_UNIT_ACTIVE: + case TIMER_ACTIVE: + if (state_translation_table[t->state] == UNIT_ACTIVE) + base = UNIT(t)->inactive_exit_timestamp.monotonic; + else + base = ts.monotonic; + break; - if (UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic <= 0) - continue; + case TIMER_BOOT: + /* CLOCK_MONOTONIC equals the uptime on Linux */ + base = 0; + break; - base = UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic; - break; + case TIMER_STARTUP: + base = UNIT(t)->manager->userspace_timestamp.monotonic; + break; - case TIMER_UNIT_INACTIVE: + case TIMER_UNIT_ACTIVE: - if (UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic <= 0) - continue; + if (UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic <= 0) + continue; - base = UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic; - break; + base = UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic; + break; - default: - assert_not_reached("Unknown timer base"); - } + case TIMER_UNIT_INACTIVE: - v->next_elapse = base + v->value; + if (UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic <= 0) + continue; - if (!initial && v->next_elapse < n) { - v->disabled = true; - continue; - } + base = UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic; + break; - if (!found) - t->next_elapse = v->next_elapse; - else - t->next_elapse = MIN(t->next_elapse, v->next_elapse); + default: + assert_not_reached("Unknown timer base"); + } - found = true; + v->next_elapse = base + v->value; + + if (!initial && v->next_elapse < ts.monotonic) { + v->disabled = true; + continue; + } + + if (!found_monotonic) + t->next_elapse_monotonic = v->next_elapse; + else + t->next_elapse_monotonic = MIN(t->next_elapse_monotonic, v->next_elapse); + + found_monotonic = true; + } } - if (!found) { + if (!found_monotonic && !found_realtime) { + log_debug("%s: Timer is elapsed.", UNIT(t)->id); timer_set_state(t, TIMER_ELAPSED); return; } - delay = n < t->next_elapse ? t->next_elapse - n : 0; + if (found_monotonic) { + char buf[FORMAT_TIMESPAN_MAX]; + log_debug("%s: Monotonic timer elapses in %s the next time.", UNIT(t)->id, format_timespan(buf, sizeof(buf), t->next_elapse_monotonic - ts.monotonic)); - if ((r = unit_watch_timer(UNIT(t), delay, &t->timer_watch)) < 0) - goto fail; + r = unit_watch_timer(UNIT(t), CLOCK_MONOTONIC, false, t->next_elapse_monotonic, &t->monotonic_watch); + if (r < 0) + goto fail; + } else + unit_unwatch_timer(UNIT(t), &t->monotonic_watch); + + if (found_realtime) { + char buf[FORMAT_TIMESTAMP_MAX]; + log_debug("%s: Realtime timer elapses at %s the next time.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime)); + + r = unit_watch_timer(UNIT(t), CLOCK_REALTIME, false, t->next_elapse_realtime, &t->realtime_watch); + if (r < 0) + goto fail; + } else + unit_unwatch_timer(UNIT(t), &t->realtime_watch); timer_set_state(t, TIMER_WAITING); return; @@ -289,7 +356,8 @@ static void timer_enter_running(Timer *t) { if (UNIT(t)->job && UNIT(t)->job->type == JOB_STOP) return; - if ((r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_DEREF(t->unit), JOB_REPLACE, true, &error, NULL)) < 0) + r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_DEREF(t->unit), JOB_REPLACE, true, &error, NULL); + if (r < 0) goto fail; timer_set_state(t, TIMER_RUNNING); @@ -350,7 +418,8 @@ static int timer_deserialize_item(Unit *u, const char *key, const char *value, F if (streq(key, "state")) { TimerState state; - if ((state = timer_state_from_string(value)) < 0) + state = timer_state_from_string(value); + if (state < 0) log_debug("Failed to parse state value %s", value); else t->deserialized_state = state; @@ -473,7 +542,8 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = { [TIMER_BOOT] = "OnBootSec", [TIMER_STARTUP] = "OnStartupSec", [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec", - [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec" + [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec", + [TIMER_CALENDAR] = "OnCalendar" }; DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase); diff --git a/src/core/timer.h b/src/core/timer.h index c6d1d42e44..57a514a68c 100644 --- a/src/core/timer.h +++ b/src/core/timer.h @@ -24,6 +24,7 @@ typedef struct Timer Timer; #include "unit.h" +#include "calendarspec.h" typedef enum TimerState { TIMER_DEAD, @@ -41,18 +42,21 @@ typedef enum TimerBase { TIMER_STARTUP, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE, + TIMER_CALENDAR, _TIMER_BASE_MAX, _TIMER_BASE_INVALID = -1 } TimerBase; typedef struct TimerValue { + TimerBase base; + bool disabled; + clockid_t clock_id; + usec_t value; + CalendarSpec *calendar_spec; usec_t next_elapse; LIST_FIELDS(struct TimerValue, value); - - TimerBase base; - bool disabled; } TimerValue; typedef enum TimerResult { @@ -66,12 +70,14 @@ struct Timer { Unit meta; LIST_HEAD(TimerValue, values); - usec_t next_elapse; + usec_t next_elapse_monotonic; + usec_t next_elapse_realtime; TimerState state, deserialized_state; UnitRef unit; - Watch timer_watch; + Watch monotonic_watch; + Watch realtime_watch; TimerResult result; }; diff --git a/src/core/unit.c b/src/core/unit.c index 82dd617e35..45453dce64 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1560,7 +1560,7 @@ void unit_unwatch_pid(Unit *u, pid_t pid) { hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u); } -int unit_watch_timer(Unit *u, usec_t delay, Watch *w) { +int unit_watch_timer(Unit *u, clockid_t clock_id, bool relative, usec_t usec, Watch *w) { struct itimerspec its; int flags, fd; bool ours; @@ -1580,7 +1580,7 @@ int unit_watch_timer(Unit *u, usec_t delay, Watch *w) { } else if (w->type == WATCH_INVALID) { ours = true; - fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); + fd = timerfd_create(clock_id, TFD_NONBLOCK|TFD_CLOEXEC); if (fd < 0) return -errno; } else @@ -1588,7 +1588,7 @@ int unit_watch_timer(Unit *u, usec_t delay, Watch *w) { zero(its); - if (delay <= 0) { + if (usec <= 0) { /* Set absolute time in the past, but not 0, since we * don't want to disarm the timer */ its.it_value.tv_sec = 0; @@ -1596,8 +1596,8 @@ int unit_watch_timer(Unit *u, usec_t delay, Watch *w) { flags = TFD_TIMER_ABSTIME; } else { - timespec_store(&its.it_value, delay); - flags = 0; + timespec_store(&its.it_value, usec); + flags = relative ? 0 : TFD_TIMER_ABSTIME; } /* This will also flush the elapse counter */ diff --git a/src/core/unit.h b/src/core/unit.h index bf961c2aac..11804d8bcf 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -484,7 +484,7 @@ void unit_unwatch_fd(Unit *u, Watch *w); int unit_watch_pid(Unit *u, pid_t pid); void unit_unwatch_pid(Unit *u, pid_t pid); -int unit_watch_timer(Unit *u, usec_t delay, Watch *w); +int unit_watch_timer(Unit *u, clockid_t, bool relative, usec_t usec, Watch *w); void unit_unwatch_timer(Unit *u, Watch *w); int unit_watch_bus_name(Unit *u, const char *name); |