[kernel] Simplify mailbox interface to call/respond

The only real usage of mailbox was mailbox_call or
mailbox_respond_receive. This change simplifies the interface to just
these syscalls.
This commit is contained in:
Justin C. Miller
2022-10-11 17:36:23 -07:00
parent 9ac4e51224
commit c9bcc87511
5 changed files with 53 additions and 157 deletions

View File

@@ -1,5 +1,5 @@
# Mailboxes are objects that enable synchronous or asynchronous # Mailboxes are objects that enable synchronous IPC via short message-passing
# IPC via short message-passing of bytes and handles. # of tagged handles.
object mailbox : object { object mailbox : object {
uid 99934ad04ece1e07 uid 99934ad04ece1e07
@@ -13,23 +13,6 @@ object mailbox : object {
method create [constructor] method create [constructor]
method close [destructor cap:close] method close [destructor cap:close]
# Asynchronously send a message to the reciever
method send [cap:send] {
param tag uint64
param subtag uint64
param handles ref object [list]
}
# Receive a pending message, or block waiting for a message to
# arrive if block is true.
method receive [cap:receive] {
param tag uint64 [out]
param subtag uint64 [out]
param handles ref object [out list zero_ok]
param reply_tag uint16 [out optional]
param flags uint64
}
# Send a message to the reciever, and block until a # Send a message to the reciever, and block until a
# response is sent. Note that getting this response # response is sent. Note that getting this response
# does not require the receive capability. # does not require the receive capability.
@@ -39,19 +22,11 @@ object mailbox : object {
param handles ref object [inout list zero_ok] param handles ref object [inout list zero_ok]
} }
# Respond to a message sent using call. Note that this
# requires the receive capability and not the send capability.
method respond [cap:receive] {
param tag uint64
param subtag uint64
param handles ref object [list zero_ok]
param reply_tag uint16
}
# Respond to a message sent using call, and wait for another # Respond to a message sent using call, and wait for another
# message to arrive. Note that this does not require the send # message to arrive. Note that this does not require the send
# capability. # capability. A reply tag of 0 skips the reply and goes directly
method respond_receive [cap:receive] { # to waiting for a new message.
method respond [cap:receive] {
param tag uint64 [inout] param tag uint64 [inout]
param subtag uint64 [inout] param subtag uint64 [inout]
param handles ref object [inout list zero_ok] param handles ref object [inout list zero_ok]

View File

@@ -45,18 +45,6 @@ mailbox::close()
m_queue.clear(); m_queue.clear();
} }
void
mailbox::send(message *msg)
{
util::scoped_lock lock {m_message_lock};
m_messages.push_back(msg);
thread *t = m_queue.pop_next();
lock.release();
if (t) t->wake(has_message);
}
bool bool
mailbox::call(message *msg) mailbox::call(message *msg)
{ {

View File

@@ -39,11 +39,6 @@ public:
/// Check if the mailbox has been closed /// Check if the mailbox has been closed
inline bool closed() const { return m_closed; } inline bool closed() const { return m_closed; }
/// Send a message to a thread waiting to receive on this mailbox. If no threads
/// are currently trying to receive, block the current thread.
/// \arg msg The mailbox::message data structure to send
void send(message *msg);
/// Send a message to a thread waiting to receive on this mailbox, and block the /// Send a message to a thread waiting to receive on this mailbox, and block the
/// current thread awaiting a response. The response will be placed in the message /// current thread awaiting a response. The response will be placed in the message
/// object provided. /// object provided.

View File

@@ -69,63 +69,6 @@ prep_receive(
} }
} }
j6_status_t
mailbox_send(
mailbox *self,
uint64_t tag,
uint64_t subtag,
j6_handle_t * handles,
size_t handle_count)
{
mailbox::message *msg = new mailbox::message;
j6_status_t s = prep_send(msg,
tag, subtag,
handles, handle_count);
if (s != j6_status_ok) {
delete msg;
return s;
}
self->send(msg);
return j6_status_ok;
}
j6_status_t
mailbox_receive(
mailbox *self,
uint64_t *tag,
uint64_t *subtag,
j6_handle_t *handles,
size_t *handle_count,
uint16_t *reply_tag,
uint64_t flags)
{
if (*handle_count < mailbox::max_handle_count)
return j6_err_insufficient;
mailbox::message *msg = nullptr;
bool block = flags & j6_mailbox_block;
if (!self->receive(msg, block)) {
// No message received
return self->closed() ? j6_status_closed :
!block ? j6_status_would_block :
j6_err_unexpected;
}
prep_receive(msg,
tag, subtag, reply_tag,
handles, handle_count);
if (*reply_tag == 0)
delete msg;
return j6_status_ok;
}
j6_status_t j6_status_t
mailbox_call( mailbox_call(
mailbox *self, mailbox *self,
@@ -159,34 +102,8 @@ mailbox_call(
return j6_status_ok; return j6_status_ok;
} }
j6_status_t j6_status_t
mailbox_respond( mailbox_respond(
mailbox *self,
uint64_t tag,
uint64_t subtag,
j6_handle_t * handles,
size_t handle_count,
uint16_t reply_tag)
{
mailbox::replyer reply = self->reply(reply_tag);
if (!reply.valid())
return j6_err_invalid_arg;
j6_status_t s = prep_send(reply.msg, tag, subtag,
handles, handle_count);
if (s != j6_status_ok) {
reply.error(s);
return s;
}
return j6_status_ok;
}
j6_status_t
mailbox_respond_receive(
mailbox *self, mailbox *self,
uint64_t *tag, uint64_t *tag,
uint64_t *subtag, uint64_t *subtag,
@@ -196,17 +113,43 @@ mailbox_respond_receive(
uint16_t *reply_tag, uint16_t *reply_tag,
uint64_t flags) uint64_t flags)
{ {
j6_status_t s = mailbox_respond(self, *tag, *subtag, handles, handles_in, *reply_tag); if (*reply_tag) {
if (s != j6_status_ok) mailbox::replyer reply = self->reply(*reply_tag);
return s; if (!reply.valid())
return j6_err_invalid_arg;
s = mailbox_receive(self, tag, subtag, handles, handle_count, reply_tag, flags); j6_status_t s = prep_send(reply.msg, *tag, *subtag,
if (s != j6_status_ok) handles, handles_in);
if (s != j6_status_ok) {
reply.error(s);
return s; return s;
}
}
if (*handle_count < mailbox::max_handle_count)
return j6_err_insufficient;
mailbox::message *msg = nullptr;
bool block = flags & j6_mailbox_block;
if (!self->receive(msg, block)) {
// No message received
return self->closed() ? j6_status_closed :
!block ? j6_status_would_block :
j6_err_unexpected;
}
prep_receive(msg,
tag, subtag, reply_tag,
handles, handle_count);
if (*reply_tag == 0)
delete msg;
return j6_status_ok; return j6_status_ok;
} }
} // namespace syscalls } // namespace syscalls

View File

@@ -23,22 +23,26 @@ service_locator_start(j6_handle_t mb)
// TODO: This should be a multimap // TODO: This should be a multimap
util::node_map<uint64_t, handle_entry> services; util::node_map<uint64_t, handle_entry> services;
uint64_t tag; uint64_t tag = 0;
uint64_t subtag; uint64_t subtag = 0;
uint16_t reply_tag; uint16_t reply_tag = 0;
j6_handle_t handles[10]; j6_handle_t handles[10] = {0};
size_t handles_count = sizeof(handles)/sizeof(j6_handle_t); const size_t handles_capacity = sizeof(handles)/sizeof(j6_handle_t);
size_t handles_count = 0;
j6_status_t s = j6_mailbox_receive(mb,
&tag, &subtag,
handles, &handles_count,
&reply_tag,
j6_mailbox_block);
uint64_t proto_id; uint64_t proto_id;
while (true) { while (true) {
size_t handles_in = handles_count;
handles_count = handles_capacity;
j6_status_t s = j6_mailbox_respond(mb,
&tag, &subtag,
handles, &handles_count,
handles_in, &reply_tag,
j6_mailbox_block);
handle_entry *found = nullptr; handle_entry *found = nullptr;
switch (tag) { switch (tag) {
@@ -82,14 +86,5 @@ service_locator_start(j6_handle_t mb)
handles_count = 0; handles_count = 0;
break; break;
} }
size_t handles_in = handles_count;
handles_count = sizeof(handles)/sizeof(j6_handle_t);
s = j6_mailbox_respond_receive(mb,
&tag, &subtag,
handles, &handles_count, handles_in,
&reply_tag,
j6_mailbox_block);
} }
} }