[systemd-devel] [RFC 6/8] HACK2: blocking ioctl(CMD_MSG_RECV)
AKASHI Takahiro
takahiro.akashi at linaro.org
Wed Jun 25 02:13:35 PDT 2014
In the current implementation, ioctl(CMD_MSG_RECV) returns immediately if
no message has been queued, and so a service process has to wait by
explicitly calling poll() system call. If such a process needs to wait only
on a single connection, we can eliminate poll() system call by adding a
synchronous attribute in receiving a message.
This patch allows us to specify a flag, KDBUS_HELLO_BLOCK, in HELLO command
and enable the feature. Please note that this is a quick hack, ignoring how
this feature and poll() could co-exist.
Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
connection.c | 39 +++++++++++++++++++++++++++++++++++++++
connection.h | 1 +
kdbus.h | 1 +
3 files changed, 41 insertions(+)
diff --git a/connection.c b/connection.c
index d122be8..5969ead 100644
--- a/connection.c
+++ b/connection.c
@@ -41,6 +41,7 @@
/*
* KDBUS_HACK1: optimize copy operations in kdbus_conn_queue_alloc()
+ * KDBUS_HACK2: add a blocking attribute to ioctl(CMD_MSG_RECV)
*/
struct kdbus_conn_reply;
@@ -795,6 +796,11 @@ static int kdbus_conn_queue_insert(struct kdbus_conn *conn,
/* wake up poll() */
wake_up_interruptible(&conn->wait);
+#if KDBUS_HACK2
+ if (conn->flags | KDBUS_HELLO_BLOCK)
+ wake_up_interruptible(&conn->wait_recv);
+#endif
+
return 0;
exit_queue_free:
@@ -1024,9 +1030,31 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn,
int ret = 0;
mutex_lock(&conn->lock);
+recv_again:
if (conn->msg_count == 0) {
+#if KDBUS_HACK2
+ if (conn->flags | KDBUS_HELLO_BLOCK) {
+ mutex_unlock(&conn->lock);
+ /* FIXME: there is a small window here. */
+ wait_event_interruptible(conn->wait_recv,
+ conn->msg_count);
+ mutex_lock(&conn->lock);
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ goto exit_unlock;
+ } else if (conn->disconnected) {
+ ret = -ESHUTDOWN;
+ goto exit_unlock;
+ }
+ goto recv_again;
+ } else {
+ ret = -EAGAIN;
+ goto exit_unlock;
+ }
+#else
ret = -EAGAIN;
goto exit_unlock;
+#endif
}
if (recv->offset > 0) {
@@ -1606,6 +1634,10 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
/* wake up the queue so that users can get a POLLERR */
wake_up_interruptible(&conn->wait);
+#if KDBUS_HACK2
+ if (conn->flags | KDBUS_HELLO_BLOCK)
+ wake_up_interruptible(&conn->wait_recv);
+#endif
kdbus_notify_id_change(conn->bus, KDBUS_ITEM_ID_REMOVE, conn->id,
conn->flags);
@@ -1748,6 +1780,10 @@ int kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
/* wake up poll() */
wake_up_interruptible(&conn_dst->wait);
+#if KDBUS_HACK2
+ if (conn_dst->flags | KDBUS_HELLO_BLOCK)
+ wake_up_interruptible(&conn_dst->wait_recv);
+#endif
return ret;
}
@@ -2058,6 +2094,9 @@ int kdbus_conn_new(struct kdbus_ep *ep,
INIT_DELAYED_WORK(&conn->work, kdbus_conn_work);
conn->cred = current_cred();
init_waitqueue_head(&conn->wait);
+#if KDBUS_HACK2
+ init_waitqueue_head(&conn->wait_recv);
+#endif
/* init entry, so we can unconditionally remove it */
INIT_LIST_HEAD(&conn->monitor_entry);
diff --git a/connection.h b/connection.h
index 46f7b6e..17a05b8 100644
--- a/connection.h
+++ b/connection.h
@@ -92,6 +92,7 @@ struct kdbus_conn {
size_t msg_count;
atomic_t reply_count;
wait_queue_head_t wait;
+ wait_queue_head_t wait_recv;
};
struct kdbus_kmsg;
diff --git a/kdbus.h b/kdbus.h
index 0b189cb..8f91f49 100644
--- a/kdbus.h
+++ b/kdbus.h
@@ -492,6 +492,7 @@ enum kdbus_hello_flags {
KDBUS_HELLO_ACTIVATOR = 1 << 1,
KDBUS_HELLO_POLICY_HOLDER = 1 << 2,
KDBUS_HELLO_MONITOR = 1 << 3,
+ KDBUS_HELLO_BLOCK = 1 << 4,
};
/**
--
1.7.9.5
More information about the systemd-devel
mailing list