Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PoC]: Yield-WaitFor-NoCallback #345

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions libtock-sync/interface/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ returncode_t libtocksync_console_write(const uint8_t* buffer, uint32_t length, i
if (err != RETURNCODE_SUCCESS) return err;

// Wait for the callback.
yield_for(&result.fired);
if (result.result != RETURNCODE_SUCCESS) return result.result;
yield_waitfor_return_t yval = yield_wait_for(DRIVER_NUM_CONSOLE, 1);
if (yval.data0 != RETURNCODE_SUCCESS) return yval.data0;

*written = result.length;
*written = yval.data1;
return RETURNCODE_SUCCESS;
}

Expand Down
21 changes: 8 additions & 13 deletions libtock-sync/services/alarm.c
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
#include "alarm.h"

// Declare non-public export of helper from libtock.
uint32_t _ms_to_ticks(uint32_t ms);

struct alarm_cb_data {
bool fired;
};

static struct alarm_cb_data delay_data = { .fired = false };

static void delay_cb(__attribute__ ((unused)) uint32_t now,
__attribute__ ((unused)) uint32_t scheduled,
__attribute__ ((unused)) void* opaque) {
delay_data.fired = true;
}

int libtocksync_alarm_delay_ms(uint32_t ms) {
delay_data.fired = false;
libtock_alarm_t alarm;
int rc;

if ((rc = libtock_alarm_in_ms(ms, delay_cb, NULL, &alarm)) != RETURNCODE_SUCCESS) {
uint32_t ticks = _ms_to_ticks(ms);
if ((rc = libtock_alarm_command_set_relative_blind(ticks)) != RETURNCODE_SUCCESS) {
return rc;
}

yield_for(&delay_data.fired);
yield_waitfor_return_t yval = yield_wait_for(DRIVER_NUM_ALARM, 1);
if (yval.data0 != RETURNCODE_SUCCESS) return yval.data0;

return rc;
}

Expand Down
1 change: 1 addition & 0 deletions libtock-sync/services/alarm.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <libtock/peripherals/syscalls/alarm_syscalls.h>
#include <libtock/services/alarm.h>
#include <libtock/tock.h>

Expand Down
5 changes: 5 additions & 0 deletions libtock/peripherals/syscalls/alarm_syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ int libtock_alarm_command_set_relative(uint32_t dt, uint32_t* actual) {
return tock_command_return_u32_to_returncode(rval, actual);
}

int libtock_alarm_command_set_relative_blind(uint32_t dt) {
syscall_return_t rval = command(DRIVER_NUM_ALARM, 5, dt, 0);
return tock_command_return_novalue_to_returncode(rval);
}

int libtock_alarm_command_set_absolute(uint32_t reference, uint32_t dt) {
syscall_return_t rval = command(DRIVER_NUM_ALARM, 6, reference, dt);
uint32_t unused;
Expand Down
9 changes: 9 additions & 0 deletions libtock/peripherals/syscalls/alarm_syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ int libtock_alarm_command_stop(void);
*/
int libtock_alarm_command_set_relative(uint32_t dt, uint32_t* actual);

/*
* Starts a oneshot alarm
*
* expiration - relative expiration value from when kernel handles syscall.
*
* Side-effects: cancels any existing/outstanding alarms
*/
int libtock_alarm_command_set_relative_blind(uint32_t dt);

/*
* Starts a oneshot alarm
*
Expand Down
12 changes: 12 additions & 0 deletions libtock/services/alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ static uint32_t ms_to_ticks(uint32_t ms) {
return ticks;
}


// Declare non-public export of helper for libtock-sync.
uint32_t _ms_to_ticks(uint32_t ms);
/** \brief Private export of ms->ticks helper to libtock-sync
*
* This is a non-stable, non-public interface for a helper
* function which is also useful to libtock-sync.
*/
uint32_t _ms_to_ticks(uint32_t ms) {
return ms_to_ticks(ms);
}

uint32_t libtock_alarm_ticks_to_ms(uint32_t ticks) {
// `ticks_to_ms`'s conversion will be accurate to within the range
// 0 to 1 milliseconds less than the exact conversion
Expand Down
36 changes: 36 additions & 0 deletions libtock/tock.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,25 @@ int yield_no_wait(void) {
}
}

yield_waitfor_return_t yield_wait_for(uint32_t driver, uint32_t subscribe) {
register uint32_t waitfor __asm__ ("r0") = 2; // yield-waitfor
register uint32_t r1 __asm__ ("r1") = driver;
register uint32_t r2 __asm__ ("r2") = 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" (waitfor), "r" (r1), "r" (r2)
: "memory"
);
yield_waitfor_return_t rv = {rv0, rv1, rv2};
return rv;
}


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 Expand Up @@ -459,6 +478,23 @@ int yield_no_wait(void) {
}
}

yield_waitfor_return_t yield_wait_for(uint32_t driver, uint32_t subscribe) {
register uint32_t waitfor __asm__ ("a0") = 2; // yield-waitfor
register uint32_t a1 __asm__ ("a1") = driver;
register uint32_t a2 __asm__ ("a2") = subscribe;
register uint32_t a4 __asm__ ("a4") = 0; // Yield
register int rv0 __asm__ ("a0");
register int rv1 __asm__ ("a1");
register int rv2 __asm__ ("a2");
__asm__ volatile (
"ecall\n"
: "=r" (rv0), "=r" (rv1), "=r" (rv2)
: "r" (waitfor), "r" (a1), "r" (a2), "r" (a4)
: "memory");
yield_waitfor_return_t rv = {rv0, rv1, rv2};
return rv;
}


void tock_restart(uint32_t completion_code) {
register uint32_t a0 __asm__ ("a0") = 1; // exit-restart
Expand Down
15 changes: 14 additions & 1 deletion libtock/tock.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ typedef struct {
uint32_t data;
} memop_return_t;

// Return structure for a Yield-WaitFor syscall. The return value are the
// arguments that would have been passed to the upcall the the Yield-WaitFor was
// waiting on.
typedef struct {
// Upcall argument 1.
uint32_t data0;
// Upcall argument 2.
uint32_t data1;
// Upcall argument 3.
uint32_t data2;
} yield_waitfor_return_t;

////////////////////////////////////////////////////////////////////////////////
///
/// HELPER FUNCTIONS
Expand Down Expand Up @@ -177,9 +189,10 @@ int tock_allow_userspace_r_return_to_returncode(allow_userspace_r_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);
yield_waitfor_return_t yield_wait_for(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
Loading