diff --git a/repos/dde_linux/src/include/lx_emul/task.h b/repos/dde_linux/src/include/lx_emul/task.h index 487c8eed39..3873bdff22 100644 --- a/repos/dde_linux/src/include/lx_emul/task.h +++ b/repos/dde_linux/src/include/lx_emul/task.h @@ -46,6 +46,8 @@ void *lx_emul_task_stack(struct task_struct const * task); char lx_emul_task_another_runnable(void); +void lx_emul_task_mark_for_removal(struct task_struct const * task); + #ifdef __cplusplus } #endif diff --git a/repos/dde_linux/src/include/lx_kit/task.h b/repos/dde_linux/src/include/lx_kit/task.h index c75a0eb506..d222665944 100644 --- a/repos/dde_linux/src/include/lx_kit/task.h +++ b/repos/dde_linux/src/include/lx_kit/task.h @@ -34,7 +34,7 @@ class Lx_kit::Task : public Genode::List::Element using Name = String<64>; - enum State { INIT, RUNNING, BLOCKED }; + enum State { INIT, RUNNING, BLOCKED, DESTROY }; enum Type { NORMAL, IRQ_HANDLER, TIME_HANDLER }; private: @@ -100,6 +100,15 @@ class Lx_kit::Task : public Genode::List::Element * Shortcut to enter blocking state and request scheduling */ void block_and_schedule(); + + /** + * Mark for destruction + * + * Let the scheduler clean up the task when a new one is added. + */ + void mark_for_destruction(); + + bool destroy() const; }; #endif /* _LX_KIT__TASK_H_ */ diff --git a/repos/dde_linux/src/lib/lx_emul/shadow/kernel/exit.c b/repos/dde_linux/src/lib/lx_emul/shadow/kernel/exit.c index b2ca7576ba..d6e78cb9c6 100644 --- a/repos/dde_linux/src/lib/lx_emul/shadow/kernel/exit.c +++ b/repos/dde_linux/src/lib/lx_emul/shadow/kernel/exit.c @@ -16,6 +16,7 @@ #include #include +#include int rcuwait_wake_up(struct rcuwait * w) @@ -38,6 +39,9 @@ void __noreturn do_exit(long code) complete(tsk->vfork_done); current->flags |= PF_NOFREEZE; + + lx_emul_task_mark_for_removal(tsk); + schedule(); BUG(); } diff --git a/repos/dde_linux/src/lib/lx_emul/task.cc b/repos/dde_linux/src/lib/lx_emul/task.cc index 04ba17b4fb..fd3f82934b 100644 --- a/repos/dde_linux/src/lib/lx_emul/task.cc +++ b/repos/dde_linux/src/lib/lx_emul/task.cc @@ -108,3 +108,9 @@ extern "C" char lx_emul_task_another_runnable() return Lx_kit::env().scheduler.another_runnable(&task); } + + +extern "C" void lx_emul_task_mark_for_removal(struct task_struct const *t) +{ + Lx_kit::env().scheduler.task((void*)t).mark_for_destruction(); +} diff --git a/repos/dde_linux/src/lib/lx_kit/scheduler.cc b/repos/dde_linux/src/lib/lx_kit/scheduler.cc index 646464ba1d..7f64977fb0 100644 --- a/repos/dde_linux/src/lib/lx_kit/scheduler.cc +++ b/repos/dde_linux/src/lib/lx_kit/scheduler.cc @@ -21,7 +21,7 @@ #include #include -#include +#include #include using namespace Genode; @@ -119,6 +119,17 @@ void Scheduler::schedule() /* update jiffies before running task */ //Lx::timer_update_jiffies(); + for (Task * t = _present_list.first(); t; ) { + + Task *tmp = t; + t = t->next(); + + if (!tmp->destroy()) + continue; + + Genode::destroy(Lx_kit::env().heap, tmp); + } + for (Task * t = _present_list.first(); t; t = t->next()) { if (!t->runnable()) diff --git a/repos/dde_linux/src/lib/lx_kit/task.cc b/repos/dde_linux/src/lib/lx_kit/task.cc index a6951b1918..ce9771d112 100644 --- a/repos/dde_linux/src/lib/lx_kit/task.cc +++ b/repos/dde_linux/src/lib/lx_kit/task.cc @@ -27,6 +27,7 @@ bool Task::runnable() const case INIT: return true; case RUNNING: return true; case BLOCKED: return false; + case DESTROY: return false; } error("Invalid task state?!"); return false; @@ -139,6 +140,18 @@ void Task::block_and_schedule() } +void Task::mark_for_destruction() +{ + _state = DESTROY; +} + + +bool Task::destroy() const +{ + return _state == DESTROY; +} + + Task::Task(int (* func)(void*), void * arg, void * lx_task,