From 32383854769efe6f2334026a92f02c8c8a47baef Mon Sep 17 00:00:00 2001 From: Maciej Slodczyk Date: Tue, 25 Feb 2020 14:49:14 +0100 Subject: [PATCH] Add reply_callback slots to async kdbus name request/release Signed-off-by: Maciej Slodczyk --- src/libsystemd/sd-bus/bus-control-kernel.c | 100 ++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 10 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-control-kernel.c b/src/libsystemd/sd-bus/bus-control-kernel.c index 8dffb56..aeb8356 100644 --- a/src/libsystemd/sd-bus/bus-control-kernel.c +++ b/src/libsystemd/sd-bus/bus-control-kernel.c @@ -73,6 +73,22 @@ int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) { return 1; } +static usec_t calc_elapse(sd_bus *bus, uint64_t usec) { + assert(bus); + + if (usec == (uint64_t) -1) + return 0; + + /* We start all timeouts the instant we enter BUS_HELLO/BUS_RUNNING state, so that the don't run in parallel + * with any connection setup states. Hence, if a method callback is started earlier than that we just store the + * relative timestamp, and afterwards the absolute one. */ + + if (IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING)) + return usec; + else + return now(CLOCK_MONOTONIC) + usec; +} + int bus_request_name_kernel_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, @@ -81,12 +97,13 @@ int bus_request_name_kernel_async(sd_bus *bus, void *userdata) { int ret; sd_bus_message *m; + uint64_t cookie; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL; - if (NULL != ret_slot) { - *ret_slot = bus_slot_allocate(bus, false, BUS_KDBUS_CALLBACK, 0, NULL); - if (!(*ret_slot)) - return -ENOMEM; - } + /* we want room for the return message */ + ret = bus_rqueue_make_room(bus); + if (ret < 0) + return ret; ret = bus_request_name_kernel(bus, name, flags); @@ -108,8 +125,36 @@ int bus_request_name_kernel_async(sd_bus *bus, if (ret < 0) return ret; + if (ret_slot || callback) { + s = bus_slot_allocate(bus, !ret_slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata); + if (!s) + return -ENOMEM; + + s->reply_callback.callback = callback; + + s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m); + ret = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback); + if (ret < 0) { + s->reply_callback.cookie = 0; + return ret; + } + + s->reply_callback.timeout_usec = calc_elapse(bus, m->timeout); + if (s->reply_callback.timeout_usec != 0) { + ret = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx); + if (ret < 0) { + s->reply_callback.timeout_usec = 0; + return ret; + } + } + } + bus->rqueue[bus->rqueue_size++] = m; + if (ret_slot) + *ret_slot = s; + s = NULL; + return ret; } @@ -148,15 +193,18 @@ int bus_release_name_kernel_async( void *userdata) { int ret; sd_bus_message *m; + uint64_t cookie; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL; - if (NULL != ret_slot) { - *ret_slot = bus_slot_allocate(bus, false, BUS_KDBUS_CALLBACK, 0, NULL); - if (!(*ret_slot)) - return -ENOMEM; - } + /* we want room for the return message */ + ret = bus_rqueue_make_room(bus); + if (ret < 0) + return ret; ret = bus_release_name_kernel(bus, name); + cookie = ++bus->cookie; + if (ret < 0) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -175,7 +223,34 @@ int bus_release_name_kernel_async( if (ret < 0) return ret; + if (ret_slot || callback) { + s = bus_slot_allocate(bus, !ret_slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata); + if (!s) + return -ENOMEM; + + s->reply_callback.callback = callback; + + s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m); + ret = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback); + if (ret < 0) { + s->reply_callback.cookie = 0; + return ret; + } + + s->reply_callback.timeout_usec = calc_elapse(bus, m->timeout); + if (s->reply_callback.timeout_usec != 0) { + ret = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx); + if (ret < 0) { + s->reply_callback.timeout_usec = 0; + return ret; + } + } + } + bus->rqueue[bus->rqueue_size++] = m; + if (ret_slot) + *ret_slot = s; + s = NULL; return ret; } @@ -1118,6 +1193,11 @@ int bus_add_match_internal_kernel_async( int ret; sd_bus_message *m; + /* we want room for the return message */ + ret = bus_rqueue_make_room(bus); + if (ret < 0) + return ret; + if (NULL != ret_slot) { *ret_slot = bus_slot_allocate(bus, false, BUS_KDBUS_CALLBACK, 0, NULL); if (!(*ret_slot)) -- 2.7.4