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,
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);
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;
}
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;
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;
}
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))