+static bool
+udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd,
+ bool wait)
+{
+ struct iovec iov = {
+ .iov_base = msg,
+ .iov_len = sizeof(*msg)
+ };
+ int ret;
+
+ ret = recv_retry(ctx->fd.fd, &iov, wait, fd);
+ if (ret == -2)
+ __udebug_disconnect(ctx, true);
+
+ return ret == sizeof(*msg);
+}
+
+static struct udebug_client_msg *
+__udebug_poll(struct udebug *ctx, int *fd, bool wait)
+{
+ static struct udebug_client_msg msg = {};
+
+ while (udebug_recv_msg(ctx, &msg, fd, wait)) {
+ struct udebug_remote_buf *rb;
+ void *key;
+
+ if (msg.type != CL_MSG_RING_NOTIFY)
+ return &msg;
+
+ if (fd && *fd >= 0)
+ close(*fd);
+
+ if (!ctx->notify_cb)
+ continue;
+
+ key = (void *)(uintptr_t)msg.id;
+ rb = avl_find_element(&ctx->remote_rings, key, rb, node);
+ if (!rb || !rb->poll)
+ continue;
+
+ if (ctx->poll_handle >= 0)
+ __atomic_fetch_or(&rb->buf.hdr->notify,
+ 1UL << ctx->poll_handle,
+ __ATOMIC_RELAXED);
+ ctx->notify_cb(ctx, rb);
+ }
+
+ return NULL;
+}
+
+static struct udebug_client_msg *
+udebug_wait_for_response(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
+{
+ int type = msg->type;
+ int fd = -1;
+
+ do {
+ if (fd >= 0)
+ close(fd);
+ fd = -1;
+ msg = __udebug_poll(ctx, &fd, true);
+ } while (msg && msg->type != type);
+ if (!msg)
+ return NULL;
+
+ if (rfd)
+ *rfd = fd;
+ else if (fd >= 0)
+ close(fd);
+
+ return msg;
+}
+