[kernel] Make mailbox non-fixed-length again

Going back to letting mailboxes use variable-length data. Note that this
requires extra copies, so shared memory channels should be used for
anything in the hot path. But this allows better RPC over mailboxes and
other flexibility.

Other changes:
- added a j6::proto::sl::client class to act as a service locator
  client, instead of duplicating that code in every program.
- moved protocol ids into j6/tables/protocols.inc so that C++ clients
  can easily have their own API
This commit is contained in:
Justin C. Miller
2023-08-07 22:59:03 -07:00
parent a0f91ed0fd
commit 8b3fa3ed01
22 changed files with 329 additions and 81 deletions

View File

@@ -7,6 +7,34 @@ enum j6_proto_base_tag
j6_proto_base_status,
j6_proto_base_get_proto_id,
j6_proto_base_proto_id,
j6_proto_base_open_channel,
j6_proto_base_opened_channel,
j6_proto_base_first_proto_id /// The first protocol-specific ID
};
#ifdef __cplusplus
#include <util/hash.h>
namespace j6::proto {
enum class style { mailbox, channel };
#define PROTOCOL(name, desc, type) namespace name { \
inline constexpr uint64_t id = #desc##_id; \
inline constexpr proto::style style = proto::style:: type; }
#include <j6/tables/protocols.inc>
#undef PROTOCOL
} // namespace j6::proto
#endif // __cplusplus
extern "C" const uint64_t j6_proto_style_mailbox;
extern "C" const uint64_t j6_proto_style_channel;
#define PROTOCOL(name, desc, type) \
extern "C" const uint64_t j6_proto_ ## name ## _id; \
extern "C" const uint64_t j6_proto_ ## name ## _style;
#include <j6/tables/protocols.inc>
#undef PROTOCOL

View File

@@ -0,0 +1,13 @@
#pragma once
/// \file protocols.hh
/// High-level C++ base protocol interface
namespace j6::proto {
class client
{
public:
};
} // namespace j6::proto

View File

@@ -4,8 +4,6 @@
#include <j6/protocols.h>
extern const uint64_t j6_proto_sl_id;
enum j6_proto_sl_tag
{
j6_proto_sl_register = j6_proto_base_first_proto_id,

View File

@@ -0,0 +1,27 @@
#include <j6/protocols/service_locator.h>
#include <j6/types.h>
namespace j6::proto::sl {
class client
{
public:
/// Constructor.
/// \arg slp_mb Handle to the service locator service's mailbox
client(j6_handle_t slp_mb);
/// Register a handle as a service with the locator.
/// \arg proto_id The protocol this handle supports
/// \arg handle The mailbox or channel handle
j6_status_t register_service(uint64_t proto_id, j6_handle_t handle);
/// Look up a handle with the locator service.
/// \arg proto_id The protocol to look for
/// \arg handle [out] The mailbox or channel handle
j6_status_t lookup_service(uint64_t proto_id, j6_handle_t &handle);
private:
j6_handle_t m_service;
};
} // namespace j6::proto::sl

View File

@@ -0,0 +1,2 @@
PROTOCOL(sl, service_locator, mailbox)
PROTOCOL(vfs, virtual_filesystem, channel)

View File

@@ -11,6 +11,7 @@ j6 = module("j6",
"memutils.cpp",
"mutex.cpp",
"protocol_ids.cpp",
"protocols/service_locator.cpp",
"syscalls.s.cog",
"sysconf.cpp.cog",
"syslog.cpp",
@@ -27,6 +28,7 @@ j6 = module("j6",
"j6/memutils.h",
"j6/protocols.h",
"j6/protocols/service_locator.h",
"j6/protocols/service_locator.hh",
"j6/syscalls.h.cog",
"j6/sysconf.h.cog",
"j6/syslog.hh",

View File

@@ -1,4 +1,10 @@
#include <util/hash.h>
#include <j6/protocols.h>
extern "C"
const uint64_t j6_proto_sl_id = "jsix.protocol.service_locator"_id;
extern "C" const uint64_t j6_proto_style_mailbox = (uint64_t)j6::proto::style::mailbox;
extern "C" const uint64_t j6_proto_style_channel = (uint64_t)j6::proto::style::channel;
#define PROTOCOL(name, desc, type) \
extern "C" const uint64_t j6_proto_##name##_id = j6::proto::name::id; \
extern "C" const uint64_t j6_proto_##name##_style = j6_proto_style_##type;
#include <j6/tables/protocols.inc>

View File

@@ -0,0 +1,64 @@
#include <j6/errors.h>
#include <j6/protocols/service_locator.hh>
#include <j6/syscalls.h>
#include <j6/syslog.hh>
#ifndef __j6kernel
namespace j6::proto::sl {
client::client(j6_handle_t slp_mb) :
m_service {slp_mb}
{
}
j6_status_t
client::register_service(uint64_t proto_id, j6_handle_t handle)
{
uint64_t tag = j6_proto_sl_register;
size_t handle_count = 1;
size_t data = proto_id;
size_t data_size = sizeof(proto_id);
j6_status_t s = j6_mailbox_call(m_service, &tag,
&data, &data_size, data_size,
&handle, &handle_count);
if (s != j6_status_ok)
return s;
if (tag == j6_proto_base_status)
return data; // contains a status
return j6_err_unexpected;
}
j6_status_t
client::lookup_service(uint64_t proto_id, j6_handle_t &handle)
{
uint64_t tag = j6_proto_sl_find;
size_t handle_count = 1;
size_t data = proto_id;
size_t data_size = sizeof(proto_id);
handle = j6_handle_invalid;
j6::syslog("Looking up service for %x", proto_id);
j6_status_t s = j6_mailbox_call(m_service, &tag,
&data, &data_size, data_size,
&handle, &handle_count);
if (s != j6_status_ok)
return s;
if (tag == j6_proto_sl_result)
return j6_status_ok; // handle is already in `handle`
else if (tag == j6_proto_base_status)
return data; // contains a status
return j6_err_unexpected;
}
} // namespace j6::proto::sl
#endif // __j6kernel