From: Daniel Mack Date: Sun, 19 Jan 2014 20:16:43 +0000 (+0100) Subject: connection: assorted sync_reply fixes and cleanups X-Git-Tag: upstream/0.20140120.123719~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=64c6b7522a25f01d15185d35ea060ee94cc79a8a;p=platform%2Fcore%2Fsystem%2Fkdbus-bus.git connection: assorted sync_reply fixes and cleanups --- diff --git a/connection.c b/connection.c index 8313476..cd2d87e 100644 --- a/connection.c +++ b/connection.c @@ -96,20 +96,34 @@ struct kdbus_conn_reply_entry { u64 deadline_ns; u64 cookie; wait_queue_head_t wait; - bool waiting; + bool waiting:1; + bool sync:1; u64 offset; }; static void kdbus_conn_reply_entry_free(struct kdbus_conn_reply_entry *reply) { - reply->waiting = false; - wake_up_interruptible(&reply->wait); atomic_dec(&reply->conn->reply_count); list_del(&reply->entry); kdbus_conn_unref(reply->conn); kfree(reply); } +static void kdbus_conn_reply_entry_finish(struct kdbus_conn *conn, + struct kdbus_conn_reply_entry *reply, + u64 offset) +{ + if (reply->sync) { + mutex_lock(&conn->lock); + reply->waiting = false; + reply->offset = offset; + mutex_unlock(&conn->lock); + wake_up_interruptible(&reply->wait); + } else { + kdbus_conn_reply_entry_free(reply); + } +} + static void kdbus_conn_fds_unref(struct kdbus_conn_queue *queue) { unsigned int i; @@ -620,7 +634,7 @@ static void kdbus_conn_scan_timeout(struct kdbus_conn *conn) * the timeout is handled by wait_event_*_timeout(), * so we don't have to care for it here. */ - if (reply->waiting) + if (reply->sync) continue; if (reply->deadline_ns > now) { @@ -1052,7 +1066,6 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, return ret; if (conn_src) { - bool allowed = false; struct kdbus_conn_reply_entry *r; /* @@ -1071,15 +1084,13 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, continue; reply_wake = r; - allowed = true; break; } - mutex_unlock(&conn_dst->lock); } /* ... otherwise, ask the policy DB for permission */ - if (!allowed && ep->policy_db) { + if (!reply_wake && ep->policy_db) { ret = kdbus_policy_db_check_send_access(ep->policy_db, conn_src, conn_dst); @@ -1105,20 +1116,21 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, goto exit_unref; } - init_waitqueue_head(&reply->wait); reply->conn = kdbus_conn_ref(conn_dst); reply->cookie = msg->cookie; if (msg->flags & KDBUS_MSG_FLAGS_SYNC_REPLY) { + init_waitqueue_head(&reply->wait); reply->offset = ~0ULL; + reply->sync = true; reply->waiting = true; reply_wait = reply; + } else { + /* calculate the deadline based on the current time */ + ktime_get_ts(&ts); + reply->deadline_ns = timespec_to_ns(&ts) + msg->timeout_ns; } - /* calculate the deadline based on the current time */ - ktime_get_ts(&ts); - reply->deadline_ns = timespec_to_ns(&ts) + msg->timeout_ns; - mutex_lock(&conn_src->lock); list_add(&reply->entry, &conn_src->reply_list); atomic_inc(&reply->conn->reply_count); @@ -1160,7 +1172,7 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, if (reply_wait) { u64 us = msg->timeout_ns; - struct kdbus_cmd_recv recv = {}; + struct kdbus_cmd_recv recv; do_div(us, 1000ULL); @@ -1171,18 +1183,23 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, */ if (!wait_event_interruptible_timeout(reply_wait->wait, !reply_wait->waiting, - usecs_to_jiffies(us))) { + usecs_to_jiffies(us))) ret = -ETIMEDOUT; - goto exit_unref; - } - if (reply_wait->offset == ~0ULL) { + recv.offset = reply_wait->offset; + recv.flags = 0; + + if (ret == 0 && reply_wait->offset == ~0ULL) ret = -EPIPE; + + mutex_lock(&conn_src->lock); + kdbus_conn_reply_entry_free(reply_wait); + mutex_unlock(&conn_src->lock); + + if (ret < 0) goto exit_unref; - } - kmsg->msg.offset_reply = reply_wait->offset; - recv.offset = reply_wait->offset; + kmsg->msg.offset_reply = recv.offset; ret = kdbus_conn_recv_msg(conn_src, &recv); if (ret < 0) @@ -1194,10 +1211,8 @@ exit_unref: * reply_wake is only non-NULL if it refers to a handled reply, * and kdbus_conn_reply_entry_free() will wake up the wait queue. */ - if (reply_wake) { - reply_wake->offset = offset; - kdbus_conn_reply_entry_free(reply_wake); - } + if (reply_wake) + kdbus_conn_reply_entry_finish(conn_src, reply_wake, offset); /* conn_dst got an extra ref from kdbus_conn_get_conn_dst */ kdbus_conn_unref(conn_dst); @@ -1367,7 +1382,7 @@ static void __kdbus_conn_free(struct kref *kref) kdbus_policy_db_remove_conn(conn->ep->policy_db, conn); list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) - kdbus_conn_reply_entry_free(reply); + kdbus_conn_reply_entry_finish(conn, reply, ~0ULL); kdbus_meta_free(conn->owner_meta); kdbus_match_db_free(conn->match_db);