libc: 'with_libc' mechanism to enter libc runtime
This commit extends an easy-to-use mechanism to allow Genode component code to enter/leave the libc application context. This is needed whenever low-level component code (like signal handlers or RPC functions) need to interact with potentially blocking libc I/O functions. Please note that this commit contains the API-level design only. The actual context switching code 'execute_in_application_context' is missing.
This commit is contained in:
parent
fdad5116dd
commit
3a65f0bba3
|
@ -21,50 +21,113 @@
|
||||||
#ifndef _INCLUDE__LIBC__COMPONENT_H_
|
#ifndef _INCLUDE__LIBC__COMPONENT_H_
|
||||||
#define _INCLUDE__LIBC__COMPONENT_H_
|
#define _INCLUDE__LIBC__COMPONENT_H_
|
||||||
|
|
||||||
|
#include <util/meta.h>
|
||||||
#include <vfs/file_system.h>
|
#include <vfs/file_system.h>
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/stdint.h>
|
#include <base/stdint.h>
|
||||||
|
|
||||||
|
namespace Libc { class Env; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to be provided by the component implementation
|
* Interface to be provided by the component implementation
|
||||||
*/
|
*/
|
||||||
|
class Libc::Env : public Genode::Env
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
virtual Genode::Xml_node _config_xml() const = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component configuration
|
||||||
|
*/
|
||||||
|
template <typename FUNC>
|
||||||
|
void config(FUNC const &func) const {
|
||||||
|
func(_config_xml()); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual File System configured for this component
|
||||||
|
*/
|
||||||
|
virtual Vfs::File_system &vfs() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace Libc { namespace Component {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return stack size of the component's initial entrypoint
|
||||||
|
*/
|
||||||
|
Genode::size_t stack_size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct component
|
||||||
|
*
|
||||||
|
* \param env extended interface to the component's execution environment
|
||||||
|
*/
|
||||||
|
void construct(Libc::Env &env);
|
||||||
|
} }
|
||||||
|
|
||||||
|
|
||||||
namespace Libc {
|
namespace Libc {
|
||||||
|
|
||||||
class Env : public Genode::Env
|
class Application_code {
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
virtual Genode::Xml_node _config_xml() const = 0;
|
protected:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper to distinguish void from non-void return type
|
||||||
|
*/
|
||||||
|
template <typename FUNC, typename RET>
|
||||||
|
void _execute(RET &ret_out, FUNC const &func) { ret_out = func(); }
|
||||||
|
|
||||||
|
template <typename FUNC>
|
||||||
|
void _execute(Genode::Meta::Empty &, FUNC const &func) { func(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
virtual void execute() = 0;
|
||||||
* Component configuration
|
|
||||||
*/
|
|
||||||
template <typename FUNC>
|
|
||||||
void config(FUNC const &func) const {
|
|
||||||
func(_config_xml()); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual File System configured for this component
|
|
||||||
*/
|
|
||||||
virtual Vfs::File_system &vfs() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Component {
|
void execute_in_application_context(Application_code &);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return stack size of the component's initial entrypoint
|
* Execute 'FUNC' lambda in the libc application context
|
||||||
*/
|
*
|
||||||
Genode::size_t stack_size();
|
* In order to invoke the libc's I/O functions (in particular 'select',
|
||||||
|
* 'read', 'write', or other functions like 'socket' that indirectly call
|
||||||
|
* them), the libc-calling application code must be executed under the
|
||||||
|
* supervision of the libc runtime. This is not the case for signal
|
||||||
|
* handlers or RPC functions that are executed in the context of the
|
||||||
|
* 'Genode::Entrypoint'. The 'with_libc' function allows such handlers to
|
||||||
|
* interact with the libc by deliberately subjecting the specified function
|
||||||
|
* ('func') to the libc runtime.
|
||||||
|
*/
|
||||||
|
template <typename FUNC>
|
||||||
|
auto with_libc(FUNC const &func)
|
||||||
|
-> typename Genode::Trait::Call_return
|
||||||
|
<typename Genode::Trait::Functor
|
||||||
|
<decltype(&FUNC::operator())>::Return_type>::Type
|
||||||
|
{
|
||||||
|
using Functor = Genode::Trait::Functor<decltype(&FUNC::operator())>;
|
||||||
|
using Return_type = typename Genode::Trait::Call_return<typename Functor::Return_type>::Type;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Construct component
|
* Implementation of the 'Application_code' interface that executes
|
||||||
*
|
* the code in the 'func' lambda.
|
||||||
* \param env extended interface to the component's execution environment
|
|
||||||
*/
|
*/
|
||||||
void construct(Libc::Env &env);
|
struct Application_code_func : Application_code
|
||||||
|
{
|
||||||
|
FUNC const &func;
|
||||||
|
Return_type retval;
|
||||||
|
void execute() override { _execute(retval, func); }
|
||||||
|
Application_code_func(FUNC const &func) : func(func) { }
|
||||||
|
} application_code_func { func };
|
||||||
|
|
||||||
|
execute_in_application_context(application_code_func);
|
||||||
|
|
||||||
|
return application_code_func.retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -933,7 +933,12 @@ _write T
|
||||||
_writev T
|
_writev T
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Public interface between Genode-component code and the libc runtime
|
||||||
|
#
|
||||||
_ZN4Libc9Component9constructERNS_3EnvE U
|
_ZN4Libc9Component9constructERNS_3EnvE U
|
||||||
|
_ZN4Libc30execute_in_application_contextERNS_16Application_codeE T
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Libc plugin interface
|
# Libc plugin interface
|
||||||
|
|
|
@ -664,6 +664,21 @@ void Libc::schedule_suspend(void (*suspended) ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Libc::execute_in_application_context(Libc::Application_code &app_code)
|
||||||
|
{
|
||||||
|
warning("executing code in application context, not implemented");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX missing: switch to/from libc app task
|
||||||
|
* XXX Should we detect nested calls?
|
||||||
|
*/
|
||||||
|
|
||||||
|
app_code.execute();
|
||||||
|
|
||||||
|
warning("leaving application context");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
** Component entry point **
|
** Component entry point **
|
||||||
***************************/
|
***************************/
|
||||||
|
|
Loading…
Reference in New Issue