Added arbitrary length terminal write and read with early return
This commit is contained in:
parent
f22a6fa5a0
commit
12ee3bb5b6
@ -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,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
|
* \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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user