mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
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_
|
||||
#define _INCLUDE__LIBC__COMPONENT_H_
|
||||
|
||||
#include <util/meta.h>
|
||||
#include <vfs/file_system.h>
|
||||
#include <base/env.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Libc { class Env; }
|
||||
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
class Env : public Genode::Env
|
||||
{
|
||||
private:
|
||||
class Application_code {
|
||||
|
||||
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:
|
||||
|
||||
/**
|
||||
* 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;
|
||||
virtual void execute() = 0;
|
||||
};
|
||||
|
||||
namespace Component {
|
||||
void execute_in_application_context(Application_code &);
|
||||
|
||||
/**
|
||||
* Return stack size of the component's initial entrypoint
|
||||
*/
|
||||
Genode::size_t stack_size();
|
||||
/**
|
||||
* Execute 'FUNC' lambda in the libc application context
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* \param env extended interface to the component's execution environment
|
||||
/*
|
||||
* Implementation of the 'Application_code' interface that executes
|
||||
* the code in the 'func' lambda.
|
||||
*/
|
||||
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
|
||||
|
||||
|
||||
#
|
||||
# Public interface between Genode-component code and the libc runtime
|
||||
#
|
||||
_ZN4Libc9Component9constructERNS_3EnvE U
|
||||
_ZN4Libc30execute_in_application_contextERNS_16Application_codeE T
|
||||
|
||||
|
||||
#
|
||||
# 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 **
|
||||
***************************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user