Skip to content

Commit

Permalink
switch console to sync-only
Browse files Browse the repository at this point in the history
  • Loading branch information
ppannuto committed Sep 8, 2023
1 parent c7d8279 commit 76ae950
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 121 deletions.
126 changes: 11 additions & 115 deletions libtock/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}
5 changes: 0 additions & 5 deletions libtock/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 19 additions & 0 deletions libtock/tock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion libtock/tock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down

0 comments on commit 76ae950

Please sign in to comment.