Allow adding timers from timer callbacks.

This commit is contained in:
Maxim Poliakovski 2022-02-05 17:10:57 +01:00
parent 5c177cc50f
commit 25a4fd1107
3 changed files with 28 additions and 13 deletions

View File

@ -48,7 +48,9 @@ uint32_t TimerManager::add_oneshot_timer(uint64_t timeout, timer_cb cb)
this->timer_queue.push(timer_desc);
// notify listeners about changes in the timer queue
this->notify_timer_changes();
if (!this->cb_active) {
this->notify_timer_changes();
}
return ti->id;
}
@ -72,7 +74,9 @@ uint32_t TimerManager::add_cyclic_timer(uint64_t interval, timer_cb cb)
this->timer_queue.push(timer_desc);
// notify listeners about changes in the timer queue
this->notify_timer_changes();
if (!this->cb_active) {
this->notify_timer_changes();
}
return ti->id;
}
@ -85,7 +89,9 @@ void TimerManager::cancel_timer(uint32_t id)
} else {
this->timer_queue.remove_by_id(id);
}
this->notify_timer_changes();
if (!this->cb_active) {
this->notify_timer_changes();
}
}
uint64_t TimerManager::process_timers(uint64_t time_now)
@ -100,8 +106,7 @@ uint64_t TimerManager::process_timers(uint64_t time_now)
cur_timer = this->timer_queue.top().get();
while (cur_timer->timeout_ns <= time_now ||
cur_timer->timeout_ns <= (time_now + MIN_TIMEOUT_NS)) {
// invoke timer callback
cur_timer->cb();
timer_cb cb = cur_timer->cb;
// re-arm cyclic timers
if (cur_timer->interval_ns) {
@ -114,6 +119,13 @@ uint64_t TimerManager::process_timers(uint64_t time_now)
this->timer_queue.pop();
}
this->cb_active = true;
// invoke timer callback
cb();
this->cb_active = false;
// process next timer
if (this->timer_queue.empty()) {
return 0ULL;
@ -124,4 +136,4 @@ uint64_t TimerManager::process_timers(uint64_t time_now)
// return time slice in nanoseconds until next timer's expiry
return cur_timer->timeout_ns - time_now;
}
}

View File

@ -82,7 +82,7 @@ public:
return timer_manager;
};
// callback ´for retrieving current time
// callback for retrieving current time
void set_time_now_cb(const function<uint64_t()> &cb) {
this->get_time_now = cb;
};
@ -103,13 +103,14 @@ private:
static TimerManager* timer_manager;
TimerManager(){}; // private constructor to implement a singleton
uint32_t id = 0;
// timer queue
my_priority_queue<shared_ptr<TimerInfo>, vector<shared_ptr<TimerInfo>>, MyGtComparator> timer_queue;
function<uint64_t()> get_time_now;
function<void()> notify_timer_changes;
uint32_t id = 0;
bool cb_active = false; // true if a timer callback is executing
};
#endif // TIMER_MANAGER_H
#endif // TIMER_MANAGER_H

View File

@ -319,7 +319,11 @@ uint64_t process_events()
void force_cycle_counter_reload()
{
// tell the interpreter loop to reload cycle counter
bb_kind = BB_end_kind::BB_TIMER;
if (bb_kind == BB_end_kind::BB_NONE || bb_kind == BB_end_kind::BB_TIMER) {
bb_kind = BB_end_kind::BB_TIMER;
} else {
ABORT_F("PPCEXEC: attempt to override basic block type %d", bb_kind);
}
}
/** Execute PPC code as long as power is on. */
@ -412,7 +416,6 @@ static void ppc_exec_inner()
max_cycles = process_events();
}
//if (eb_last) {
if (bb_kind != BB_end_kind::BB_NONE) { // execution block ended ?
if (!power_on)
break;
@ -611,7 +614,6 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
max_cycles = process_events();
}
//if (eb_last) {
if (bb_kind != BB_end_kind::BB_NONE) { // execution block ended ?
// reload cycle counter if requested
if (bb_kind == BB_end_kind::BB_TIMER) {