diff --git a/core/sched.cc b/core/sched.cc index a301591ee493e50e85fcef3f84d806eda147cdaa..35b4174cb82d7e8ef55e9dda24d2f5ce4d029412 100644 --- a/core/sched.cc +++ b/core/sched.cc @@ -652,6 +652,14 @@ thread::thread(std::function<void ()> func, attr attr, bool main) } } +static std::list<std::function<void (thread *)>> exit_notifiers; +void thread::register_exit_notifier(std::function<void (thread *)> &&n) +{ + WITH_LOCK(thread_map_mutex) { + exit_notifiers.push_front(std::move(n)); + } +} + thread::~thread() { cancel_this_thread_alarm(); @@ -662,6 +670,10 @@ thread::~thread() WITH_LOCK(thread_map_mutex) { thread_map.erase(_id); total_app_time_exited += _total_cpu_time; + + for (auto& notifier : exit_notifiers) { + notifier(this); + } } if (_attr._stack.deleter) { _attr._stack.deleter(_attr._stack); diff --git a/include/osv/sched.hh b/include/osv/sched.hh index c51981aaf00d5ae447f99d6d4d18267a729f8cc8..d8079f128096cd5b3e4c610e444daee5060fdb95 100644 --- a/include/osv/sched.hh +++ b/include/osv/sched.hh @@ -585,6 +585,18 @@ public: static thread *find_by_id(unsigned int id); static int numthreads(); + /** + * Registers an std::function that will be called when a thread is torn + * down. This is useful, for example, to run code that needs to cleanup + * resources acquired by a given thread, about which the thread has no + * knowledge about + * + * In general, this will not run in the same context as the dying thread, + * but rather from special scheduler methods. Therefore, one needs to be + * careful about stack usage in here. Do not register notifiers that use a + * lot of stack + */ + static void register_exit_notifier(std::function<void (thread *)> &&n); private: class reaper; friend class reaper;