[srv.init] Serve a service locator protocol from init

The init process now serves as a service locator for its children,
passing all children a mailbox handle on which it is serving the service
locator protocol.
This commit is contained in:
Justin C. Miller
2022-02-28 20:23:18 -08:00
parent ef307e8ec6
commit 17dcb961ec
10 changed files with 165 additions and 4 deletions

View File

@@ -2,8 +2,10 @@
j6 = module("j6",
kind = "lib",
deps = [ "util" ],
sources = [
"init.cpp",
"protocol_ids.cpp",
"syscalls.s.cog",
"sysconf.cpp.cog",
],
@@ -12,6 +14,8 @@ j6 = module("j6",
"j6/errors.h",
"j6/flags.h",
"j6/init.h",
"j6/protocols.h",
"j6/protocols/service_locator.h",
"j6/syscalls.h.cog",
"j6/sysconf.h.cog",
"j6/types.h",

View File

@@ -0,0 +1,12 @@
#pragma once
/// \file j6/protocols.h
/// Common definition for j6 user-mode IPC protocols
enum j6_proto_base_tag
{
j6_proto_base_status,
j6_proto_base_get_proto_id,
j6_proto_base_proto_id,
j6_proto_base_first_proto_id /// The first protocol-specific ID
};

View File

@@ -0,0 +1,14 @@
#pragma once
/// \file j6/protocols/service_locator.h
/// Definitions for the service locator protocol
#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,
j6_proto_sl_find,
j6_proto_sl_result,
};

View File

@@ -0,0 +1,4 @@
#include <util/hash.h>
extern "C"
const uint64_t j6_proto_sl_id = "jsix.protocol.service_locator"_id;

View File

@@ -8,6 +8,7 @@ init = module("srv.init",
"loader.cpp",
"main.cpp",
"modules.cpp",
"service_locator.cpp",
"start.s",
])

View File

@@ -19,7 +19,10 @@ constexpr size_t stack_size = 0x10000;
constexpr uintptr_t stack_top = 0x80000000000;
bool
load_program(const module_program &prog, j6_handle_t sys, char *err_msg)
load_program(
const module_program &prog,
j6_handle_t sys, j6_handle_t slp,
char *err_msg)
{
if (prog.mod_flags && module_flags::no_load) {
sprintf(err_msg, " skipping pre-loaded program module '%s' at %lx", prog.filename, prog.base_address);
@@ -60,6 +63,12 @@ load_program(const module_program &prog, j6_handle_t sys, char *err_msg)
return false;
}
res = j6_process_give_handle(proc, slp, nullptr);
if (res != j6_status_ok) {
sprintf(err_msg, " ** error loading program '%s': giving SLP handle: %lx", prog.filename, res);
return false;
}
for (auto &seg : progelf.programs()) {
if (seg.type != elf::segment_type::load)
continue;

View File

@@ -8,4 +8,7 @@ namespace bootproto {
struct module_program;
}
bool load_program(const bootproto::module_program &prog, j6_handle_t sys, char *err_msg);
bool load_program(
const bootproto::module_program &prog,
j6_handle_t sys, j6_handle_t slp,
char *err_msg);

View File

@@ -10,6 +10,7 @@
#include "loader.h"
#include "modules.h"
#include "service_locator.h"
using bootproto::module;
using bootproto::module_type;
@@ -28,6 +29,9 @@ main(int argc, const char **argv)
{
j6_status_t s;
j6_handle_t slp_mb = j6_handle_invalid;
j6_handle_t slp_mb_child = j6_handle_invalid;
j6_handle_t sys = j6_handle_invalid;
j6_handle_t sys_child = j6_handle_invalid;
@@ -45,6 +49,13 @@ main(int argc, const char **argv)
if (s != j6_status_ok)
return s;
s = j6_mailbox_create(&slp_mb);
if (s != j6_status_ok)
return s;
s = j6_handle_clone(slp_mb, &slp_mb_child,
j6_cap_mailbox_send |
j6_cap_object_clone);
if (s != j6_status_ok)
return s;
@@ -57,11 +68,12 @@ main(int argc, const char **argv)
sprintf(message, " loading program module '%s' at %lx", prog.filename, prog.base_address);
j6_log(message);
if (!load_program(prog, sys_child, message)) {
if (!load_program(prog, sys_child, slp_mb_child, message)) {
j6_log(message);
return 1;
return 2;
}
}
service_locator_start(slp_mb);
return 0;
}

View File

@@ -0,0 +1,97 @@
#include <unordered_map>
#include <j6/errors.h>
#include <j6/flags.h>
#include <j6/types.h>
#include <j6/protocols/service_locator.h>
#include <j6/syscalls.h>
#include <util/map.h>
#include "service_locator.h"
void
service_locator_start(j6_handle_t mb)
{
// TODO: This should be a multimap
util::map<uint64_t, j6_handle_t> services;
uint64_t tag;
uint16_t reply_tag;
uint8_t data[100];
size_t data_len = sizeof(data);
j6_handle_t handles[10];
size_t handles_count = sizeof(handles)/sizeof(j6_handle_t);
j6_status_t s = j6_mailbox_receive(mb, &tag,
data, &data_len,
handles, &handles_count,
&reply_tag, nullptr,
j6_mailbox_block);
uint64_t proto_id;
uint64_t *data_words = reinterpret_cast<uint64_t*>(data);
while (true) {
j6_handle_t *found = nullptr;
switch (tag) {
case j6_proto_base_get_proto_id:
tag = j6_proto_base_proto_id;
*data_words = j6_proto_sl_id;
data_len = sizeof(j6_status_t);
handles_count = 0;
break;
case j6_proto_sl_register:
proto_id = *data_words;
if (handles_count != 1) {
tag = j6_proto_base_status;
*data_words = j6_err_invalid_arg;
data_len = sizeof(j6_status_t);
handles_count = 0;
break;
}
services.insert( proto_id, handles[0] );
tag = j6_proto_base_status;
*data_words = j6_status_ok;
data_len = sizeof(j6_status_t);
handles_count = 0;
break;
case j6_proto_sl_find:
proto_id = *data_words;
tag = j6_proto_sl_result;
data_len = 0;
found = services.find(proto_id);
if (found) {
handles_count = 1;
handles[0] = *found;
} else {
handles_count = 0;
}
break;
default:
tag = j6_proto_base_status;
*data_words = j6_err_invalid_arg;
data_len = sizeof(j6_status_t);
handles_count = 0;
break;
}
size_t data_in = data_len;
size_t handles_in = handles_count;
data_len = sizeof(data);
handles_count = sizeof(handles)/sizeof(j6_handle_t);
s = j6_mailbox_respond_receive(mb, &tag,
data, &data_len, data_in,
handles, &handles_count, handles_in,
&reply_tag, nullptr,
j6_mailbox_block);
}
}

View File

@@ -0,0 +1,5 @@
#pragma once
/// \file service_locator.h
/// Definitions for srv.init's implementation of the service locator protocol
void service_locator_start(j6_handle_t mb);