From 12ee3bb5b6df8420045a441212dd5466cee24880 Mon Sep 17 00:00:00 2001 From: Sparchatus Date: Thu, 31 Mar 2022 13:12:33 +0000 Subject: [PATCH] Added arbitrary length terminal write and read with early return --- include/aos/aos_rpc.h | 12 +++++++-- lib/aos/aos_rpc.c | 61 +++++++++++++++++++++++++++++++++++------- lib/aos/init.c | 38 +++++++++----------------- lib/spawn/rpc_server.c | 24 ++++++++++++++--- 4 files changed, 95 insertions(+), 40 deletions(-) diff --git a/include/aos/aos_rpc.h b/include/aos/aos_rpc.h index eb7dc64..ec74ca4 100644 --- a/include/aos/aos_rpc.h +++ b/include/aos/aos_rpc.h @@ -28,6 +28,7 @@ enum rpc_mtype { RPC_MTYPE_SERIAL_GETCHAR, RPC_MTYPE_SERIAL_PUTCHAR, RPC_MTYPE_SERIAL_WRITE, + RPC_MTYPE_SERIAL_READ, RPC_MTYPE_PROCESS_SPAWN, RPC_MTYPE_PROCESS_GET_NAME, RPC_MTYPE_PROCESS_GET_ALL_PIDS, @@ -82,8 +83,15 @@ 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); +size_t aos_rpc_serial_write(struct aos_rpc *chan, const char *buf, + size_t buf_len); + +/** + * \brief Read a list of characters from the serial port + */ +size_t aos_rpc_serial_read(struct aos_rpc *rpc, char *buf, + size_t buf_len); + /** * \brief Request that the process manager start a new process diff --git a/lib/aos/aos_rpc.c b/lib/aos/aos_rpc.c index 652ec1e..7c3d9cf 100644 --- a/lib/aos/aos_rpc.c +++ b/lib/aos/aos_rpc.c @@ -126,34 +126,77 @@ aos_rpc_serial_putchar(struct aos_rpc *rpc, char c) { ); } -// putchar for terminal printing is too slow so we send buffers instead -errval_t +// putchar for terminal printing is too slow so we write buffers instead +// the corresponding interface does not know about errors, just partial writes +size_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 + size_t total_bytes = 0; while(buf_len > 0) { - size_t chunk_len = buf_len; - if (chunk_len > RPC_SHARED_SIZE) { - chunk_len = RPC_SHARED_SIZE; - } + size_t chunk_len = MIN(buf_len, RPC_SHARED_SIZE); memcpy(rpc->shared_mem, buf, chunk_len); + size_t written_bytes; err = do_aos_rpc( rpc, RPC_MTYPE_SERIAL_WRITE, NULL_CAP, chunk_len, 0, 0, - NULL, NULL, NULL, NULL + NULL, NULL, &written_bytes, NULL ); if (err_is_fail(err)) { - return err; + return total_bytes; + } + + total_bytes += written_bytes; + + // if the receiver was not able to write all we have given, return for now + if (written_bytes < chunk_len) { + return total_bytes; } buf += chunk_len; buf_len -= chunk_len; } - return SYS_ERR_OK; + return total_bytes; +} + +// getchar for terminal reading is too slow so we read buffers instead +// the corresponding interface does not know about errors, just partial reads +size_t +aos_rpc_serial_read(struct aos_rpc *rpc, char *buf, size_t buf_len) { + errval_t err; + + // split the buffer into chunks for reading + size_t total_bytes = 0; + while(buf_len > 0) { + size_t chunk_len = MIN(buf_len, RPC_SHARED_SIZE); + + size_t read_bytes; + err = do_aos_rpc( + rpc, RPC_MTYPE_SERIAL_WRITE, + NULL_CAP, 0, chunk_len, 0, + NULL, NULL, &read_bytes, NULL + ); + if (err_is_fail(err)) { + return total_bytes; + } + + memcpy(buf, rpc->shared_mem, read_bytes); + total_bytes += read_bytes; + + // if the receiver was not able to write all we have given, return for now + if (read_bytes < chunk_len) { + return total_bytes; + } + + buf += chunk_len; + buf_len -= chunk_len; + } + + return total_bytes; } errval_t diff --git a/lib/aos/init.c b/lib/aos/init.c index 2cc90fa..8ad7240 100644 --- a/lib/aos/init.c +++ b/lib/aos/init.c @@ -83,17 +83,6 @@ static size_t dummy_terminal_read(char *buf, size_t len) return 0; } -static int event_init_dispatch_thread(void *arg) -{ - errval_t err; - while(true) { - err = event_dispatch(get_default_waitset()); - if (err_is_fail(err)) { - USER_PANIC_ERR(err_push(err, LIB_ERR_EVENT_DISPATCH), "Failed to dispatch events"); - } - } -} - static void handle_init_recv(void *arg) { errval_t err; @@ -115,27 +104,29 @@ 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; + if(len == 0) return 0; + 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; + debug_printf("[aos_terminal_write] RPC NOT YET INITIALIZED: %.*s\n", len, buf); + USER_PANIC("Make sure to initialize aos_rpc before barrelfish_libc_glue_init is called."); } - err = aos_rpc_serial_write(rpc, buf, len); - assert(err_is_ok(err)); - return len; + return aos_rpc_serial_write(rpc, buf, len); } // TODO rueegges: make more efficient? static size_t aos_terminal_read(char *buf, size_t len) { - errval_t err; + if(len == 0) return 0; + struct aos_rpc *rpc = aos_rpc_get_serial_channel(); - err = aos_rpc_serial_getchar(rpc, buf); - assert(err_is_ok(err)); - return 1; + if (rpc == NULL) { + debug_printf("[aos_terminal_read] RPC NOT YET INITIALIZED: %.*s\n", len, buf); + USER_PANIC("Make sure to initialize aos_rpc before barrelfish_libc_glue_init is called."); + } + + return aos_rpc_serial_read(rpc, buf, len); } /* Set libc function pointers */ @@ -250,9 +241,6 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params) /* set init RPC client in our program state */ set_init_rpc(init_rpc); - // create thread to dispatch events - thread_create(event_init_dispatch_thread, NULL); - /* TODO MILESTONE 3: now we should have a channel with init set up and can * use it for the ram allocator */ diff --git a/lib/spawn/rpc_server.c b/lib/spawn/rpc_server.c index c88ac4a..6cb5e58 100644 --- a/lib/spawn/rpc_server.c +++ b/lib/spawn/rpc_server.c @@ -166,15 +166,30 @@ static errval_t handle_rpc_serial_write( 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 the number of characters written. Important for UART for early return when the buffer is full + *ret0 = arg_size; + + return SYS_ERR_OK; +} + +static errval_t handle_rpc_serial_read( + 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 +) { + // MARKER SHELL: Replace with UART call + for (size_t i = 0; i < arg_size; ++i){ + ((char *)rpc->shared_mem)[i] = getchar(); + } + + // return the number of characters read. Important for UART for early return when the buffer is empty + *ret0 = arg_size; + return SYS_ERR_OK; } @@ -268,6 +283,7 @@ static rpc_handler_t rpc_handlers[RPC_MTYPE_COUNT] = { [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_SERIAL_READ] = handle_rpc_serial_read, [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,