From c4eea920a4e90eac43cc0cb47a9128eb6928dc8b Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Tue, 21 Feb 2017 17:35:51 +0100 Subject: [PATCH] libc: fix resume mechanism Fixes #2287 --- repos/libports/src/lib/libc/task.cc | 49 +++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/repos/libports/src/lib/libc/task.cc b/repos/libports/src/lib/libc/task.cc index 3de57f144..cbc94233a 100644 --- a/repos/libports/src/lib/libc/task.cc +++ b/repos/libports/src/lib/libc/task.cc @@ -375,7 +375,8 @@ struct Libc::Kernel Application_code *_app_code = nullptr; bool _app_returned = false; - bool _resume_main_once = false; + bool _resume_main_once = false; + bool _suspend_scheduled = false; Select_handler_base *_scheduled_select_handler = nullptr; @@ -447,6 +448,21 @@ struct Libc::Kernel Pthreads _pthreads { _timer_accessor }; + struct Resumer + { + GENODE_RPC(Rpc_resume, void, resume); + GENODE_RPC_INTERFACE(Rpc_resume); + }; + + struct Resumer_component : Rpc_object + { + Kernel &_kernel; + + Resumer_component(Kernel &kernel) : _kernel(kernel) { } + + void resume() { _kernel.run_after_resume(); } + }; + /** * Trampoline to application (user) code * @@ -566,12 +582,31 @@ struct Libc::Kernel /* _setjmp() returned after _longjmp() - user context suspended */ - while (!_app_returned) { + while ((!_app_returned) && (!_suspend_scheduled)) { _env.ep().wait_and_dispatch_one_signal(); if (_resume_main_once && !_setjmp(_kernel_context)) _switch_to_user(); } + + _suspend_scheduled = false; + } + + /* + * Run libc application main context after suspend and resume + */ + void run_after_resume() + { + if (!_setjmp(_kernel_context)) + _switch_to_user(); + + while ((!_app_returned) && (!_suspend_scheduled)) { + _env.ep().wait_and_dispatch_one_signal(); + if (_resume_main_once && !_setjmp(_kernel_context)) + _switch_to_user(); + } + + _suspend_scheduled = false; } /** @@ -635,6 +670,7 @@ struct Libc::Kernel if (!_setjmp(_user_context)) { _valid_user_context = true; + _suspend_scheduled = true; _switch_to_kernel(); } else { _valid_user_context = false; @@ -663,7 +699,14 @@ struct Libc::Kernel { _resume_main_handler.construct(_env.ep(), *this, &Kernel::_resume_main); - _resume_main(); + Resumer_component resumer { *this }; + + Capability resumer_cap = + _env.ep().rpc_ep().manage(&resumer); + + resumer_cap.call(); + + _env.ep().rpc_ep().dissolve(&resumer); } /**