lib/component: pass extended Libc::Env

Libc::Env is the Genode::Env interface extended to cover access
to the XML content of the 'config' ROM and a VFS instance. This
deduplicates the burden of components to attain and manage
these resources.

Fix #2217
Ref #1987
This commit is contained in:
Emery Hemingway 2017-01-03 14:33:55 +01:00 committed by Norman Feske
parent fc273f3840
commit 745eb89237
27 changed files with 216 additions and 146 deletions

View File

@ -254,4 +254,4 @@ struct Main
};
void Libc::Component::construct(Genode::Env &env) { static Main server(env); }
void Libc::Component::construct(Libc::Env &env) { static Main server(env); }

View File

@ -366,6 +366,6 @@ void Backdrop::Main::handle_sync()
extern "C" void _sigprocmask() { }
void Libc::Component::construct(Genode::Env &env) {
void Libc::Component::construct(Libc::Env &env) {
static Backdrop::Main application(env); }

View File

@ -292,5 +292,5 @@ void Menu_view::Main::_handle_frame_timer()
extern "C" void _sigprocmask() { }
void Libc::Component::construct(Genode::Env &env) { static Menu_view::Main main(env); }
void Libc::Component::construct(Libc::Env &env) { static Menu_view::Main main(env); }

View File

@ -317,4 +317,4 @@ void Decorator::Main::_handle_pointer_update()
}
void Libc::Component::construct(Genode::Env &env) { static Decorator::Main main(env); }
void Libc::Component::construct(Libc::Env &env) { static Decorator::Main main(env); }

View File

@ -107,4 +107,4 @@ struct Main
};
void Libc::Component::construct(Genode::Env &env) { static Main m(env); }
void Libc::Component::construct(Libc::Env &env) { static Main m(env); }

View File

@ -721,4 +721,4 @@ struct Main
};
void Libc::Component::construct(Genode::Env &env) { static Main inst(env); }
void Libc::Component::construct(Libc::Env &env) { static Main inst(env); }

View File

@ -21,28 +21,51 @@
#ifndef _INCLUDE__LIBC__COMPONENT_H_
#define _INCLUDE__LIBC__COMPONENT_H_
#include <vfs/file_system.h>
#include <base/env.h>
#include <base/stdint.h>
namespace Genode { struct Env; }
/**
* Interface to be provided by the component implementation
*/
namespace Libc { namespace Component {
namespace Libc {
/**
* Return stack size of the component's initial entrypoint
*/
Genode::size_t stack_size();
class Env : public Genode::Env
{
private:
/**
* Construct component
*
* \param env interface to the component's execution environment
*/
void construct(Genode::Env &env);
} }
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 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);
}
}
#endif /* _INCLUDE__LIBC__COMPONENT_H_ */

View File

@ -4,7 +4,7 @@
LIBS = libc-string libc-locale libc-stdlib libc-stdio libc-gen libc-gdtoa \
libc-inet libc-stdtime libc-regex libc-compat libc-setjmp libc-mem
LIBS += base config vfs
LIBS += base vfs
#
# Back end

View File

@ -933,7 +933,7 @@ _write T
_writev T
_ZN4Libc9Component9constructERN6Genode3EnvE U
_ZN4Libc9Component9constructERNS_3EnvE U
#
# Libc plugin interface

View File

