Skip to content
Open
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
1 change: 1 addition & 0 deletions native/src/include/nsi_timer_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void hwtimer_adjust_rt_ratio(double ratio_correction);
void hwtimer_wake_in_time(uint64_t time);
void hwtimer_set_silent_ticks(int64_t sys_ticks);
void hwtimer_enable(uint64_t period);
void hwtimer_set_tick_deadline(uint64_t deadline);
int64_t hwtimer_get_pending_silent_ticks(void);

void hwtimer_reset_rtc(void);
Expand Down
30 changes: 30 additions & 0 deletions native/src/timer_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static uint64_t hw_timer_timer; /* Event timer exposed to the HW scheduler */
static uint64_t hw_timer_tick_timer;
static uint64_t hw_timer_rt_timer;
static uint64_t hw_timer_awake_timer;
static uint64_t hw_timer_deadline_timer;

static uint64_t tick_p; /* Period of the ticker */
static int64_t silent_ticks;
Expand Down Expand Up @@ -129,6 +130,7 @@ static void hwtimer_update_timer(void)
{
hw_timer_timer = NSI_MIN(hw_timer_tick_timer, hw_timer_awake_timer);
hw_timer_timer = NSI_MIN(hw_timer_timer, hw_timer_rt_timer);
hw_timer_timer = NSI_MIN(hw_timer_timer, hw_timer_deadline_timer);
}

static inline void host_clock_gettime(struct timespec *tv)
Expand Down Expand Up @@ -173,6 +175,7 @@ static void hwtimer_init(void)
silent_ticks = 0;
hw_timer_tick_timer = NSI_NEVER;
hw_timer_awake_timer = NSI_NEVER;
hw_timer_deadline_timer = NSI_NEVER;
hwtimer_update_timer();

if (!reset_rtc) {
Expand Down Expand Up @@ -269,6 +272,13 @@ static void hwtimer_awake_timer_reached(void)
hw_irq_ctrl_set_irq(PHONY_HARD_IRQ);
}

static void hwtimer_deadline_timer_reached(void)
{
hw_timer_deadline_timer = NSI_NEVER;
hwtimer_update_timer();
hw_irq_ctrl_set_irq(TIMER_TICK_IRQ);
}

static void hwtimer_timer_reached(void)
{
uint64_t Now = hw_timer_timer;
Expand All @@ -281,6 +291,10 @@ static void hwtimer_timer_reached(void)
hwtimer_rt_timer_reached();
}

if (hw_timer_deadline_timer == Now) {
hwtimer_deadline_timer_reached();
}

if (hw_timer_tick_timer == Now) {
hwtimer_tick_timer_reached();
}
Expand Down Expand Up @@ -312,6 +326,22 @@ void hwtimer_wake_in_time(uint64_t time)
}
}

/**
* Raise the tick interrupt when simulated time reaches <deadline>, an absolute
* time in microseconds since boot. A deadline already passed fires at once.
* NSI_NEVER cancels without setting a new one.
*
* One-shot alternative to hwtimer_enable()'s periodic tick. Do not use both.
*/
void hwtimer_set_tick_deadline(uint64_t deadline)
{
uint64_t now = nsi_hws_get_time();

hw_timer_deadline_timer = NSI_MAX(deadline, now);
hwtimer_update_timer();
nsi_hws_find_next_event();
}

/**
* The kernel wants to skip the next sys_ticks tick interrupts
* If sys_ticks == 0, the next interrupt will be raised.
Expand Down