X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Flibelogind%2Fsd-event%2Fsd-event.c;h=019d411c43ae65a5113009695ffeb3aee6ccf26f;hb=093a10d73a66352cb8c03f38659e214638dba6b5;hp=63a64f339282d4fc2442454d246055ccd040738a;hpb=91662cfb8364703fee7c698f503a0f3ab3142c8b;p=elogind.git diff --git a/src/libelogind/sd-event/sd-event.c b/src/libelogind/sd-event/sd-event.c index 63a64f339..019d411c4 100644 --- a/src/libelogind/sd-event/sd-event.c +++ b/src/libelogind/sd-event/sd-event.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -111,8 +109,8 @@ struct sd_event_source { int64_t priority; unsigned pending_index; unsigned prepare_index; - unsigned pending_iteration; - unsigned prepare_iteration; + uint64_t pending_iteration; + uint64_t prepare_iteration; LIST_FIELDS(sd_event_source, sources); @@ -217,9 +215,8 @@ struct sd_event { pid_t original_pid; - unsigned iteration; - dual_timestamp timestamp; - usec_t timestamp_boottime; + uint64_t iteration; + triple_timestamp timestamp; int state; bool exit_requested:1; @@ -466,7 +463,9 @@ fail: } _public_ sd_event* sd_event_ref(sd_event *e) { - assert_return(e, NULL); + + if (!e) + return NULL; assert(e->n_ref >= 1); e->n_ref++; @@ -649,7 +648,7 @@ static int event_make_signal_data( if (sigismember(&d->sigset, sig) > 0) { if (ret) *ret = d; - return 0; + return 0; } } else { r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops); @@ -665,8 +664,10 @@ static int event_make_signal_data( d->priority = priority; r = hashmap_put(e->signal_data, &d->priority, d); - if (r < 0) + if (r < 0) { + free(d); return r; + } added = true; } @@ -694,7 +695,7 @@ static int event_make_signal_data( ev.data.ptr = d; r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev); - if (r < 0) { + if (r < 0) { r = -errno; goto fail; } @@ -731,7 +732,6 @@ static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig /* If all the mask is all-zero we can get rid of the structure */ hashmap_remove(e->signal_data, &d->priority); - assert(!d->current); safe_close(d->fd); free(d); return; @@ -951,7 +951,7 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t sd_event_ref(e); LIST_PREPEND(sources, e->sources, s); - e->n_sources ++; + e->n_sources++; return s; } @@ -1068,17 +1068,20 @@ _public_ int sd_event_add_time( int r; assert_return(e, -EINVAL); - assert_return(usec != (uint64_t) -1, -EINVAL); assert_return(accuracy != (uint64_t) -1, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); + if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */ + return -EOPNOTSUPP; + + type = clock_to_event_source_type(clock); /* checks whether sd-event supports this clock */ + if (type < 0) + return -EOPNOTSUPP; + if (!callback) callback = time_exit_callback; - type = clock_to_event_source_type(clock); - assert_return(type >= 0, -EOPNOTSUPP); - d = event_get_clock_data(e, type); assert(d); @@ -1146,8 +1149,7 @@ _public_ int sd_event_add_signal( int r; assert_return(e, -EINVAL); - assert_return(sig > 0, -EINVAL); - assert_return(sig < _NSIG, -EINVAL); + assert_return(SIGNAL_VALID(sig), -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -1180,10 +1182,10 @@ _public_ int sd_event_add_signal( e->signal_sources[sig] = s; r = event_make_signal_data(e, sig, &d); - if (r < 0) { - source_free(s); - return r; - } + if (r < 0) { + source_free(s); + return r; + } /* Use the signal name as description for the event source by default */ (void) sd_event_source_set_description(s, signal_to_string(sig)); @@ -1237,14 +1239,14 @@ _public_ int sd_event_add_child( return r; } - e->n_enabled_child_sources ++; + e->n_enabled_child_sources++; r = event_make_signal_data(e, SIGCHLD, NULL); - if (r < 0) { + if (r < 0) { e->n_enabled_child_sources--; - source_free(s); - return r; - } + source_free(s); + return r; + } e->need_process_child = true; @@ -1368,7 +1370,9 @@ _public_ int sd_event_add_exit( #if 0 /// UNNEEDED by elogind _public_ sd_event_source* sd_event_source_ref(sd_event_source *s) { - assert_return(s, NULL); + + if (!s) + return NULL; assert(s->n_ref >= 1); s->n_ref++; @@ -1547,7 +1551,8 @@ _public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) assert_return(s, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); - return s->priority; + *priority = s->priority; + return 0; } #endif // 0 @@ -1579,7 +1584,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) event_unmask_signal_data(s->event, old, s->signal.sig); } else - s->priority = priority; + s->priority = priority; if (s->pending) prioq_reshuffle(s->event->pending, s, &s->pending_index); @@ -1707,11 +1712,11 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { s->enabled = m; r = event_make_signal_data(s->event, s->signal.sig, NULL); - if (r < 0) { - s->enabled = SD_EVENT_OFF; + if (r < 0) { + s->enabled = SD_EVENT_OFF; event_gc_signal_data(s->event, &s->priority, s->signal.sig); - return r; - } + return r; + } break; @@ -1723,12 +1728,12 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { s->enabled = m; r = event_make_signal_data(s->event, SIGCHLD, NULL); - if (r < 0) { - s->enabled = SD_EVENT_OFF; + if (r < 0) { + s->enabled = SD_EVENT_OFF; s->event->n_enabled_child_sources--; event_gc_signal_data(s->event, &s->priority, SIGCHLD); - return r; - } + return r; + } break; @@ -1770,7 +1775,6 @@ _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(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); @@ -1904,6 +1908,8 @@ static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { if (a <= 0) return 0; + if (a >= USEC_INFINITY) + return USEC_INFINITY; if (b <= a + 1) return a; @@ -1993,7 +1999,7 @@ static int event_arm_timer( d->needs_rearm = false; a = prioq_peek(d->earliest); - if (!a || a->enabled == SD_EVENT_OFF) { + if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { if (d->fd < 0) return 0; @@ -2216,7 +2222,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { if (_unlikely_(n != sizeof(si))) return -EIO; - assert(si.ssi_signo < _NSIG); + assert(SIGNAL_VALID(si.ssi_signo)); read_one = true; @@ -2239,11 +2245,16 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { } static int source_dispatch(sd_event_source *s) { + EventSourceType saved_type; int r = 0; assert(s); assert(s->pending || s->type == SOURCE_EXIT); + /* Save the event source type, here, so that we still know it after the event callback which might invalidate + * the event. */ + saved_type = s->type; + if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) { r = source_set_pending(s, false); if (r < 0) @@ -2331,7 +2342,7 @@ static int source_dispatch(sd_event_source *s) { if (r < 0) log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m", - strna(s->description), event_source_type_to_string(s->type)); + strna(s->description), event_source_type_to_string(saved_type)); if (s->n_ref == 0) source_free(s); @@ -2543,8 +2554,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { goto finish; } - dual_timestamp_get(&e->timestamp); - e->timestamp_boottime = now(CLOCK_BOOTTIME); + triple_timestamp_get(&e->timestamp); for (i = 0; i < m; i++) { @@ -2556,7 +2566,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { switch (*t) { case WAKEUP_EVENT_SOURCE: - r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); + r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); break; case WAKEUP_CLOCK_DATA: { @@ -2585,7 +2595,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { if (r < 0) goto finish; - r = process_timer(e, e->timestamp_boottime, &e->boottime); + r = process_timer(e, e->timestamp.boottime, &e->boottime); if (r < 0) goto finish; @@ -2597,7 +2607,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { if (r < 0) goto finish; - r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm); + r = process_timer(e, e->timestamp.boottime, &e->boottime_alarm); if (r < 0) goto finish; @@ -2776,36 +2786,24 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { assert_return(e, -EINVAL); assert_return(usec, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); - assert_return(IN_SET(clock, - CLOCK_REALTIME, - CLOCK_REALTIME_ALARM, - CLOCK_MONOTONIC, - CLOCK_BOOTTIME, - CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP); - - if (!dual_timestamp_is_set(&e->timestamp)) { + + if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock)) + return -EOPNOTSUPP; + + /* Generate a clean error in case CLOCK_BOOTTIME is not available. Note that don't use clock_supported() here, + * for a reason: there are systems where CLOCK_BOOTTIME is supported, but CLOCK_BOOTTIME_ALARM is not, but for + * the purpose of getting the time this doesn't matter. */ + if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported()) + return -EOPNOTSUPP; + + if (!triple_timestamp_is_set(&e->timestamp)) { /* Implicitly fall back to now() if we never ran * before and thus have no cached time. */ *usec = now(clock); return 1; } - switch (clock) { - - case CLOCK_REALTIME: - case CLOCK_REALTIME_ALARM: - *usec = e->timestamp.realtime; - break; - - case CLOCK_MONOTONIC: - *usec = e->timestamp.monotonic; - break; - - default: - *usec = e->timestamp_boottime; - break; - } - + *usec = triple_timestamp_by_clock(&e->timestamp, clock); return 0; } #endif // 0 @@ -2911,3 +2909,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) { return e->watchdog; } #endif // 0 + +_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) { + assert_return(e, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + *ret = e->iteration; + return 0; +}