diff --git a/libtock/console.c b/libtock/console.c index 7d69f21ec..878ea38e3 100644 --- a/libtock/console.c +++ b/libtock/console.c @@ -4,138 +4,39 @@ #include "console.h" -typedef struct putstr_data { - char* buf; - int len; - bool called; - struct putstr_data* next; -} putstr_data_t; - -static putstr_data_t *putstr_head = NULL; -static putstr_data_t *putstr_tail = NULL; - -static void putstr_upcall(int _x __attribute__ ((unused)), - int _y __attribute__ ((unused)), - int _z __attribute__ ((unused)), - void* ud __attribute__ ((unused))) { - putstr_data_t* data = putstr_head; - data->called = true; - putstr_head = data->next; - - if (putstr_head == NULL) { - putstr_tail = NULL; - } else { - int ret; - ret = putnstr_async(putstr_head->buf, putstr_head->len, putstr_upcall, NULL); - if (ret < 0) { - // XXX There's no path to report errors currently, so just drop it - putstr_upcall(0, 0, 0, NULL); - } - } -} - int putnstr(const char *str, size_t len) { int ret = RETURNCODE_SUCCESS; - putstr_data_t* data = (putstr_data_t*)malloc(sizeof(putstr_data_t)); - if (data == NULL) return RETURNCODE_ENOMEM; - - data->len = len; - data->called = false; - data->buf = (char*)malloc(len * sizeof(char)); - if (data->buf == NULL) { - ret = RETURNCODE_ENOMEM; - goto putnstr_fail_buf_alloc; - } - strncpy(data->buf, str, len); - data->next = NULL; - - if (putstr_tail == NULL) { - // Invariant, if tail is NULL, head is also NULL - ret = putnstr_async(data->buf, data->len, putstr_upcall, NULL); - if (ret < 0) goto putnstr_fail_async; - putstr_head = data; - putstr_tail = data; - } else { - putstr_tail->next = data; - putstr_tail = data; - } - - yield_for(&data->called); - -putnstr_fail_async: - free(data->buf); -putnstr_fail_buf_alloc: - free(data); - - return ret; -} - -int putnstr_async(const char *str, size_t len, subscribe_upcall cb, void* userdata) { -#pragma GCC diagnostic push -#pragma GCC diagnostic pop - allow_ro_return_t ro = allow_readonly(DRIVER_NUM_CONSOLE, 1, str, len); if (!ro.success) { return tock_status_to_returncode(ro.status); } - subscribe_return_t sub = subscribe(DRIVER_NUM_CONSOLE, 1, cb, userdata); - if (!sub.success) { - return tock_status_to_returncode(sub.status); - } - syscall_return_t com = command(DRIVER_NUM_CONSOLE, 1, len, 0); - return tock_command_return_novalue_to_returncode(com); -} - -int getnstr_async(char *buf, size_t len, subscribe_upcall cb, void* userdata) { - allow_rw_return_t rw = allow_readwrite(DRIVER_NUM_CONSOLE, 1, buf, len); - if (!rw.success) { - return tock_status_to_returncode(rw.status); - } - - subscribe_return_t sub = subscribe(DRIVER_NUM_CONSOLE, 2, cb, userdata); - if (!sub.success) { - return tock_status_to_returncode(sub.status); + ret = tock_command_return_novalue_to_returncode(com); + if (ret < 0) { + return ret; } - syscall_return_t com = command(DRIVER_NUM_CONSOLE, 2, len, 0); - return tock_command_return_novalue_to_returncode(com); + return yield_for_subscribable_upcall_returnr0_sync(DRIVER_NUM_CONSOLE, 2); } -typedef struct getnstr_data { - bool called; - int result; -} getnstr_data_t; - -static getnstr_data_t getnstr_data = { true, 0 }; -static void getnstr_upcall(int result, - int _y __attribute__ ((unused)), - int _z __attribute__ ((unused)), - void* ud __attribute__ ((unused))) { - getnstr_data.result = result; - getnstr_data.called = true; -} - -int getnstr(char *str, size_t len) { +int getnstr(char *buf, size_t len) { int ret; - if (!getnstr_data.called) { - // A call is already in progress - return RETURNCODE_EALREADY; + allow_rw_return_t rw = allow_readwrite(DRIVER_NUM_CONSOLE, 1, buf, len); + if (!rw.success) { + return tock_status_to_returncode(rw.status); } - getnstr_data.called = false; - ret = getnstr_async(str, len, getnstr_upcall, NULL); + syscall_return_t com = command(DRIVER_NUM_CONSOLE, 2, len, 0); + ret = tock_command_return_novalue_to_returncode(com); if (ret < 0) { return ret; } - yield_for(&getnstr_data.called); - - return getnstr_data.result; + return yield_for_subscribable_upcall_returnr0_sync(DRIVER_NUM_CONSOLE, 2); } int getch(void) { @@ -145,8 +46,3 @@ int getch(void) { r = getnstr(buf, 1); return (r == RETURNCODE_SUCCESS) ? buf[0] : RETURNCODE_FAIL; } - -int getnstr_abort(void) { - syscall_return_t com = command(DRIVER_NUM_CONSOLE, 3, 0, 0); - return tock_command_return_novalue_to_returncode(com); -} diff --git a/libtock/console.h b/libtock/console.h index 2f10866cf..b0390b69e 100644 --- a/libtock/console.h +++ b/libtock/console.h @@ -9,17 +9,12 @@ extern "C" { #define DRIVER_NUM_CONSOLE 0x1 int putnstr(const char* str, size_t len); -int putnstr_async(const char* str, size_t len, subscribe_upcall cb, void* userdata); int getnstr(char *str, size_t len); -int getnstr_async(char *str, size_t len, subscribe_upcall cb, void* userdata); /* Returns TOCK_FAIL on failure, or else the character received */ int getch(void); -// Abort an ongoing receive call. -int getnstr_abort(void); - #ifdef __cplusplus } #endif diff --git a/libtock/tock.c b/libtock/tock.c index 86a56f58f..551859557 100644 --- a/libtock/tock.c +++ b/libtock/tock.c @@ -193,6 +193,25 @@ int yield_no_wait(void) { } } +int yield_for_subscribable_upcall_returnr0_sync(uint32_t driver, uint32_t subscribe) { + register uint32_t wait __asm__ ("r0") = 2; // yield-waitfor-nocallback + register uint8_t* wait_field __asm__ ("r1") = NULL; // yield result ptr + register uint32_t r2 __asm__ ("r2") = driver; + register uint32_t r3 __asm__ ("r3") = subscribe; + register int rv0 __asm__ ("r0"); + register int rv1 __asm__ ("r1"); + register int rv2 __asm__ ("r2"); + + __asm__ volatile ( + "svc 0 \n" + : "=r" (rv0), "=r" (rv1), "=r" (rv2) + : "r" (wait), "r" (wait_field), "r" (r2), "r" (r3) + : "memory" + ); + return rv0; +} + + void tock_exit(uint32_t completion_code) { register uint32_t r0 __asm__ ("r0") = 0; // Terminate register uint32_t r1 __asm__ ("r1") = completion_code; diff --git a/libtock/tock.h b/libtock/tock.h index bb5ce0500..73813fff0 100644 --- a/libtock/tock.h +++ b/libtock/tock.h @@ -164,9 +164,10 @@ int tock_allow_ro_return_to_returncode(allow_ro_return_t); int tock_enqueue(subscribe_upcall cb, int arg0, int arg1, int arg2, void* ud); int yield_check_tasks(void); +int yield_no_wait(void); void yield(void); void yield_for(bool*); -int yield_no_wait(void); +int yield_for_subscribable_upcall_returnr0_sync(uint32_t driver, uint32_t subscribe); void tock_exit(uint32_t completion_code) __attribute__ ((noreturn)); void tock_restart(uint32_t completion_code) __attribute__ ((noreturn));