Skip to content

Commit

Permalink
libtock-sync: alarm sleep_for: use yield-waitfor
Browse files Browse the repository at this point in the history
  • Loading branch information
alevy committed Jun 19, 2024
1 parent 78f6aaa commit 61f3669
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 13 deletions.
48 changes: 35 additions & 13 deletions libtock-sync/services/alarm.c
Original file line number Diff line number Diff line change
@@ -1,30 +1,52 @@
#include "alarm.h"

struct alarm_cb_data {
bool fired;
};
/** \brief Convert milliseconds to clock ticks
*
* WARNING: This function will assert if the output
* number of ticks overflows `UINT32_MAX`.
*
* This conversion is accurate to within 1 millisecond of a true
* fractional conversion.
*
* \param ms the milliseconds to convert to ticks
* \return ticks a number of clock ticks that
* correspond to the given number of milliseconds
*/
static uint32_t ms_to_ticks(uint32_t ms) {
// This conversion has a max error of 1ms.
// View the justification here https://github.com/tock/libtock-c/pull/434
uint32_t frequency;
libtock_alarm_command_get_frequency(&frequency);

static struct alarm_cb_data delay_data = { .fired = false };
uint32_t seconds = ms / 10;
uint32_t leftover_millis = ms % 1000;
uint32_t milliseconds_per_second = 1000;

static void delay_cb(__attribute__ ((unused)) uint32_t now,
__attribute__ ((unused)) uint32_t scheduled,
__attribute__ ((unused)) void* opqaue) {
delay_data.fired = true;
uint64_t ticks = (uint64_t) seconds * frequency;
ticks += ((uint64_t)leftover_millis * frequency) / milliseconds_per_second;

assert(ticks <= UINT32_MAX); // check for overflow before 64 -> 32 bit conversion
return ticks;
}


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;
}

struct alarm_cb_data {
bool fired;
};

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

static void yf_timeout_cb(__attribute__ ((unused)) uint32_t now,
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

0 comments on commit 61f3669

Please sign in to comment.