mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-06 18:48:35 +00:00
parent
a891b3832c
commit
a0a112ffe7
@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/log.h>
|
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
#include <base/registry.h>
|
#include <base/registry.h>
|
||||||
#include <base/child.h>
|
#include <base/child.h>
|
||||||
@ -34,9 +33,7 @@
|
|||||||
/* libc-internal includes */
|
/* libc-internal includes */
|
||||||
#include <internal/init.h>
|
#include <internal/init.h>
|
||||||
#include <internal/clone_session.h>
|
#include <internal/clone_session.h>
|
||||||
#include <internal/kernel_routine.h>
|
#include <internal/monitor.h>
|
||||||
#include <internal/suspend.h>
|
|
||||||
#include <internal/resume.h>
|
|
||||||
#include <internal/signal.h>
|
#include <internal/signal.h>
|
||||||
|
|
||||||
namespace Libc {
|
namespace Libc {
|
||||||
@ -58,15 +55,15 @@ namespace Libc {
|
|||||||
|
|
||||||
using namespace Libc;
|
using namespace Libc;
|
||||||
|
|
||||||
|
namespace { using Fn = Monitor::Function_result; }
|
||||||
|
|
||||||
|
|
||||||
static pid_t fork_result;
|
static pid_t fork_result;
|
||||||
|
|
||||||
static Env *_env_ptr;
|
static Env *_env_ptr;
|
||||||
static Allocator *_alloc_ptr;
|
static Allocator *_alloc_ptr;
|
||||||
static Suspend *_suspend_ptr;
|
static Monitor *_monitor_ptr;
|
||||||
static Resume *_resume_ptr;
|
|
||||||
static Libc::Signal *_signal_ptr;
|
static Libc::Signal *_signal_ptr;
|
||||||
static Kernel_routine_scheduler *_kernel_routine_scheduler_ptr;
|
|
||||||
static Heap *_malloc_heap_ptr;
|
static Heap *_malloc_heap_ptr;
|
||||||
static void *_user_stack_base_ptr;
|
static void *_user_stack_base_ptr;
|
||||||
static size_t _user_stack_size;
|
static size_t _user_stack_size;
|
||||||
@ -77,6 +74,15 @@ static Binary_name const *_binary_name_ptr;
|
|||||||
static Forked_children *_forked_children_ptr;
|
static Forked_children *_forked_children_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
static Libc::Monitor & monitor()
|
||||||
|
{
|
||||||
|
struct Missing_call_of_init_fork : Genode::Exception { };
|
||||||
|
if (!_monitor_ptr)
|
||||||
|
throw Missing_call_of_init_fork();
|
||||||
|
return *_monitor_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Libc::Child_config
|
struct Libc::Child_config
|
||||||
{
|
{
|
||||||
Constructible<Attached_ram_dataspace> _ds { };
|
Constructible<Attached_ram_dataspace> _ds { };
|
||||||
@ -348,44 +354,35 @@ struct Libc::Local_clone_service : Noncopyable
|
|||||||
|
|
||||||
typedef Local_service<Session> Service;
|
typedef Local_service<Session> Service;
|
||||||
|
|
||||||
Child_ready &_child_ready;
|
|
||||||
|
|
||||||
Resume &_resume;
|
|
||||||
|
|
||||||
Io_signal_handler<Local_clone_service> _child_ready_handler;
|
|
||||||
|
|
||||||
void _handle_child_ready()
|
|
||||||
{
|
|
||||||
_child_ready.child_ready();
|
|
||||||
|
|
||||||
_resume.resume_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Factory : Local_service<Session>::Factory
|
struct Factory : Local_service<Session>::Factory
|
||||||
{
|
{
|
||||||
Session &_session;
|
Session &_session;
|
||||||
Signal_context_capability _started_sigh;
|
Child_ready &_child_ready;
|
||||||
|
|
||||||
Factory(Session &session, Signal_context_capability started_sigh)
|
Factory(Session &session, Child_ready &child_ready)
|
||||||
: _session(session), _started_sigh(started_sigh) { }
|
: _session(session), _child_ready(child_ready) { }
|
||||||
|
|
||||||
Session &create(Args const &, Affinity) override { return _session; }
|
Session &create(Args const &, Affinity) override { return _session; }
|
||||||
|
|
||||||
void upgrade(Session &, Args const &) override { }
|
void upgrade(Session &, Args const &) override { }
|
||||||
|
|
||||||
void destroy(Session &) override { Signal_transmitter(_started_sigh).submit(); }
|
void destroy(Session &) override
|
||||||
|
{
|
||||||
|
Mutex mutex { };
|
||||||
|
mutex.acquire();
|
||||||
|
|
||||||
|
monitor().monitor(mutex, [&] {
|
||||||
|
_child_ready.child_ready();
|
||||||
|
return Fn::COMPLETE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} _factory;
|
} _factory;
|
||||||
|
|
||||||
Service service { _factory };
|
Service service { _factory };
|
||||||
|
|
||||||
Local_clone_service(Env &env, Entrypoint &ep, Child_ready &child_ready,
|
Local_clone_service(Env &env, Entrypoint &ep, Child_ready &child_ready)
|
||||||
Resume &resume)
|
: _session(env, ep), _factory(_session, child_ready) { }
|
||||||
:
|
|
||||||
_session(env, ep), _child_ready(child_ready), _resume(resume),
|
|
||||||
_child_ready_handler(env.ep(), *this, &Local_clone_service::_handle_child_ready),
|
|
||||||
_factory(_session, _child_ready_handler)
|
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -395,8 +392,6 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
|
|
||||||
Binary_name const _binary_name;
|
Binary_name const _binary_name;
|
||||||
|
|
||||||
Resume &_resume;
|
|
||||||
|
|
||||||
Signal &_signal;
|
Signal &_signal;
|
||||||
|
|
||||||
pid_t const _pid;
|
pid_t const _pid;
|
||||||
@ -408,8 +403,8 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
Name const _name { _pid };
|
Name const _name { _pid };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signal handler triggered at the main entrypoint, waking up the libc
|
* Signal handler triggered at the main entrypoint, charging 'SIGCHILD'
|
||||||
* suspend mechanism.
|
* and waking up the libc monitor mechanism.
|
||||||
*/
|
*/
|
||||||
Io_signal_handler<Libc::Forked_child> _exit_handler {
|
Io_signal_handler<Libc::Forked_child> _exit_handler {
|
||||||
_env.ep(), *this, &Forked_child::_handle_exit };
|
_env.ep(), *this, &Forked_child::_handle_exit };
|
||||||
@ -417,7 +412,7 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
void _handle_exit()
|
void _handle_exit()
|
||||||
{
|
{
|
||||||
_signal.charge(SIGCHLD);
|
_signal.charge(SIGCHLD);
|
||||||
_resume.resume_all();
|
monitor().trigger_monitor_examination();
|
||||||
}
|
}
|
||||||
|
|
||||||
Child_config _child_config;
|
Child_config _child_config;
|
||||||
@ -427,20 +422,6 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
Local_clone_service _local_clone_service;
|
Local_clone_service _local_clone_service;
|
||||||
Local_rom_service _config_rom_service;
|
Local_rom_service _config_rom_service;
|
||||||
|
|
||||||
struct Wait_fork_ready : Kernel_routine
|
|
||||||
{
|
|
||||||
Forked_child const &child;
|
|
||||||
|
|
||||||
Wait_fork_ready(Forked_child const &child) : child(child) { }
|
|
||||||
|
|
||||||
void execute_in_kernel() override
|
|
||||||
{
|
|
||||||
/* keep executing this kernel routine until child is running */
|
|
||||||
if (!child.running() && !child.exited())
|
|
||||||
_kernel_routine_scheduler_ptr->register_kernel_routine(*this);
|
|
||||||
}
|
|
||||||
} wait_fork_ready { *this };
|
|
||||||
|
|
||||||
pid_t pid() const { return _pid; }
|
pid_t pid() const { return _pid; }
|
||||||
|
|
||||||
bool running() const { return _state == State::RUNNING; }
|
bool running() const { return _state == State::RUNNING; }
|
||||||
@ -459,7 +440,7 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
/*
|
/*
|
||||||
* Don't modify the state if the child already exited.
|
* Don't modify the state if the child already exited.
|
||||||
* This can happen for short-lived children where the asynchronous
|
* This can happen for short-lived children where the asynchronous
|
||||||
* notification for '_handle_exit' arrives before '_handle_child_ready'
|
* notification for 'Child_exit' arrives before 'Child_ready'
|
||||||
* (while the parent is still blocking in the fork call).
|
* (while the parent is still blocking in the fork call).
|
||||||
*/
|
*/
|
||||||
if (_state == State::STARTING_UP)
|
if (_state == State::STARTING_UP)
|
||||||
@ -544,6 +525,10 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
_exit_code = code;
|
_exit_code = code;
|
||||||
_state = State::EXITED;
|
_state = State::EXITED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't destroy the child object in a monitor from this RPC
|
||||||
|
* function as this would deadlock in an 'Entrypoint::dissolve()'.
|
||||||
|
*/
|
||||||
Signal_transmitter(_exit_handler).submit();
|
Signal_transmitter(_exit_handler).submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,7 +538,6 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
Entrypoint &fork_ep,
|
Entrypoint &fork_ep,
|
||||||
Allocator &alloc,
|
Allocator &alloc,
|
||||||
Binary_name const &binary_name,
|
Binary_name const &binary_name,
|
||||||
Resume &resume,
|
|
||||||
Signal &signal,
|
Signal &signal,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
Config_accessor const &config_accessor,
|
Config_accessor const &config_accessor,
|
||||||
@ -561,11 +545,11 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
Local_rom_services &local_rom_services)
|
Local_rom_services &local_rom_services)
|
||||||
:
|
:
|
||||||
_env(env), _binary_name(binary_name),
|
_env(env), _binary_name(binary_name),
|
||||||
_resume(resume), _signal(signal), _pid(pid),
|
_signal(signal), _pid(pid),
|
||||||
_child_config(env, config_accessor, pid),
|
_child_config(env, config_accessor, pid),
|
||||||
_parent_services(parent_services),
|
_parent_services(parent_services),
|
||||||
_local_rom_services(local_rom_services),
|
_local_rom_services(local_rom_services),
|
||||||
_local_clone_service(env, fork_ep, *this, resume),
|
_local_clone_service(env, fork_ep, *this),
|
||||||
_config_rom_service(fork_ep, "config", _child_config.ds_cap()),
|
_config_rom_service(fork_ep, "config", _child_config.ds_cap()),
|
||||||
_child(env.rm(), fork_ep.rpc_ep(), *this)
|
_child(env.rm(), fork_ep.rpc_ep(), *this)
|
||||||
{ }
|
{ }
|
||||||
@ -574,7 +558,7 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void fork_kernel_routine()
|
static Forked_child * fork_kernel_routine()
|
||||||
{
|
{
|
||||||
fork_result = 0;
|
fork_result = 0;
|
||||||
|
|
||||||
@ -585,7 +569,6 @@ static void fork_kernel_routine()
|
|||||||
|
|
||||||
Env &env = *_env_ptr;
|
Env &env = *_env_ptr;
|
||||||
Allocator &alloc = *_alloc_ptr;
|
Allocator &alloc = *_alloc_ptr;
|
||||||
Resume &resume = *_resume_ptr;
|
|
||||||
Libc::Signal &signal = *_signal_ptr;
|
Libc::Signal &signal = *_signal_ptr;
|
||||||
|
|
||||||
pid_t const child_pid = ++_pid_cnt;
|
pid_t const child_pid = ++_pid_cnt;
|
||||||
@ -597,15 +580,15 @@ static void fork_kernel_routine()
|
|||||||
|
|
||||||
static Local_rom_services local_rom_services(env, fork_ep, alloc);
|
static Local_rom_services local_rom_services(env, fork_ep, alloc);
|
||||||
|
|
||||||
Registered<Forked_child> &child = *new (alloc)
|
Registered<Forked_child> *child = new (alloc)
|
||||||
Registered<Forked_child>(*_forked_children_ptr, env, fork_ep, alloc,
|
Registered<Forked_child>(*_forked_children_ptr, env, fork_ep, alloc,
|
||||||
*_binary_name_ptr, resume,
|
*_binary_name_ptr,
|
||||||
signal, child_pid, *_config_accessor_ptr,
|
signal, child_pid, *_config_accessor_ptr,
|
||||||
parent_services, local_rom_services);
|
parent_services, local_rom_services);
|
||||||
|
|
||||||
fork_result = child_pid;
|
fork_result = child_pid;
|
||||||
|
|
||||||
_kernel_routine_scheduler_ptr->register_kernel_routine(child.wait_fork_ready);
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -627,25 +610,28 @@ extern "C" pid_t __sys_fork(void)
|
|||||||
_user_stack_base_ptr = (void *)mystack.base;
|
_user_stack_base_ptr = (void *)mystack.base;
|
||||||
_user_stack_size = mystack.top - mystack.base;
|
_user_stack_size = mystack.top - mystack.base;
|
||||||
|
|
||||||
struct Fork_kernel_routine : Kernel_routine
|
Mutex mutex { };
|
||||||
{
|
mutex.acquire();
|
||||||
void execute_in_kernel() override { fork_kernel_routine(); }
|
|
||||||
|
|
||||||
} kernel_routine { };
|
enum class Stage { FORK, WAIT_FORK_READY };
|
||||||
|
|
||||||
struct Missing_call_of_init_fork : Exception { };
|
Stage stage { Stage::FORK };
|
||||||
if (!_kernel_routine_scheduler_ptr || !_suspend_ptr)
|
Forked_child *child { nullptr };
|
||||||
throw Missing_call_of_init_fork();
|
|
||||||
|
|
||||||
_kernel_routine_scheduler_ptr->register_kernel_routine(kernel_routine);
|
monitor().monitor(mutex, [&] {
|
||||||
|
switch (stage) {
|
||||||
|
case Stage::FORK:
|
||||||
|
child = fork_kernel_routine();
|
||||||
|
stage = Stage::WAIT_FORK_READY; [[ fallthrough ]]
|
||||||
|
case Stage::WAIT_FORK_READY:
|
||||||
|
if (child->running() || child->exited()) {
|
||||||
|
return Fn::COMPLETE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
struct Suspend_functor_impl : Suspend_functor
|
return Fn::INCOMPLETE;
|
||||||
{
|
});
|
||||||
bool suspend() override { return false; }
|
|
||||||
|
|
||||||
} suspend_functor { };
|
|
||||||
|
|
||||||
_suspend_ptr->suspend(suspend_functor, 0);
|
|
||||||
|
|
||||||
return fork_result;
|
return fork_result;
|
||||||
}
|
}
|
||||||
@ -669,15 +655,15 @@ pid_t getpid(void) __attribute__((weak, alias("__sys_getpid")));
|
|||||||
** wait4 **
|
** wait4 **
|
||||||
***********/
|
***********/
|
||||||
|
|
||||||
namespace Libc { struct Wait4_suspend_functor; }
|
namespace Libc { struct Wait4_functor; }
|
||||||
|
|
||||||
struct Libc::Wait4_suspend_functor : Suspend_functor
|
struct Libc::Wait4_functor
|
||||||
{
|
{
|
||||||
Forked_children &_children;
|
Forked_children &_children;
|
||||||
|
|
||||||
pid_t const _pid;
|
pid_t const _pid;
|
||||||
|
|
||||||
Wait4_suspend_functor(pid_t pid, Forked_children &children)
|
Wait4_functor(pid_t pid, Forked_children &children)
|
||||||
: _children(children), _pid(pid) { }
|
: _children(children), _pid(pid) { }
|
||||||
|
|
||||||
template <typename FN>
|
template <typename FN>
|
||||||
@ -700,14 +686,6 @@ struct Libc::Wait4_suspend_functor : Suspend_functor
|
|||||||
fn(*child_ptr);
|
fn(*child_ptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool suspend() override
|
|
||||||
{
|
|
||||||
bool const any_child_exited =
|
|
||||||
with_exited_child([] (Forked_child const &) { });
|
|
||||||
|
|
||||||
return !any_child_exited;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -724,25 +702,23 @@ extern "C" pid_t __sys_wait4(pid_t pid, int *status, int options, rusage *rusage
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Missing_call_of_init_fork : Exception { };
|
Wait4_functor functor { pid, *_forked_children_ptr };
|
||||||
if (!_suspend_ptr)
|
|
||||||
throw Missing_call_of_init_fork();
|
|
||||||
|
|
||||||
Wait4_suspend_functor suspend_functor { pid, *_forked_children_ptr };
|
Mutex mutex { };
|
||||||
|
mutex.acquire();
|
||||||
|
|
||||||
for (;;) {
|
monitor().monitor(mutex, [&] {
|
||||||
|
functor.with_exited_child([&] (Registered<Forked_child> &child) {
|
||||||
suspend_functor.with_exited_child([&] (Registered<Forked_child> &child) {
|
|
||||||
result = child.pid();
|
result = child.pid();
|
||||||
exit_code = child.exit_code();
|
exit_code = child.exit_code();
|
||||||
destroy(*_alloc_ptr, &child);
|
destroy(*_alloc_ptr, &child);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result >= 0 || (options & WNOHANG))
|
if (result >= 0 || (options & WNOHANG))
|
||||||
break;
|
return Fn::COMPLETE;
|
||||||
|
|
||||||
_suspend_ptr->suspend(suspend_functor, 0);
|
return Fn::INCOMPLETE;
|
||||||
}
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The libc expects status information in bits 0..6 and the exit value
|
* The libc expects status information in bits 0..6 and the exit value
|
||||||
@ -761,16 +737,13 @@ extern "C" pid_t wait4(pid_t, int *, int, rusage *) __attribute__((weak, alias("
|
|||||||
|
|
||||||
void Libc::init_fork(Env &env, Config_accessor const &config_accessor,
|
void Libc::init_fork(Env &env, Config_accessor const &config_accessor,
|
||||||
Allocator &alloc, Heap &malloc_heap, pid_t pid,
|
Allocator &alloc, Heap &malloc_heap, pid_t pid,
|
||||||
Suspend &suspend, Resume &resume, Signal &signal,
|
Monitor &monitor, Signal &signal,
|
||||||
Kernel_routine_scheduler &kernel_routine_scheduler,
|
|
||||||
Binary_name const &binary_name)
|
Binary_name const &binary_name)
|
||||||
{
|
{
|
||||||
_env_ptr = &env;
|
_env_ptr = &env;
|
||||||
_alloc_ptr = &alloc;
|
_alloc_ptr = &alloc;
|
||||||
_suspend_ptr = &suspend;
|
_monitor_ptr = &monitor;
|
||||||
_resume_ptr = &resume;
|
|
||||||
_signal_ptr = &signal;
|
_signal_ptr = &signal;
|
||||||
_kernel_routine_scheduler_ptr = &kernel_routine_scheduler;
|
|
||||||
_malloc_heap_ptr = &malloc_heap;
|
_malloc_heap_ptr = &malloc_heap;
|
||||||
_config_accessor_ptr = &config_accessor;
|
_config_accessor_ptr = &config_accessor;
|
||||||
_pid = pid;
|
_pid = pid;
|
||||||
|
@ -35,7 +35,6 @@ namespace Libc {
|
|||||||
struct Current_time;
|
struct Current_time;
|
||||||
struct Current_real_time;
|
struct Current_real_time;
|
||||||
struct Clone_connection;
|
struct Clone_connection;
|
||||||
struct Kernel_routine_scheduler;
|
|
||||||
struct Watch;
|
struct Watch;
|
||||||
struct Signal;
|
struct Signal;
|
||||||
struct File_descriptor_allocator;
|
struct File_descriptor_allocator;
|
||||||
@ -126,8 +125,7 @@ namespace Libc {
|
|||||||
*/
|
*/
|
||||||
void init_fork(Genode::Env &, Config_accessor const &,
|
void init_fork(Genode::Env &, Config_accessor const &,
|
||||||
Genode::Allocator &heap, Heap &malloc_heap, int pid,
|
Genode::Allocator &heap, Heap &malloc_heap, int pid,
|
||||||
Suspend &, Resume &, Signal &, Kernel_routine_scheduler &,
|
Monitor &, Signal &, Binary_name const &);
|
||||||
Binary_name const &);
|
|
||||||
|
|
||||||
struct Reset_malloc_heap : Interface
|
struct Reset_malloc_heap : Interface
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <internal/suspend.h>
|
#include <internal/suspend.h>
|
||||||
#include <internal/resume.h>
|
#include <internal/resume.h>
|
||||||
#include <internal/select.h>
|
#include <internal/select.h>
|
||||||
#include <internal/kernel_routine.h>
|
|
||||||
#include <internal/current_time.h>
|
#include <internal/current_time.h>
|
||||||
#include <internal/kernel_timer_accessor.h>
|
#include <internal/kernel_timer_accessor.h>
|
||||||
#include <internal/watch.h>
|
#include <internal/watch.h>
|
||||||
@ -108,7 +107,6 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
Suspend,
|
Suspend,
|
||||||
Monitor,
|
Monitor,
|
||||||
Select,
|
Select,
|
||||||
Kernel_routine_scheduler,
|
|
||||||
Current_time,
|
Current_time,
|
||||||
Current_real_time,
|
Current_real_time,
|
||||||
Watch,
|
Watch,
|
||||||
@ -236,8 +234,6 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
|
|
||||||
Select_handler_base *_scheduled_select_handler = nullptr;
|
Select_handler_base *_scheduled_select_handler = nullptr;
|
||||||
|
|
||||||
Kernel_routine *_kernel_routine = nullptr;
|
|
||||||
|
|
||||||
void _resume_main() { _resume_main_once = true; }
|
void _resume_main() { _resume_main_once = true; }
|
||||||
|
|
||||||
Kernel_timer_accessor _timer_accessor { _env };
|
Kernel_timer_accessor _timer_accessor { _env };
|
||||||
@ -356,7 +352,7 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check.suspend() && !_kernel_routine)
|
if (!check.suspend())
|
||||||
return timeout_ms;
|
return timeout_ms;
|
||||||
|
|
||||||
if (timeout_ms > 0)
|
if (timeout_ms > 0)
|
||||||
@ -425,6 +421,7 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
/* _setjmp() returned directly -> switch to user stack and call application code */
|
/* _setjmp() returned directly -> switch to user stack and call application code */
|
||||||
|
|
||||||
if (_cloned) {
|
if (_cloned) {
|
||||||
|
_main_monitor_job->complete();
|
||||||
_switch_to_user();
|
_switch_to_user();
|
||||||
} else {
|
} else {
|
||||||
_state = USER;
|
_state = USER;
|
||||||
@ -438,22 +435,6 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
|
|
||||||
while ((!_app_returned)) {
|
while ((!_app_returned)) {
|
||||||
|
|
||||||
if (_kernel_routine) {
|
|
||||||
Kernel_routine &routine = *_kernel_routine;
|
|
||||||
|
|
||||||
/* the 'kernel_routine' may install another kernel routine */
|
|
||||||
_kernel_routine = nullptr;
|
|
||||||
routine.execute_in_kernel();
|
|
||||||
|
|
||||||
if (!_kernel_routine) {
|
|
||||||
_switch_to_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_kernel_routine) {
|
|
||||||
_env.ep().wait_and_dispatch_one_io_signal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispatch all pending I/O signals at once and execute
|
* Dispatch all pending I/O signals at once and execute
|
||||||
* monitors that may now become able to complete.
|
* monitors that may now become able to complete.
|
||||||
@ -521,7 +502,7 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
/*
|
/*
|
||||||
* Return to the application
|
* Return to the application
|
||||||
*/
|
*/
|
||||||
if (!_kernel_routine && _resume_main_once && !_setjmp(_kernel_context)) {
|
if (_resume_main_once && !_setjmp(_kernel_context)) {
|
||||||
_switch_to_user();
|
_switch_to_user();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -701,14 +682,6 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
|
|
||||||
void handle_io_progress() override;
|
void handle_io_progress() override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Kernel_routine_scheduler interface
|
|
||||||
*/
|
|
||||||
void register_kernel_routine(Kernel_routine &kernel_routine) override
|
|
||||||
{
|
|
||||||
_kernel_routine = &kernel_routine;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
** Access to kernel singleton **
|
** Access to kernel singleton **
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Interface executing code in the context of the libc kernel
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2019-09-18
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LIBC__INTERNAL__KERNEL_ROUTINE_H_
|
|
||||||
#define _LIBC__INTERNAL__KERNEL_ROUTINE_H_
|
|
||||||
|
|
||||||
/* libc-internal includes */
|
|
||||||
#include <internal/types.h>
|
|
||||||
|
|
||||||
namespace Libc {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class to be implemented by a kernel routine
|
|
||||||
*/
|
|
||||||
struct Kernel_routine : Interface
|
|
||||||
{
|
|
||||||
virtual void execute_in_kernel() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Kernel_routine_scheduler : Interface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Register routine to be called once on the next libc-kernel activation
|
|
||||||
*
|
|
||||||
* The specified routine is executed only once. For a repeated execution,
|
|
||||||
* the routine must call 'register_kernel_routine' with itself as
|
|
||||||
* argument.
|
|
||||||
*
|
|
||||||
* This mechanism is used by 'fork' to implement the blocking for the
|
|
||||||
* startup of a new child and for 'wait4'.
|
|
||||||
*/
|
|
||||||
virtual void register_kernel_routine(Kernel_routine &) = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _LIBC__INTERNAL__KERNEL_ROUTINE_H_ */
|
|
@ -348,6 +348,7 @@ void Libc::Kernel::_clone_state_from_parent()
|
|||||||
|
|
||||||
/* fetch user contex of the parent's application */
|
/* fetch user contex of the parent's application */
|
||||||
_clone_connection->memory_content(&_user_context, sizeof(_user_context));
|
_clone_connection->memory_content(&_user_context, sizeof(_user_context));
|
||||||
|
_clone_connection->memory_content(&_main_monitor_job, sizeof(_main_monitor_job));
|
||||||
_valid_user_context = true;
|
_valid_user_context = true;
|
||||||
|
|
||||||
_libc_env.libc_config().for_each_sub_node([&] (Xml_node node) {
|
_libc_env.libc_config().for_each_sub_node([&] (Xml_node node) {
|
||||||
@ -466,8 +467,8 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
|||||||
init_malloc(*_malloc_heap);
|
init_malloc(*_malloc_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_fork(_env, _libc_env, _heap, *_malloc_heap, _pid, *this, *this, _signal,
|
init_fork(_env, _libc_env, _heap, *_malloc_heap, _pid, *this, _signal,
|
||||||
*this, _binary_name);
|
_binary_name);
|
||||||
init_execve(_env, _heap, _user_stack, *this, _binary_name,
|
init_execve(_env, _heap, _user_stack, *this, _binary_name,
|
||||||
*file_descriptor_allocator());
|
*file_descriptor_allocator());
|
||||||
init_plugin(*this);
|
init_plugin(*this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user