From: Daniel Mack Date: Tue, 21 Oct 2014 18:23:07 +0000 (+0200) Subject: connection: switch to absolute timeouts (API break) X-Git-Tag: upstream/0.20141102.012929utc~59 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=440b16c51cd16f218cde9eb691b27b4e9dcc4530;p=platform%2Fcore%2Fsystem%2Fkdbus-bus.git connection: switch to absolute timeouts (API break) Make the timeouts in struct kdbus_msg.timeout_ns absolute. This is necessary in order to support blocking sync calls with SA_RESTART behavior. Signed-off-by: Daniel Mack --- diff --git a/connection.c b/connection.c index 9317391..b087695 100644 --- a/connection.c +++ b/connection.c @@ -653,7 +653,7 @@ static int kdbus_conn_wait_reply(struct kdbus_ep *ep, struct kdbus_conn *conn_dst, struct kdbus_msg *msg, struct kdbus_conn_reply *reply_wait, - u64 timeout_us) + u64 timeout_ns) { struct kdbus_queue_entry *entry; int r, ret; @@ -665,7 +665,7 @@ static int kdbus_conn_wait_reply(struct kdbus_ep *ep, */ r = wait_event_interruptible_timeout(reply_wait->conn->wait, !reply_wait->waiting || !kdbus_conn_active(conn_src), - usecs_to_jiffies(timeout_us)); + nsecs_to_jiffies(timeout_ns)); if (r == 0) ret = -ETIMEDOUT; else if (r < 0) @@ -859,10 +859,22 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, name_entry = kdbus_name_unlock(bus->name_registry, name_entry); if (sync) { + struct timespec64 ts; + u64 now, timeout; + BUG_ON(!reply_wait); + + ktime_get_ts64(&ts); + now = timespec64_to_ns(&ts); + + if (unlikely(msg->timeout_ns <= now)) + timeout = 0; + else + timeout = msg->timeout_ns - now; + usecs = div_u64(msg->timeout_ns, 1000ULL); ret = kdbus_conn_wait_reply(ep, conn_src, conn_dst, msg, - reply_wait, usecs); + reply_wait, timeout); } exit_unref: diff --git a/kdbus.h b/kdbus.h index 087d50a..50b4ec4 100644 --- a/kdbus.h +++ b/kdbus.h @@ -384,7 +384,8 @@ enum kdbus_payload_type { * @timeout_ns: The time to wait for a message reply from the peer. * If there is no reply, a kernel-generated message * with an attached KDBUS_ITEM_REPLY_TIMEOUT item - * is sent to @src_id. + * is sent to @src_id. The timeout is expected in + * nanoseconds and as absolute CLOCK_MONOTONIC value. * @cookie_reply: A reply to the requesting message with the same * cookie. The requesting connection can match its * request and the reply with this value diff --git a/kdbus.txt b/kdbus.txt index 944d283..11da3ac 100644 --- a/kdbus.txt +++ b/kdbus.txt @@ -673,7 +673,8 @@ struct kdbus_msg { the timeout_ns field must be set to a non-zero number of nanoseconds in which the receiving peer is expected to reply. If such a reply is not received in time, the sender will be notified with a timeout message - (see below). + (see below). The value must be an absolute value, in nanoseconds and + based on CLOCK_MONOTONIC. For a message to be accepted as reply, it must be a direct message to the original sender (not a broadcast), and its kdbus_msg.reply_cookie @@ -737,7 +738,8 @@ struct kdbus_msg { __u64 timeout_ns; If the message sent requires a reply from the remote peer (see above), - this field contains the timeout in nanoseconds. + this field contains the timeout in absolute nanoseconds based on + CLOCK_MONOTONIC. __u64 cookie_reply; If the message sent is a reply to another message, this field must diff --git a/test/kdbus-util.c b/test/kdbus-util.c index 5b9ff06..2eef0e7 100644 --- a/test/kdbus-util.c +++ b/test/kdbus-util.c @@ -323,6 +323,7 @@ int kdbus_msg_send(const struct kdbus_conn *conn, const char ref1[1024 * 128 + 3] = "0123456789_0"; const char ref2[] = "0123456789_1"; struct kdbus_item *item; + struct timespec now; uint64_t size; int memfd = -1; int ret; @@ -369,7 +370,6 @@ int kdbus_msg_send(const struct kdbus_conn *conn, memset(msg, 0, size); msg->flags = flags; - msg->timeout_ns = timeout; msg->priority = priority; msg->size = size; msg->src_id = conn->id; @@ -377,6 +377,15 @@ int kdbus_msg_send(const struct kdbus_conn *conn, msg->cookie = cookie; msg->payload_type = KDBUS_PAYLOAD_DBUS; + if (timeout) { + ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); + if (ret < 0) + return ret; + + msg->timeout_ns = now.tv_sec * 1000000000ULL + + now.tv_nsec + timeout; + } + item = msg->items; if (name) {