dde_linux: remove exited tasks

The commit introduces means to mark a task for destruction that is
removed on the next scheduling cycle. This fixes stack leakage from
dynamic kworker tasks.

Issue #4575.
This commit is contained in:
Josef Söntgen 2022-07-21 16:09:25 +02:00 committed by Christian Helmuth
parent bc665384c3
commit 3d8c1080b1
6 changed files with 47 additions and 2 deletions

View File

@ -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

View File

@ -34,7 +34,7 @@ class Lx_kit::Task : public Genode::List<Lx_kit::Task>::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<Lx_kit::Task>::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_ */

View File

@ -16,6 +16,7 @@
#include <linux/rcuwait.h>
#include <lx_emul/debug.h>
#include <lx_emul/task.h>
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();
}

View File

@ -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();
}

View File

@ -21,7 +21,7 @@
#include <base/thread.h>
#include <os/backtrace.h>
#include <lx_kit/scheduler.h>
#include <lx_kit/env.h>
#include <lx_kit/task.h>
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())

View File

@ -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,