Files
jsix_import/src/kernel/syscalls/mailbox.cpp
Justin C. Miller 9ac4e51224 [kernel] Make capabilities/handles global
Instead of handles / capabilities having numeric ids that are only valid
for the owning process, they are now global in a system capabilities
table. This will allow for specifying capabilities in IPC that doesn't
need to be kernel-controlled.

Processes will still need to be granted access to given capabilities,
but that can become a simpler system call than the current method of
sending them through mailbox messages (and worse, having to translate
every one into a new capability like was the case before). In order to
track which handles a process has access to, a new node_set based on
node_map allows for an efficient storage and lookup of handles.
2022-10-10 21:19:25 -07:00

213 lines
4.3 KiB
C++

#include <j6/errors.h>
#include <j6/flags.h>
#include <util/util.h>
#include "objects/mailbox.h"
#include "objects/thread.h"
#include "syscalls/helpers.h"
using namespace obj;
namespace syscalls {
j6_status_t
mailbox_create(j6_handle_t *self)
{
construct_handle<mailbox>(self);
return j6_status_ok;
}
j6_status_t
mailbox_close(mailbox *self)
{
if (self->closed())
return j6_status_closed;
self->close();
return j6_status_ok;
}
j6_status_t
prep_send(
mailbox::message *msg,
uint64_t tag,
uint64_t subtag,
const j6_handle_t *handles,
size_t handle_count)
{
if (!msg ||
handle_count > mailbox::max_handle_count)
return j6_err_invalid_arg;
msg->tag = tag;
msg->subtag = subtag;
msg->handle_count = handle_count;
memcpy(msg->handles, handles, sizeof(j6_handle_t) * handle_count);
return j6_status_ok;
}
void
prep_receive(
mailbox::message *msg,
uint64_t *tag,
uint64_t *subtag,
uint16_t *reply_tag,
j6_handle_t *handles,
size_t *handle_count)
{
if (tag) *tag = msg->tag;
if (subtag) *subtag = msg->subtag;
if (reply_tag) *reply_tag = msg->reply_tag;
*handle_count = msg->handle_count;
process &proc = process::current();
for (size_t i = 0; i < msg->handle_count; ++i) {
proc.add_handle(msg->handles[i]);
handles[i] = msg->handles[i];
}
}
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
mailbox_call(
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;
}
if (!self->call(msg)) {
delete msg;
return self->closed() ? j6_status_closed :
j6_err_unexpected;
}
prep_receive(msg,
tag, subtag, 0,
handles, handle_count);
delete msg;
return j6_status_ok;
}
j6_status_t
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,
uint64_t *tag,
uint64_t *subtag,
j6_handle_t *handles,
size_t *handle_count,
size_t handles_in,
uint16_t *reply_tag,
uint64_t flags)
{
j6_status_t s = mailbox_respond(self, *tag, *subtag, handles, handles_in, *reply_tag);
if (s != j6_status_ok)
return s;
s = mailbox_receive(self, tag, subtag, handles, handle_count, reply_tag, flags);
if (s != j6_status_ok)
return s;
return j6_status_ok;
}
} // namespace syscalls