@ -15,9 +15,8 @@ set config {
<start name="test-ldso">
<resource name="RAM" quantum="2M"/>
<config ld_bind_now="no" ld_verbose="no">
<libc stdout="/dev/log">
<vfs> <dir name="dev"> <log/> </dir> </vfs>
</libc>
<vfs> <dir name="dev"> <log/> </dir> </vfs>
<libc stdout="/dev/log"/>
</config>
</start>
</config>

View File

@ -22,9 +22,8 @@ install_config {
<start name="test-libc">
<resource name="RAM" quantum="4M"/>
<config>
<libc stdout="/dev/log">
<vfs> <dir name="dev"> <log/> </dir> </vfs>
</libc>
<vfs> <dir name="dev"> <log/> </dir> </vfs>
<libc stdout="/dev/log"/>
</config>
</start>
</config>

View File

@ -307,4 +307,4 @@ ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 irq, ACPI_OSD_HANDLER handler,
/* used by normal (no-printf-debug) target */
void Component::construct(Genode::Env &env) { static Acpica::Main main(env); }
/* used by debug target (using printf of libc) */
void Libc::Component::construct(Genode::Env &env) { static Acpica::Main main(env); }
void Libc::Component::construct(Libc::Env &env) { static Acpica::Main main(env); }

View File

@ -37,7 +37,7 @@ static inline void load_stylesheet()
extern int genode_argc;
extern char **genode_argv;
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
QApplication app(genode_argc, genode_argv);

View File

@ -57,7 +57,7 @@ struct Qt_launchpad_namespace::Local_env : Genode::Env
};
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
static Qt_launchpad_namespace::Local_env local_env(env);

View File

@ -13,11 +13,12 @@
/* Genode includes */
#include <base/component.h>
#include <base/printf.h>
#include <base/thread.h>
#include <base/rpc_server.h>
#include <base/rpc_client.h>
#include <base/heap.h>
#include <base/attached_rom_dataspace.h>
#include <vfs/dir_file_system.h>
/* libc includes */
#include <libc/component.h>
@ -44,7 +45,10 @@
} while (0)
namespace Libc { class Task; }
namespace Libc {
class Env_implementation;
class Task;
}
struct Task_resume
@ -54,6 +58,102 @@ struct Task_resume
};
class Libc::Env_implementation : public Libc::Env
{
private:
Genode::Env &_env;
Genode::Attached_rom_dataspace _config { _env, "config" };
Genode::Xml_node _vfs_config()
{
try { return _config.xml().sub_node("vfs"); }
catch (Genode::Xml_node::Nonexistent_sub_node) { }
try {
Genode::Xml_node node =
_config.xml().sub_node("libc").sub_node("vfs");
Genode::warning("'<config> <libc> <vfs/>' is deprecated, "
"please move to '<config> <vfs/>'");
return node;
}
catch (Genode::Xml_node::Nonexistent_sub_node) { }
return Genode::Xml_node("<vfs/>");
}
Vfs::Dir_file_system _vfs;
Genode::Xml_node _config_xml() const override {
return _config.xml(); };
public:
Env_implementation(Genode::Env &env, Genode::Allocator &alloc)
:
_env(env),
_vfs(_env, alloc, _vfs_config(),
Vfs::global_file_system_factory())
{ }
/*************************
** Libc::Env interface **
*************************/
Vfs::File_system &vfs() override {
return _vfs; }
/***************************
** Genode::Env interface **
***************************/
Parent &parent() override {
return _env.parent(); }
Ram_session &ram() override {
return _env.ram(); }
Cpu_session &cpu() override {
return _env.cpu(); }
Region_map &rm() override {
return _env.rm(); }
Pd_session &pd() override {
return _env.pd(); }
Entrypoint &ep() override {
return _env.ep(); }
Ram_session_capability ram_session_cap() override {
return _env.ram_session_cap(); }
Cpu_session_capability cpu_session_cap() override {
return _env.cpu_session_cap(); }
Pd_session_capability pd_session_cap() override {
return _env.pd_session_cap(); }
Id_space<Parent::Client> &id_space() override {
return _env.id_space(); }
Session_capability session(Parent::Service_name const &name,
Parent::Client::Id id,
Parent::Session_args const &args,
Affinity const &aff) override {
return _env.session(name, id, args, aff); }
void upgrade(Parent::Client::Id id,
Parent::Upgrade_args const &args) override {
return _env.upgrade(id, args); }
void close(Parent::Client::Id id) override {
return _env.close(id); }
};
/**
* Libc task
*
@ -68,12 +168,10 @@ class Libc::Task : public Genode::Rpc_object<Task_resume, Libc::Task>
{
private:
Genode::Env &_env;
/* XXX: this heap is only used by the Vfs_plugin */
Genode::Heap _heap { &_env.ram(), &_env.rm() };
Vfs_plugin _vfs { _env, _heap };
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Env_implementation _libc_env { _env, _heap };
Vfs_plugin _vfs { _libc_env, _heap };
/**
* Application context and execution state
@ -158,9 +256,11 @@ class Libc::Task : public Genode::Rpc_object<Task_resume, Libc::Task>
** Libc task implementation **
******************************/
extern "C" void wait_for_continue(void);
void Libc::Task::_app_entry(Task *task)
{
Libc::Component::construct(task->_env);
Libc::Component::construct(task->_libc_env);
/* returned from task - switch stack to libc and return to dispatch loop */
_longjmp(task->_libc_task, 1);

View File

@ -83,14 +83,6 @@ namespace Libc {
return Genode::config()->xml_node().sub_node("libc");
}
Genode::Xml_node vfs_config() __attribute__((weak));
Genode::Xml_node vfs_config()
{
return Libc::config().sub_node("vfs");
}
class Config_attr
{
private:
@ -110,38 +102,6 @@ namespace Libc {
char const *string() const { return _buf; }
};
char const *initial_cwd() __attribute__((weak));
char const *initial_cwd()
{
static Config_attr initial_cwd("cwd", "/");
return initial_cwd.string();
}
char const *config_stdin() __attribute__((weak));
char const *config_stdin()
{
static Config_attr stdin("stdin", "");
return stdin.string();
}
char const *config_stdout() __attribute__((weak));
char const *config_stdout()
{
static Config_attr stdout("stdout", "");
return stdout.string();
}
char const *config_stderr() __attribute__((weak));
char const *config_stderr()
{
static Config_attr stderr("stderr", "");
return stderr.string();
}
char const *config_rtc() __attribute__((weak));
char const *config_rtc()
{

View File

@ -15,10 +15,7 @@
#define _LIBC_VFS__PLUGIN_H_
/* Genode includes */
#include <base/env.h>
#include <base/printf.h>
#include <vfs/dir_file_system.h>
#include <os/config.h>
#include <libc/component.h>
/* libc includes */
#include <fcntl.h>
@ -28,19 +25,6 @@
#include <libc-plugin/plugin.h>
#include <libc-plugin/fd_alloc.h>
namespace Libc {
Genode::Xml_node config();
Genode::Xml_node vfs_config();
char const *initial_cwd();
char const *config_stdin();
char const *config_stdout();
char const *config_stderr();
}
namespace Libc { class Vfs_plugin; }
@ -50,41 +34,39 @@ class Libc::Vfs_plugin : public Libc::Plugin
Genode::Allocator &_alloc;
Vfs::Dir_file_system _root_dir;
Vfs::File_system &_root_dir;
Genode::Xml_node _vfs_config()
void _open_stdio(Genode::Xml_node const &node, char const *attr,
int libc_fd, unsigned flags)
{
try {
return vfs_config();
} catch (...) {
PINF("no VFS configured");
return Genode::Xml_node("<vfs/>");
}
}
Genode::String<Vfs::MAX_PATH_LEN> path;
struct stat out_stat;
void _open_stdio(int libc_fd, char const *path, unsigned flags)
{
struct stat out_stat;
if (::strlen(path) == 0 || stat(path, &out_stat) != 0)
return;
node.attribute(attr).value(&path);
Libc::File_descriptor *fd = open(path, flags, libc_fd);
if (fd->libc_fd != libc_fd) {
PERR("could not allocate fd %d for %s, got fd %d",
libc_fd, path, fd->libc_fd);
close(fd);
return;
}
if (stat(path.string(), &out_stat) != 0)
return;
/*
* We need to manually register the path. Normally this is done
* by '_open'. But we call the local 'open' function directly
* because we want to explicitly specify the libc fd ID.
*
* We have to allocate the path from the libc (done via 'strdup')
* such that the path can be freed when an stdio fd is closed.
*/
fd->fd_path = strdup(path);
Libc::File_descriptor *fd = open(path.string(), flags, libc_fd);
if (fd->libc_fd != libc_fd) {
Genode::error("could not allocate fd ",libc_fd," for ",path,", "
"got fd ",fd->libc_fd);
close(fd);
return;
}
/*
* We need to manually register the path. Normally this is done
* by '_open'. But we call the local 'open' function directly
* because we want to explicitly specify the libc fd ID.
*
* We have to allocate the path from the libc (done via 'strdup')
* such that the path can be freed when an stdio fd is closed.
*/
fd->fd_path = strdup(path.string());
} catch (Xml_node::Nonexistent_attribute) { }
}
public:
@ -92,19 +74,26 @@ class Libc::Vfs_plugin : public Libc::Plugin
/**
* Constructor
*/
Vfs_plugin(Genode::Env &env, Genode::Allocator &alloc)
Vfs_plugin(Libc::Env &env, Genode::Allocator &alloc)
:
_alloc(alloc),
_root_dir(env, _alloc, _vfs_config(),
Vfs::global_file_system_factory())
_alloc(alloc), _root_dir(env.vfs())
{
if (_root_dir.num_dirent("/")) {
chdir(initial_cwd());
using Genode::Xml_node;
_open_stdio(0, config_stdin(), O_RDONLY);
_open_stdio(1, config_stdout(), O_WRONLY);
_open_stdio(2, config_stderr(), O_WRONLY);
}
if (_root_dir.num_dirent("/"))
env.config([&] (Xml_node const &top) {
Xml_node const node = top.sub_node("libc");
try {
Genode::String<Vfs::MAX_PATH_LEN> path;
node.attribute("cwd").value(&path);
chdir(path.string());
} catch (Xml_node::Nonexistent_attribute) { }
_open_stdio(node, "stdin", 0, O_RDONLY);
_open_stdio(node, "stdout", 1, O_WRONLY);
_open_stdio(node, "stderr", 2, O_WRONLY);
});
}
~Vfs_plugin() { }

View File

@ -26,7 +26,7 @@ extern char **genode_envp;
extern "C" int main(int argc, char ** argv, char **envp);
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
exit(main(genode_argc, genode_argv, genode_envp));
}

View File

@ -543,7 +543,7 @@ struct File_system::Main
** Component **
***************/
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
static File_system::Main inst(env.ep());
}

