Skip to content
Snippets Groups Projects
Commit c87706a3 authored by Avi Kivity's avatar Avi Kivity
Browse files

sched: migrate timers

When we migrate a thread, remove its timers from the cpu-local timer list,
and move them back when we complete migration.
parent ac2c0ff2
No related branches found
No related tags found
No related merge requests found
...@@ -59,6 +59,9 @@ void cpu::handle_incoming_wakeups() ...@@ -59,6 +59,9 @@ void cpu::handle_incoming_wakeups()
q.pop_front_nonatomic(); q.pop_front_nonatomic();
t._on_runqueue = true; t._on_runqueue = true;
runqueue.push_back(t); runqueue.push_back(t);
with_lock(irq_lock, [&] {
t.resume_timers();
});
} }
} }
} }
...@@ -95,6 +98,7 @@ void cpu::load_balance() ...@@ -95,6 +98,7 @@ void cpu::load_balance()
auto& mig = runqueue.back(); auto& mig = runqueue.back();
runqueue.pop_back(); runqueue.pop_back();
// we won't race with wake(), since we're not _waiting // we won't race with wake(), since we're not _waiting
mig.suspend_timers();
mig._cpu = min; mig._cpu = min;
min->incoming_wakeups[id].push_front(mig); min->incoming_wakeups[id].push_front(mig);
// FIXME: IPI // FIXME: IPI
...@@ -148,6 +152,7 @@ thread::thread(std::function<void ()> func, attr attr, bool main) ...@@ -148,6 +152,7 @@ thread::thread(std::function<void ()> func, attr attr, bool main)
, _waiting(false) , _waiting(false)
, _attr(attr) , _attr(attr)
, _terminated(false) , _terminated(false)
, _timers_need_reload()
, _joiner() , _joiner()
{ {
with_lock(thread_list_mutex, [this] { with_lock(thread_list_mutex, [this] {
...@@ -233,6 +238,28 @@ void thread::complete() ...@@ -233,6 +238,28 @@ void thread::complete()
} }
} }
void thread::suspend_timers()
{
if (_timers_need_reload) {
return;
}
_timers_need_reload = true;
for (auto& t : _active_timers) {
_cpu->timers.suspend(t);
}
}
void thread::resume_timers()
{
if (!_timers_need_reload) {
return;
}
_timers_need_reload = false;
for (auto& t : _active_timers) {
_cpu->timers.resume(t);
}
}
void thread::join() void thread::join()
{ {
_joiner = current(); _joiner = current();
...@@ -263,6 +290,29 @@ void timer_list::fired() ...@@ -263,6 +290,29 @@ void timer_list::fired()
} }
} }
// call with irq disabled
void timer_list::suspend(bi::list<timer>& timers)
{
for (auto& t : timers) {
assert(!t._expired);
_list.erase(_list.iterator_to(t));
}
}
// call with irq disabled
void timer_list::resume(bi::list<timer>& timers)
{
bool rearm = false;
for (auto& t : timers) {
assert(!t._expired);
auto i = _list.insert(t).first;
rearm |= i == _list.begin();
}
if (rearm) {
clock_event->set(_list.begin()->_time);
}
}
void timer_list::callback_dispatch::fired() void timer_list::callback_dispatch::fired()
{ {
cpu::current()->timers.fired(); cpu::current()->timers.fired();
...@@ -309,7 +359,7 @@ void timer::cancel() ...@@ -309,7 +359,7 @@ void timer::cancel()
return; return;
} }
_t._active_timers.erase(_t._active_timers.iterator_to(*this)); _t._active_timers.erase(_t._active_timers.iterator_to(*this));
_t._cpu->timers._list.erase(*this); _t._cpu->timers._list.erase(_t._cpu->timers._list.iterator_to(*this));
_expired = false; _expired = false;
}); });
// even if we remove the first timer, allow it to expire rather than // even if we remove the first timer, allow it to expire rather than
......
...@@ -87,6 +87,8 @@ private: ...@@ -87,6 +87,8 @@ private:
void init_stack(); void init_stack();
void setup_tcb(); void setup_tcb();
void complete(); void complete();
void suspend_timers();
void resume_timers();
static void on_thread_stack(thread* t); static void on_thread_stack(thread* t);
private: private:
std::function<void ()> _func; std::function<void ()> _func;
...@@ -97,6 +99,7 @@ private: ...@@ -97,6 +99,7 @@ private:
attr _attr; attr _attr;
cpu* _cpu; cpu* _cpu;
bool _terminated; bool _terminated;
bool _timers_need_reload;
bi::list<timer> _active_timers; bi::list<timer> _active_timers;
friend void thread_main_c(thread* t); friend void thread_main_c(thread* t);
friend class wait_guard; friend class wait_guard;
...@@ -117,6 +120,8 @@ public: ...@@ -117,6 +120,8 @@ public:
class timer_list { class timer_list {
public: public:
void fired(); void fired();
void suspend(bi::list<timer>& t);
void resume(bi::list<timer>& t);
private: private:
friend class timer; friend class timer;
bi::set<timer, bi::base_hook<bi::set_base_hook<>>> _list; bi::set<timer, bi::base_hook<bi::set_base_hook<>>> _list;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment