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:
Norman Feske 2017-02-01 12:43:30 +01:00 committed by Christian Helmuth
parent fdad5116dd
commit 3a65f0bba3
3 changed files with 108 additions and 25 deletions

View File

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

View File

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

View File

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