View File

@ -185,7 +185,7 @@ static void test_shared_object_api(Env &env, Allocator &alloc)
/**
* Main function of LDSO test
*/
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
static Heap heap(env.ram(), env.rm());

View File

@ -13,4 +13,4 @@
#include <libc/component.h>
void Libc::Component::construct(Genode::Env &) { }
void Libc::Component::construct(Libc::Env &env) { }

View File

@ -154,7 +154,7 @@ struct Test::Main
};
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
static Test::Main server(env.ep());
}

View File

@ -33,7 +33,7 @@ extern "C" int gdbserver_main(int argc, const char *argv[]);
extern Genode::Env *genode_env;
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
genode_env = &env;

View File

@ -286,7 +286,7 @@ struct Main
** Component **
***************/
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
static Main server(env.ep());
}

View File

@ -1262,4 +1262,4 @@ void Component::construct(Genode::Env &env)
/**
* Support for the noux/net version
*/
void Libc::Component::construct(Genode::Env &env) { Component::construct(env); }
void Libc::Component::construct(Libc::Env &env) { Component::construct(env); }

View File

@ -207,7 +207,7 @@ Genode::Env &genode_env()
}
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
/* make Genode environment accessible via the global 'genode_env()' */
genode_env_ptr = &env;

View File

@ -238,7 +238,7 @@ Genode::Env &genode_env()
}
void Libc::Component::construct(Genode::Env &env)
void Libc::Component::construct(Libc::Env &env)
{
/* make Genode environment accessible via the global 'genode_env()' */
genode_env_ptr = &env;