[PATCH net-next v18 07/15] net: homa: create homa_interest.h and homa_interest.c

John Ousterhout
2026-04-10T20:03:31Z

These files implement the homa_interest struct, which is used to
wait for incoming messages.

Signed-off-by: John Ousterhout <ouster@cs.stanford.edu>

---
Changes for v18:
* Fix minor issues with indentation and lockdep annotations

Changes for v14:
* Fix race in homa_wait_shared (an RPC could get lost if it became
ready at the same time that homa_interest_wait returned with an error)
* Remove nonblocking parameter from homa_interest_wait (handle this elsewhere)

Changes for v11:
* Clean up sparse annotations

Changes for v10: none

Changes for v9:
* Remove unused field homa_interest->core
---
net/homa/homa_interest.c | 114 +++++++++++++++++++++++++++++++++++++++
net/homa/homa_interest.h | 93 ++++++++++++++++++++++++++++++++
2 files changed, 207 insertions(+)
create mode 100644 net/homa/homa_interest.c
create mode 100644 net/homa/homa_interest.h

diff --git a/net/homa/homa_interest.c b/net/homa/homa_interest.c
new file mode 100644
index 000000000000..da32e1ddce22
--- /dev/null
+++ b/net/homa/homa_interest.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: BSD-2-Clause or GPL-2.0+
+
+/* This file contains functions for managing homa_interest structs. */
+
+#include "homa_impl.h"
+#include "homa_interest.h"
+#include "homa_rpc.h"
+#include "homa_sock.h"
+
+/**
+ * homa_interest_init_shared() - Initialize an interest and queue it up on
+ * a socket.
+ * @interest: Interest to initialize
+ * @hsk: Socket on which the interests should be queued. Must be locked
+ * by caller.
+ */
+void homa_interest_init_shared(struct homa_interest *interest,
+ struct homa_sock *hsk)
+ __must_hold(hsk->lock)
+{
+ interest->rpc = NULL;
+ atomic_set(&interest->ready, 0);
+ interest->blocked = 0;
+ init_waitqueue_head(&interest->wait_queue);
+ interest->hsk = hsk;
+ list_add(&interest->links, &hsk->interests);
+}
+
+/**
+ * homa_interest_init_private() - Initialize an interest that will wait
+ * on a particular (private) RPC, and link it to that RPC.
+ * @interest: Interest to initialize.
+ * @rpc: RPC to associate with the interest. Must be private, and
+ * caller must have locked it.
+ *
+ * Return: 0 for success, otherwise a negative errno.
+ */
+int homa_interest_init_private(struct homa_interest *interest,
+ struct homa_rpc *rpc)
+ __must_hold(rpc->bucket->lock)
+{
+ if (rpc->private_interest)
+ return -EINVAL;
+
+ interest->rpc = rpc;
+ atomic_set(&interest->ready, 0);
+ interest->blocked = 0;
+ init_waitqueue_head(&interest->wait_queue);
+ interest->hsk = rpc->hsk;
+ rpc->private_interest = interest;
+ return 0;
+}
+
+/**
+ * homa_interest_wait() - Wait for an interest to have an actionable RPC,
+ * or for an error to occur.
+ * @interest: Interest to wait for; must previously have been initialized
+ * and linked to a socket or RPC. On return, the interest
+ * will have been unlinked if its ready flag is set; otherwise
+ * it may still be linked.
+ *
+ * Return: 0 for success (the ready flag is set in the interest), or -EINTR
+ * if the thread received an interrupt.
+ */
+int homa_interest_wait(struct homa_interest *interest)
+{
+ struct homa_sock *hsk = interest->hsk;
+ int result = 0;
+ int iteration;
+ int wait_err;
+
+ interest->blocked = 0;
+
+ /* This loop iterates in order to poll and/or reap dead RPCS. */
+ for (iteration = 0; ; iteration++) {
+ if (iteration != 0)
+ /* Give NAPI/SoftIRQ tasks a chance to run. */
+ schedule();
+
+ if (atomic_read_acquire(&interest->ready) != 0)
+ goto done;
+
+ /* See if we can cleanup dead RPCs while waiting. */
+ if (homa_rpc_reap(hsk, false) != 0)
+ continue;
+
+ break;
+ }
+
+ interest->blocked = 1;
+ wait_err = wait_event_interruptible_exclusive(interest->wait_queue,
+ atomic_read_acquire(&interest->ready) != 0);
+ if (wait_err == -ERESTARTSYS)
+ result = -EINTR;
+
+done:
+ return result;
+}
+
+/**
+ * homa_interest_notify_private() - If a thread is waiting on the private
+ * interest for an RPC, wake it up.
+ * @rpc: RPC that may (potentially) have a private interest. Must be
+ * locked by the caller.
+ */
+void homa_interest_notify_private(struct homa_rpc *rpc)
+ __must_hold(rpc->bucket->lock)
+{
+ if (rpc->private_interest) {
+ atomic_set_release(&rpc->private_interest->ready, 1);
+ wake_up(&rpc->private_interest->wait_queue);
+ }
+}
+
diff --git a/net/homa/homa_interest.h b/net/homa/homa_interest.h
new file mode 100644
index 000000000000..8d16f82d1343
--- /dev/null
+++ b/net/homa/homa_interest.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-2-Clause or GPL-2.0+ */
+
+/* This file defines struct homa_interest and related functions. */
+
+#ifndef _HOMA_INTEREST_H
+#define _HOMA_INTEREST_H
+
+#include "homa_rpc.h"
+#include "homa_sock.h"
+
+/**
+ * struct homa_interest - Holds info that allows applications to wait for
+ * incoming RPC messages. An interest can be either private, in which case
+ * the application is waiting for a single specific RPC response and the
+ * interest is referenced by an rpc->private_interest, or shared, in which
+ * case the application is waiting for any incoming message that isn't
+ * private and the interest is present on hsk->interests.
+ */
+struct homa_interest {
+ /**
+ * @rpc: If ready is set, then this holds an RPC that needs
+ * attention, or NULL if this is a shared interest and hsk has
+ * been shutdown. If ready is not set, this will be NULL if the
+ * interest is shared; if it's private, it holds the RPC the
+ * interest is associated with. If non-NULL, a reference has been
+ * taken on the RPC.
+ */
+ struct homa_rpc *rpc;
+
+ /**
+ * @ready: Nonzero means the interest is ready for attention: either
+ * there is an RPC that needs attention or @hsk has been shutdown.
+ */
+ atomic_t ready;
+
+ /**
+ * @blocked: Zero means a handoff was received without the thread
+ * needing to block; nonzero means the thread blocked.
+ */
+ int blocked;
+
+ /**
+ * @wait_queue: Used to block the thread while waiting (will never
+ * have more than one queued thread).
+ */
+ struct wait_queue_head wait_queue;
+
+ /** @hsk: Socket that the interest is associated with. */
+ struct homa_sock *hsk;
+
+ /**
+ * @links: If the interest is shared, used to link this object into
+ * @hsk->interests.
+ */
+ struct list_head links;
+};
+
+/**
+ * homa_interest_unlink_shared() - Remove an interest from the list for a
+ * socket. Note: this can race with homa_rpc_handoff, so on return it's
+ * possible that the interest is ready.
+ * @interest: Interest to remove. Must have been initialized with
+ * homa_interest_init_shared.
+ */
+static inline void homa_interest_unlink_shared(struct homa_interest *interest)
+ __must_hold(interest->hsk->lock)
+{
+ list_del_init(&interest->links);
+}
+
+/**
+ * homa_interest_unlink_private() - Detach a private interest from its
+ * RPC. Note: this can race with homa_rpc_handoff, so on return it's
+ * possible that the interest is ready.
+ * @interest: Interest to remove. Must have been initialized with
+ * homa_interest_init_private. Its RPC must be locked by
+ * the caller.
+ */
+static inline void homa_interest_unlink_private(struct homa_interest *interest)
+ __must_hold(interest->rpc->bucket->lock)
+{
+ if (interest == interest->rpc->private_interest)
+ interest->rpc->private_interest = NULL;
+}
+
+void homa_interest_init_shared(struct homa_interest *interest,
+ struct homa_sock *hsk);
+int homa_interest_init_private(struct homa_interest *interest,
+ struct homa_rpc *rpc);
+void homa_interest_notify_private(struct homa_rpc *rpc);
+int homa_interest_wait(struct homa_interest *interest);
+
+#endif /* _HOMA_INTEREST_H */
--
2.43.0