Added arbitrary length terminal write and read with early return

This commit is contained in:
Sparchatus 2022-03-31 13:12:33 +00:00
parent f22a6fa5a0
commit 12ee3bb5b6
4 changed files with 95 additions and 40 deletions

View File

@ -28,6 +28,7 @@ enum rpc_mtype {
RPC_MTYPE_SERIAL_GETCHAR, RPC_MTYPE_SERIAL_GETCHAR,
RPC_MTYPE_SERIAL_PUTCHAR, RPC_MTYPE_SERIAL_PUTCHAR,
RPC_MTYPE_SERIAL_WRITE, RPC_MTYPE_SERIAL_WRITE,
RPC_MTYPE_SERIAL_READ,
RPC_MTYPE_PROCESS_SPAWN, RPC_MTYPE_PROCESS_SPAWN,
RPC_MTYPE_PROCESS_GET_NAME, RPC_MTYPE_PROCESS_GET_NAME,
RPC_MTYPE_PROCESS_GET_ALL_PIDS, RPC_MTYPE_PROCESS_GET_ALL_PIDS,
@ -82,9 +83,16 @@ errval_t aos_rpc_serial_putchar(struct aos_rpc *chan, char c);
/** /**
* \brief Send a list of characters to the serial port * \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 aos_rpc_serial_write(struct aos_rpc *chan, const char *buf,
size_t buf_len); 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 * \brief Request that the process manager start a new process
* \arg cmdline the name of the process that needs to be spawned (without a * \arg cmdline the name of the process that needs to be spawned (without a

View File

@ -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 // putchar for terminal printing is too slow so we write buffers instead
errval_t // 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) { aos_rpc_serial_write(struct aos_rpc *rpc, const char *buf, size_t buf_len) {
errval_t err; errval_t err;
// split the buffer into chunks for sending // split the buffer into chunks for sending
size_t total_bytes = 0;
while(buf_len > 0) { while(buf_len > 0) {
size_t chunk_len = buf_len; size_t chunk_len = MIN(buf_len, RPC_SHARED_SIZE);
if (chunk_len > RPC_SHARED_SIZE) {
chunk_len = RPC_SHARED_SIZE;
}
memcpy(rpc->shared_mem, buf, chunk_len); memcpy(rpc->shared_mem, buf, chunk_len);
size_t written_bytes;
err = do_aos_rpc( err = do_aos_rpc(
rpc, RPC_MTYPE_SERIAL_WRITE, rpc, RPC_MTYPE_SERIAL_WRITE,
NULL_CAP, chunk_len, 0, 0, NULL_CAP, chunk_len, 0, 0,
NULL, NULL, NULL, NULL NULL, NULL, &written_bytes, NULL
); );
if (err_is_fail(err)) { 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 += chunk_len;
buf_len -= 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 errval_t

View File

@ -83,17 +83,6 @@ static size_t dummy_terminal_read(char *buf, size_t len)
return 0; 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) static void handle_init_recv(void *arg)
{ {
errval_t err; errval_t err;
@ -115,27 +104,29 @@ static void handle_init_recv(void *arg)
// TODO rueegges: allow partial write // TODO rueegges: allow partial write
static size_t aos_terminal_write(const char *buf, size_t len) 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(); struct aos_rpc *rpc = aos_rpc_get_serial_channel();
if (rpc == NULL) { if (rpc == NULL) {
debug_printf("Attempted to printf before initializing rpc: %.*s\n", len, buf); debug_printf("[aos_terminal_write] RPC NOT YET INITIALIZED: %.*s\n", len, buf);
USER_PANIC("Make sure to initialize rpc before function barrelfish_libc_glue_init is called."); USER_PANIC("Make sure to initialize aos_rpc before barrelfish_libc_glue_init is called.");
return len;
} }
err = aos_rpc_serial_write(rpc, buf, len); return aos_rpc_serial_write(rpc, buf, len);
assert(err_is_ok(err));
return len;
} }
// TODO rueegges: make more efficient? // TODO rueegges: make more efficient?
static size_t aos_terminal_read(char *buf, size_t len) 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(); struct aos_rpc *rpc = aos_rpc_get_serial_channel();
err = aos_rpc_serial_getchar(rpc, buf); if (rpc == NULL) {
assert(err_is_ok(err)); debug_printf("[aos_terminal_read] RPC NOT YET INITIALIZED: %.*s\n", len, buf);
return 1; 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 */ /* 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 client in our program state */
set_init_rpc(init_rpc); 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 /* TODO MILESTONE 3: now we should have a channel with init set up and can
* use it for the ram allocator */ * use it for the ram allocator */

View File

@ -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 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 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 // MARKER SHELL: Replace with UART call
for (size_t i = 0; i < arg_size; ++i){ for (size_t i = 0; i < arg_size; ++i){
putchar(((char *)rpc->shared_mem)[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; 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_GETCHAR] = handle_rpc_serial_getchar,
[RPC_MTYPE_SERIAL_PUTCHAR] = handle_rpc_serial_putchar, [RPC_MTYPE_SERIAL_PUTCHAR] = handle_rpc_serial_putchar,
[RPC_MTYPE_SERIAL_WRITE] = handle_rpc_serial_write, [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_SPAWN] = handle_rpc_process_spawn,
[RPC_MTYPE_PROCESS_GET_NAME] = handle_rpc_process_get_name, [RPC_MTYPE_PROCESS_GET_NAME] = handle_rpc_process_get_name,
[RPC_MTYPE_PROCESS_GET_ALL_PIDS] = handle_rpc_process_get_all_pids, [RPC_MTYPE_PROCESS_GET_ALL_PIDS] = handle_rpc_process_get_all_pids,