Added: Terminal RPC, Spawn RPC, small abstraction fixes, automatic recv slot allocation in aos_rpc
This commit is contained in:
parent
14063e60be
commit
9750a752c3
@ -1380,6 +1380,7 @@ errors aos AOS_ERR_ {
|
||||
failure RPC_ARG_TOO_BIG "RPC argument is too big",
|
||||
failure RPC_RET_TOO_BIG "RPC return value is too big",
|
||||
failure RPC_UNKNOWN_MSG_TYPE "RPC with unknown message type",
|
||||
failure RPC_PROCESS_UNKNOWN_PID "Requested process name for an unknown PID",
|
||||
};
|
||||
|
||||
// errors NIC driver
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
bootdriver /armv8/sbin/boot_armv8_generic
|
||||
cpudriver /armv8/sbin/cpu_a57_qemu loglevel=3 serial=0x9000000 logmask=128
|
||||
module /armv8/sbin/init
|
||||
module /armv8/sbin/hello Aurel Jan Sandro
|
||||
module /armv8/sbin/hello spawn
|
||||
module /armv8/sbin/memeater
|
||||
|
||||
# End of file, this needs to have a certain length...
|
||||
|
||||
@ -27,6 +27,7 @@ enum rpc_mtype {
|
||||
RPC_MTYPE_GET_RAM_CAP,
|
||||
RPC_MTYPE_SERIAL_GETCHAR,
|
||||
RPC_MTYPE_SERIAL_PUTCHAR,
|
||||
RPC_MTYPE_SERIAL_WRITE,
|
||||
RPC_MTYPE_PROCESS_SPAWN,
|
||||
RPC_MTYPE_PROCESS_GET_NAME,
|
||||
RPC_MTYPE_PROCESS_GET_ALL_PIDS,
|
||||
@ -78,6 +79,12 @@ errval_t aos_rpc_serial_getchar(struct aos_rpc *chan, char *retc);
|
||||
*/
|
||||
errval_t aos_rpc_serial_putchar(struct aos_rpc *chan, char c);
|
||||
|
||||
/**
|
||||
* \brief Send a list of characters to the serial port
|
||||
*/
|
||||
errval_t aos_rpc_serial_write(struct aos_rpc *chan, const char *buf,
|
||||
size_t buf_len);
|
||||
|
||||
/**
|
||||
* \brief Request that the process manager start a new process
|
||||
* \arg cmdline the name of the process that needs to be spawned (without a
|
||||
|
||||
@ -63,6 +63,11 @@ struct spawninfo {
|
||||
struct aos_rpc_server rpc_server;
|
||||
};
|
||||
|
||||
struct spawninfo *sawn_get_process_list(void);
|
||||
|
||||
// parse a commandline into arguments
|
||||
void spawn_parse_cmd(char *cmdline, int *argc, char **argv);
|
||||
|
||||
// Start a child process using the multiboot command line. Fills in si.
|
||||
errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si,
|
||||
domainid_t *pid);
|
||||
|
||||
@ -27,6 +27,11 @@ static errval_t do_aos_rpc(
|
||||
) {
|
||||
errval_t err;
|
||||
|
||||
// allocate capability if we expect one and the recv slot is empty
|
||||
if (ret_cap != NULL && rpc->chan->endpoint->k.recv_cptr == 0){
|
||||
lmp_chan_alloc_recv_slot(rpc->chan);
|
||||
}
|
||||
|
||||
// Send call
|
||||
while (true) {
|
||||
err = lmp_chan_send4(rpc->chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, arg_cap, msg_type, arg_size, arg0, arg1);
|
||||
@ -121,6 +126,36 @@ aos_rpc_serial_putchar(struct aos_rpc *rpc, char c) {
|
||||
);
|
||||
}
|
||||
|
||||
// putchar for terminal printing is too slow so we send buffers instead
|
||||
errval_t
|
||||
aos_rpc_serial_write(struct aos_rpc *rpc, const char *buf, size_t buf_len) {
|
||||
errval_t err;
|
||||
|
||||
// split the buffer into chunks for sending
|
||||
while(buf_len > 0) {
|
||||
size_t chunk_len = buf_len;
|
||||
if (chunk_len > RPC_SHARED_SIZE) {
|
||||
chunk_len = RPC_SHARED_SIZE;
|
||||
}
|
||||
|
||||
memcpy(rpc->shared_mem, buf, chunk_len);
|
||||
|
||||
err = do_aos_rpc(
|
||||
rpc, RPC_MTYPE_SERIAL_WRITE,
|
||||
NULL_CAP, chunk_len, 0, 0,
|
||||
NULL, NULL, NULL, NULL
|
||||
);
|
||||
if (err_is_fail(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
buf += chunk_len;
|
||||
buf_len -= chunk_len;
|
||||
}
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
errval_t
|
||||
aos_rpc_process_spawn(struct aos_rpc *rpc, char *cmdline,
|
||||
coreid_t core, domainid_t *newpid) {
|
||||
@ -153,7 +188,8 @@ aos_rpc_process_get_name(struct aos_rpc *rpc, domainid_t pid, char **name) {
|
||||
if (err_is_fail(err)) return err;
|
||||
*name = malloc(name_len);
|
||||
if (*name == NULL) return LIB_ERR_MALLOC_FAIL;
|
||||
memcpy(name, rpc->shared_mem, name_len);
|
||||
memcpy(*name, rpc->shared_mem, name_len);
|
||||
assert((*name)[name_len] == '\0');
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -164,7 +200,7 @@ aos_rpc_process_get_all_pids(struct aos_rpc *rpc, domainid_t **pids,
|
||||
// (M5): implement process id discovery
|
||||
size_t ret_len;
|
||||
errval_t err = do_aos_rpc(
|
||||
rpc, RPC_MTYPE_PROCESS_GET_NAME,
|
||||
rpc, RPC_MTYPE_PROCESS_GET_ALL_PIDS,
|
||||
NULL_CAP, 0, 0, 0,
|
||||
NULL, &ret_len, NULL, NULL
|
||||
);
|
||||
@ -172,7 +208,7 @@ aos_rpc_process_get_all_pids(struct aos_rpc *rpc, domainid_t **pids,
|
||||
*pid_count = ret_len / sizeof(**pids);
|
||||
*pids = malloc(ret_len);
|
||||
if (*pids == NULL) return LIB_ERR_MALLOC_FAIL;
|
||||
memcpy(pids, rpc->shared_mem, ret_len);
|
||||
memcpy(*pids, rpc->shared_mem, ret_len);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -100,9 +100,8 @@ static void handle_init_recv(void *arg)
|
||||
struct lmp_chan *init_chan = (struct lmp_chan *)arg;
|
||||
|
||||
struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
|
||||
struct capref cap;
|
||||
|
||||
err = lmp_chan_recv(init_chan, &msg, &cap);
|
||||
err = lmp_chan_recv(init_chan, &msg, NULL);
|
||||
assert(err_is_ok(err));
|
||||
|
||||
if (msg.words[0] == SYS_ERR_OK) {
|
||||
@ -113,6 +112,32 @@ static void handle_init_recv(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO rueegges: allow partial write
|
||||
static size_t aos_terminal_write(const char *buf, size_t len)
|
||||
{
|
||||
errval_t err;
|
||||
struct aos_rpc *rpc = aos_rpc_get_serial_channel();
|
||||
if (rpc == NULL) {
|
||||
debug_printf("Attempted to printf before initializing rpc: %.*s\n", len, buf);
|
||||
USER_PANIC("Make sure to initialize rpc before function barrelfish_libc_glue_init is called.");
|
||||
return len;
|
||||
}
|
||||
|
||||
err = aos_rpc_serial_write(rpc, buf, len);
|
||||
assert(err_is_ok(err));
|
||||
return len;
|
||||
}
|
||||
|
||||
// TODO rueegges: make more efficient?
|
||||
static size_t aos_terminal_read(char *buf, size_t len)
|
||||
{
|
||||
errval_t err;
|
||||
struct aos_rpc *rpc = aos_rpc_get_serial_channel();
|
||||
err = aos_rpc_serial_getchar(rpc, buf);
|
||||
assert(err_is_ok(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set libc function pointers */
|
||||
void barrelfish_libc_glue_init(void)
|
||||
{
|
||||
@ -120,8 +145,14 @@ void barrelfish_libc_glue_init(void)
|
||||
// what we need for that
|
||||
// TODO: change these to use the user-space serial driver if possible
|
||||
// TODO: set these functions
|
||||
// MARKER SHELL: replace functions for init domain or UART driver with non-remote calls
|
||||
if(init_domain) {
|
||||
_libc_terminal_read_func = dummy_terminal_read;
|
||||
_libc_terminal_write_func = syscall_terminal_write;
|
||||
} else {
|
||||
_libc_terminal_read_func = aos_terminal_read;
|
||||
_libc_terminal_write_func = aos_terminal_write;
|
||||
}
|
||||
_libc_exit_func = libc_exit;
|
||||
_libc_assert_func = libc_assert;
|
||||
/* morecore func is setup by morecore_init() */
|
||||
|
||||
@ -16,19 +16,19 @@ void do_test_spawn(void) {
|
||||
}
|
||||
|
||||
// wait for 10 seconds but handle events in the mean time
|
||||
struct waitset *default_ws = get_default_waitset();
|
||||
struct timespec tt;
|
||||
clock_gettime(CLOCK_REALTIME, &tt);
|
||||
long start = time_to_ms(tt);
|
||||
do {
|
||||
if(err_is_ok(check_for_event(default_ws))){
|
||||
CHECK_ERR(event_dispatch(default_ws));
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &tt);
|
||||
} while(time_to_ms(tt) - start < 10000);
|
||||
// struct waitset *default_ws = get_default_waitset();
|
||||
// struct timespec tt;
|
||||
// clock_gettime(CLOCK_REALTIME, &tt);
|
||||
// long start = time_to_ms(tt);
|
||||
// do {
|
||||
// if(err_is_ok(check_for_event(default_ws))){
|
||||
// CHECK_ERR(event_dispatch(default_ws));
|
||||
// }
|
||||
// clock_gettime(CLOCK_REALTIME, &tt);
|
||||
// } while(time_to_ms(tt) - start < 10000);
|
||||
|
||||
for(uint i = 0; i < PROCESS_COUNT; ++i) {
|
||||
debug_printf("TEST_SPAWN: Killing %u\n", i);
|
||||
CHECK_ERR(invoke_dispatcher_stop(si[i].dispatcher));
|
||||
}
|
||||
// for(uint i = 0; i < PROCESS_COUNT; ++i) {
|
||||
// debug_printf("TEST_SPAWN: Killing %u\n", i);
|
||||
// CHECK_ERR(invoke_dispatcher_stop(si[i].dispatcher));
|
||||
// }
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <aos/aos_rpc.h>
|
||||
#include <spawn/rpc_server.h>
|
||||
#include <grading.h>
|
||||
#include <spawn/spawn.h>
|
||||
|
||||
typedef errval_t (*rpc_handler_t)(
|
||||
struct aos_rpc_server *rpc,
|
||||
@ -139,8 +140,8 @@ static errval_t handle_rpc_serial_getchar(
|
||||
|
||||
grading_rpc_handler_serial_getchar();
|
||||
|
||||
// TODO
|
||||
*ret0 = 'A';
|
||||
// MARKER SHELL: Replace with UART call
|
||||
*ret0 = getchar();
|
||||
|
||||
return LIB_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@ -154,9 +155,27 @@ static errval_t handle_rpc_serial_putchar(
|
||||
|
||||
grading_rpc_handler_serial_putchar(c);
|
||||
|
||||
// TODO
|
||||
// MARKER SHELL: Replace with UART call
|
||||
putchar(c);
|
||||
|
||||
return LIB_ERR_NOT_IMPLEMENTED;
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
static errval_t handle_rpc_serial_write(
|
||||
struct aos_rpc_server *rpc,
|
||||
struct capref arg_cap, size_t arg_size, uintptr_t arg0, uintptr_t arg1,
|
||||
struct capref *ret_cap, size_t *ret_size, uintptr_t *ret0, uintptr_t *ret1
|
||||
) {
|
||||
if (arg_size == 0 ) {
|
||||
return ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
// MARKER SHELL: Replace with UART call
|
||||
for (size_t i = 0; i < arg_size; ++i){
|
||||
putchar(((char *)rpc->shared_mem)[i]);
|
||||
}
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
static errval_t handle_rpc_process_spawn(
|
||||
@ -172,10 +191,13 @@ static errval_t handle_rpc_process_spawn(
|
||||
|
||||
grading_rpc_handler_process_spawn(cmdline, core);
|
||||
|
||||
// TODO
|
||||
*ret0 = 0;
|
||||
struct spawninfo *si = malloc(sizeof(struct spawninfo));
|
||||
|
||||
return LIB_ERR_NOT_IMPLEMENTED;
|
||||
char *argv[MAX_CMDLINE_ARGS];
|
||||
int argc;
|
||||
spawn_parse_cmd(cmdline, &argc, argv);
|
||||
|
||||
return spawn_load_argv(argc, argv, si, (domainid_t *)ret0);
|
||||
}
|
||||
|
||||
static errval_t handle_rpc_process_get_name(
|
||||
@ -187,11 +209,28 @@ static errval_t handle_rpc_process_get_name(
|
||||
|
||||
grading_rpc_handler_process_get_name(pid);
|
||||
|
||||
// TODO
|
||||
memcpy(rpc->shared_mem, "name", 5);
|
||||
*ret_size = 5;
|
||||
// search for the pid
|
||||
char *name = NULL;
|
||||
for (struct spawninfo *si = sawn_get_process_list(); si != NULL; si = si->next) {
|
||||
if (si->pid == pid) {
|
||||
name = si->binary_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return LIB_ERR_NOT_IMPLEMENTED;
|
||||
if (name == NULL) {
|
||||
return AOS_ERR_RPC_PROCESS_UNKNOWN_PID;
|
||||
}
|
||||
|
||||
size_t name_len = strlen(name) + 1;
|
||||
if(name_len > RPC_SHARED_SIZE) {
|
||||
return AOS_ERR_RPC_RET_TOO_BIG;
|
||||
}
|
||||
|
||||
memcpy(rpc->shared_mem, name, name_len);
|
||||
*ret_size = name_len;
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
static errval_t handle_rpc_process_get_all_pids(
|
||||
@ -201,9 +240,24 @@ static errval_t handle_rpc_process_get_all_pids(
|
||||
) {
|
||||
grading_rpc_handler_process_get_all_pids();
|
||||
|
||||
// TODO
|
||||
// size in bytes
|
||||
size_t list_size = 0;
|
||||
domainid_t *buf = rpc->shared_mem;
|
||||
|
||||
return LIB_ERR_NOT_IMPLEMENTED;
|
||||
// get all PIDs that fit into the given space
|
||||
for (struct spawninfo *si = sawn_get_process_list(); si != NULL; si = si->next) {
|
||||
if (list_size + sizeof(domainid_t) > RPC_SHARED_SIZE) {
|
||||
return AOS_ERR_RPC_RET_TOO_BIG;
|
||||
}
|
||||
|
||||
*buf = si->pid;
|
||||
++buf;
|
||||
list_size += sizeof(domainid_t);
|
||||
}
|
||||
|
||||
*ret_size = list_size;
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -213,6 +267,7 @@ static rpc_handler_t rpc_handlers[RPC_MTYPE_COUNT] = {
|
||||
[RPC_MTYPE_GET_RAM_CAP] = handle_rpc_get_ram_cap,
|
||||
[RPC_MTYPE_SERIAL_GETCHAR] = handle_rpc_serial_getchar,
|
||||
[RPC_MTYPE_SERIAL_PUTCHAR] = handle_rpc_serial_putchar,
|
||||
[RPC_MTYPE_SERIAL_WRITE] = handle_rpc_serial_write,
|
||||
[RPC_MTYPE_PROCESS_SPAWN] = handle_rpc_process_spawn,
|
||||
[RPC_MTYPE_PROCESS_GET_NAME] = handle_rpc_process_get_name,
|
||||
[RPC_MTYPE_PROCESS_GET_ALL_PIDS] = handle_rpc_process_get_all_pids,
|
||||
|
||||
@ -20,7 +20,9 @@ struct spawninfo *spawn_process_list = NULL;
|
||||
// TODO: handle "freeing" of PIDs in case we learn how to detect stopped child processes
|
||||
domainid_t spawn_last_pid = 1;
|
||||
|
||||
|
||||
struct spawninfo *sawn_get_process_list(void) {
|
||||
return spawn_process_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the base address of the .got (Global Offset Table) section of the ELF binary
|
||||
@ -334,6 +336,13 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
|
||||
// - Initialize the spawn_info struct
|
||||
// TODO
|
||||
// copy name to spawninfo struct
|
||||
size_t binary_name_len = strlen(argv[0]);
|
||||
si->binary_name = malloc(binary_name_len);
|
||||
if (si->binary_name == NULL) {
|
||||
return LIB_ERR_MALLOC_FAIL;
|
||||
}
|
||||
memcpy(si->binary_name, argv[0], binary_name_len);
|
||||
|
||||
// - Get the module from the multiboot image
|
||||
// and map it (take a look at multiboot.c)
|
||||
@ -633,9 +642,23 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
si->pid = ++spawn_last_pid;
|
||||
*pid = si->pid;
|
||||
|
||||
// add to process list
|
||||
si->next = spawn_process_list;
|
||||
spawn_process_list = si;
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
void spawn_parse_cmd(char *cmdline, int *argc, char **argv){
|
||||
*argc = 0;
|
||||
char *token = strtok(cmdline, " ");
|
||||
while (token != NULL) {
|
||||
argv[*argc] = token;
|
||||
token = strtok(NULL, " ");
|
||||
*argc += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (M2): Implement this function.
|
||||
* \brief Spawn a new dispatcher executing 'binary_name'
|
||||
@ -665,22 +688,13 @@ errval_t spawn_load_by_name(char *binary_name, struct spawninfo * si,
|
||||
// printf("raw_arguments_str: %s\n", raw_arguments_str);
|
||||
|
||||
// afeer: explode the raw_arguments_str into argv
|
||||
char * argv[MAX_CMDLINE_ARGS];
|
||||
int argc = 0;
|
||||
char * token = strtok(raw_arguments_str, " ");
|
||||
while (token != NULL) {
|
||||
argv[argc] = token;
|
||||
token = strtok(NULL, " ");
|
||||
argc += 1;
|
||||
}
|
||||
char *argv[MAX_CMDLINE_ARGS];
|
||||
int argc;
|
||||
spawn_parse_cmd(raw_arguments_str, &argc, argv);
|
||||
|
||||
// - Call spawn_load_argv
|
||||
err = spawn_load_argv(argc, argv, si, pid);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// add to process list
|
||||
si->next = spawn_process_list;
|
||||
spawn_process_list = si;
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <aos/deferred.h>
|
||||
|
||||
#define HELLO_CATCH_COMMAND "catch"
|
||||
#define HELLO_SPAWN_COMMAND "spawn"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -40,6 +41,32 @@ int main(int argc, char *argv[])
|
||||
err = aos_rpc_send_string(rpc, "Hello World via RPC!");
|
||||
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to send RPC");
|
||||
|
||||
// try to spawn a child using rpc
|
||||
if (argc > 1 && !strncmp(argv[1], HELLO_SPAWN_COMMAND, sizeof(HELLO_SPAWN_COMMAND))) {
|
||||
// start process
|
||||
domainid_t pid;
|
||||
rpc = aos_rpc_get_process_channel();
|
||||
err = aos_rpc_process_spawn(rpc, "hello Aurel Jan Sandro", 0, &pid);
|
||||
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to spawn process");
|
||||
printf("Started a new process!\n");
|
||||
|
||||
// get process name
|
||||
char *name;
|
||||
err = aos_rpc_process_get_name(rpc, pid, &name);
|
||||
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to get process name");
|
||||
printf("Process Name: %s\n", name);
|
||||
|
||||
// get all PIDs
|
||||
domainid_t *pids;
|
||||
size_t pid_count;
|
||||
err = aos_rpc_process_get_all_pids(rpc, &pids, &pid_count);
|
||||
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to get all PIDs");
|
||||
printf("PIDs:\n");
|
||||
for(size_t i = 0; i < pid_count; ++i) {
|
||||
printf(" %lu\n", pids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// if we receive the catch command, RUN!
|
||||
if (argc > 1 && !strncmp(argv[1], HELLO_CATCH_COMMAND, sizeof(HELLO_CATCH_COMMAND))) {
|
||||
int iter = 0;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user