Handle lifetime of dynamic allocations in Noux

This commit is contained in:
Norman Feske 2012-02-25 20:41:59 +01:00
parent 4e3be6b146
commit a9152ff412
14 changed files with 453 additions and 288 deletions

View File

@ -38,6 +38,9 @@
#include <termios.h>
enum { verbose = false };
void *operator new (size_t, void *ptr) { return ptr; }
@ -166,13 +169,15 @@ static bool serialize_string_array(char const * const * array, char *dst, Genode
extern "C" int execve(const char *filename, char *const argv[],
char *const envp[])
{
PDBG("filename=%s", filename);
if (verbose) {
PDBG("filename=%s", filename);
for (int i = 0; argv[i]; i++)
PDBG("argv[%d]='%s'", i, argv[i]);
for (int i = 0; argv[i]; i++)
PDBG("argv[%d]='%s'", i, argv[i]);
for (int i = 0; envp[i]; i++)
PDBG("envp[%d]='%s'", i, envp[i]);
for (int i = 0; envp[i]; i++)
PDBG("envp[%d]='%s'", i, envp[i]);
}
Genode::strncpy(sysio()->execve_in.filename, filename, sizeof(sysio()->execve_in.filename));
if (!serialize_string_array(argv, sysio()->execve_in.args,
@ -420,6 +425,33 @@ extern "C" int gettimeofday(struct timeval *tv, struct timezone *tz)
}
/*********************
** Signal handling **
*********************/
extern "C" int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
/* XXX todo */
errno = ENOSYS;
return -1;
}
extern "C" int _sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
return sigprocmask(how, set, oldset);
}
extern "C" int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact)
{
/* XXX todo */
errno = ENOSYS;
return -1;
}
/*********************
** File operations **
*********************/

View File

@ -15,7 +15,6 @@
#define _NOUX__CHILD_H_
/* Genode includes */
#include <init/child_policy.h>
#include <base/signal.h>
#include <base/semaphore.h>
#include <cap_session/cap_session.h>
@ -28,10 +27,9 @@
#include <noux_session/capability.h>
#include <args.h>
#include <environment.h>
#include <local_rm_service.h>
#include <ram_session_component.h>
#include <cpu_session_component.h>
#include <child_policy.h>
namespace Noux {
@ -118,99 +116,9 @@ namespace Noux {
};
class Family_member : public List<Family_member>::Element
{
private:
int const _pid;
Lock _lock;
List<Family_member> _list;
Family_member * const _parent;
bool _has_exited;
int _exit_status;
Semaphore _wait4_blocker;
void _wakeup_wait4()
{
_wait4_blocker.up();
}
public:
Family_member(int pid, Family_member *parent)
: _pid(pid), _parent(parent), _has_exited(false), _exit_status(0)
{ }
virtual ~Family_member() { }
int pid() const { return _pid; }
Family_member *parent() { return _parent; }
int exit_status() const { return _exit_status; }
/**
* Called by the parent at creation time of the process
*/
void insert(Family_member *member)
{
Lock::Guard guard(_lock);
_list.insert(member);
}
/**
* Called by the parent from the return path of the wait4 syscall
*/
void remove(Family_member *member)
{
Lock::Guard guard(_lock);
_list.remove(member);
}
/**
* Tell the parent that we exited
*/
void wakeup_parent(int exit_status)
{
_exit_status = exit_status;
_has_exited = true;
if (_parent)
_parent->_wakeup_wait4();
}
Family_member *poll4()
{
Lock::Guard guard(_lock);
/* check if any of our children has exited */
Family_member *curr = _list.first();
for (; curr; curr = curr->next()) {
if (curr->_has_exited)
return curr;
}
return 0;
}
/**
* Wait for the exit of any of our children
*/
Family_member *wait4()
{
for (;;) {
Family_member *result = poll4();
if (result)
return result;
_wait4_blocker.down();
}
}
};
class Child : private Child_policy,
public Rpc_object<Session>,
public File_descriptor_registry,
public Family_member
class Child : public Rpc_object<Session>,
public File_descriptor_registry,
public Family_member
{
private:
@ -221,9 +129,6 @@ namespace Noux {
*/
Semaphore _blocker;
enum { MAX_NAME_LEN = 64 };
char _name[MAX_NAME_LEN];
Child_exit_dispatcher _exit_dispatcher;
Signal_context_capability _exit_context_cap;
@ -244,12 +149,12 @@ namespace Noux {
* Entrypoint used to serve the RPC interfaces of the
* locally-provided services
*/
Rpc_entrypoint &ep;
Rpc_entrypoint &ep;
/**
* Registry of dataspaces owned by the Noux process
*/
Dataspace_registry ds_registry;
Dataspace_registry ds_registry;
/**
* Locally-provided services for accessing platform resources
@ -293,15 +198,6 @@ namespace Noux {
*/
Dataspace_capability const _binary_ds;
Genode::Child _child;
Service_registry * const _parent_services;
Init::Child_policy_enforce_labeling _labeling_policy;
Init::Child_policy_provide_rom_file _binary_policy;
Init::Child_policy_provide_rom_file _args_policy;
Init::Child_policy_provide_rom_file _env_policy;
enum { PAGE_SIZE = 4096, PAGE_MASK = ~(PAGE_SIZE - 1) };
enum { SYSIO_DS_SIZE = PAGE_MASK & (sizeof(Sysio) + PAGE_SIZE - 1) };
@ -310,25 +206,12 @@ namespace Noux {
Session_capability const _noux_session_cap;
struct Local_noux_service : public Service
{
Genode::Session_capability _cap;
Local_noux_service _local_noux_service;
Local_rm_service _local_rm_service;
Service_registry &_parent_services;
/**
* Constructor
*
* \param cap capability to return on session requests
*/
Local_noux_service(Genode::Session_capability cap)
: Service(service_name()), _cap(cap) { }
Genode::Session_capability session(const char *args) { return _cap; }
void upgrade(Genode::Session_capability, const char *args) { }
void close(Genode::Session_capability) { }
} _local_noux_service;
Local_rm_service _local_rm_service;
Child_policy _child_policy;
Genode::Child _child;
/**
* Exception type for failed file-descriptor lookup
@ -375,7 +258,7 @@ namespace Noux {
Args const &args,
char const *env,
Cap_session *cap_session,
Service_registry *parent_services,
Service_registry &parent_services,
Rpc_entrypoint &resources_ep,
bool forked)
:
@ -393,33 +276,30 @@ namespace Noux {
_vfs(vfs),
_binary_ds(forked ? Dataspace_capability()
: vfs->dataspace_from_file(name)),
_child(_binary_ds, _resources.ram.cap(), _resources.cpu.cap(),
_resources.rm.cap(), &_entrypoint, this),
_parent_services(parent_services),
_labeling_policy(_name),
_binary_policy("binary", _binary_ds, &_entrypoint),
_args_policy( "args", _args.cap(), &_entrypoint),
_env_policy( "env", _env.cap(), &_entrypoint),
_sysio_ds(Genode::env()->ram_session(), SYSIO_DS_SIZE),
_sysio(_sysio_ds.local_addr<Sysio>()),
_noux_session_cap(Session_capability(_entrypoint.manage(this))),
_local_noux_service(_noux_session_cap),
_local_rm_service(_entrypoint, _resources.ds_registry)
_local_rm_service(_entrypoint, _resources.ds_registry),
_parent_services(parent_services),
_child_policy(name, _binary_ds, _args.cap(), _env.cap(),
_entrypoint, _local_noux_service,
_local_rm_service, _parent_services,
*this, _exit_context_cap, _resources.ram),
_child(_binary_ds, _resources.ram.cap(), _resources.cpu.cap(),
_resources.rm.cap(), &_entrypoint, &_child_policy)
{
_args.dump();
strncpy(_name, name, sizeof(_name));
}
~Child()
{
PDBG("Destructing child %p", this);
_sig_rec->dissolve(&_execve_cleanup_dispatcher);
_sig_rec->dissolve(&_exit_dispatcher);
/* XXX _binary_ds */
_entrypoint.dissolve(this);
_vfs->release_dataspace_for_file(_child_policy.name(), _binary_ds);
}
void start() { _entrypoint.activate(); }
@ -439,61 +319,6 @@ namespace Noux {
Dataspace_registry &ds_registry() { return _resources.ds_registry; }
/****************************
** Child_policy interface **
****************************/
const char *name() const { return _name; }
Service *resolve_session_request(const char *service_name,
const char *args)
{
Service *service = 0;
/* check for local ROM file requests */
if ((service = _args_policy.resolve_session_request(service_name, args))
|| (service = _env_policy.resolve_session_request(service_name, args))
|| (service = _binary_policy.resolve_session_request(service_name, args)))
return service;
/* check for locally implemented noux service */
if (strcmp(service_name, Session::service_name()) == 0)
return &_local_noux_service;
/*
* Check for the creation of an RM session, which is used by
* the dynamic linker to manually manage a part of the address
* space.
*/
if (strcmp(service_name, Rm_session::service_name()) == 0)
return &_local_rm_service;
return _parent_services->find(service_name);
}
void filter_session_args(const char *service,
char *args, size_t args_len)
{
_labeling_policy.filter_session_args(service, args, args_len);
}
void exit(int exit_value)
{
PINF("child %s exited with exit value %d", _name, exit_value);
wakeup_parent(exit_value);
/* handle exit of the init process */
if (parent() == 0)
Signal_transmitter(_exit_context_cap).submit();
}
Ram_session *ref_ram_session()
{
return &_resources.ram;
}
/****************************
** Noux session interface **
****************************/

View File

@ -0,0 +1,125 @@
/*
* \brief Noux child policy
* \author Norman Feske
* \date 2012-02-25
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _NOUX__CHILD_POLICY_H_
#define _NOUX__CHILD_POLICY_H_
/* Genode includes */
#include <init/child_policy.h>
/* Noux includes */
#include <family_member.h>
#include <local_noux_service.h>
#include <local_rm_service.h>
namespace Noux {
class Child_policy : public Genode::Child_policy
{
private:
enum { NAME_MAX_LEN = 128 };
char _name_buf[NAME_MAX_LEN];
char const *_name;
Init::Child_policy_enforce_labeling _labeling_policy;
Init::Child_policy_provide_rom_file _binary_policy;
Init::Child_policy_provide_rom_file _args_policy;
Init::Child_policy_provide_rom_file _env_policy;
Local_noux_service &_local_noux_service;
Local_rm_service &_local_rm_service;
Service_registry &_parent_services;
Family_member &_family_member;
Signal_context_capability _exit_context_cap;
Ram_session &_ref_ram_session;
public:
Child_policy(char const *name,
Dataspace_capability binary_ds,
Dataspace_capability args_ds,
Dataspace_capability env_ds,
Rpc_entrypoint &entrypoint,
Local_noux_service &local_noux_service,
Local_rm_service &local_rm_service,
Service_registry &parent_services,
Family_member &family_member,
Signal_context_capability exit_context_cap,
Ram_session &ref_ram_session)
:
_name(strncpy(_name_buf, name, sizeof(_name_buf))),
_labeling_policy(_name),
_binary_policy("binary", binary_ds, &entrypoint),
_args_policy( "args", args_ds, &entrypoint),
_env_policy( "env", env_ds, &entrypoint),
_local_noux_service(local_noux_service),
_local_rm_service(local_rm_service),
_parent_services(parent_services),
_family_member(family_member),
_exit_context_cap(exit_context_cap),
_ref_ram_session(ref_ram_session)
{ }
const char *name() const { return _name; }
Service *resolve_session_request(const char *service_name,
const char *args)
{
Service *service = 0;
/* check for local ROM file requests */
if ((service = _args_policy.resolve_session_request(service_name, args))
|| (service = _env_policy.resolve_session_request(service_name, args))
|| (service = _binary_policy.resolve_session_request(service_name, args)))
return service;
/* check for locally implemented noux service */
if (strcmp(service_name, Session::service_name()) == 0)
return &_local_noux_service;
/*
* Check for the creation of an RM session, which is used by
* the dynamic linker to manually manage a part of the address
* space.
*/
if (strcmp(service_name, Rm_session::service_name()) == 0)
return &_local_rm_service;
return _parent_services.find(service_name);
}
void filter_session_args(const char *service,
char *args, size_t args_len)
{
_labeling_policy.filter_session_args(service, args, args_len);
}
void exit(int exit_value)
{
PINF("child %s exited with exit value %d", _name, exit_value);
_family_member.wakeup_parent(exit_value);
/* handle exit of the init process */
if (_family_member.parent() == 0)
Signal_transmitter(_exit_context_cap).submit();
}
Ram_session *ref_ram_session()
{
return &_ref_ram_session;
}
};
}
#endif /* _NOUX__CHILD_POLICY_H_ */

View File

@ -15,20 +15,12 @@
#define _NOUX__DATASPACE_REGISTRY_H_
/* Genode includes */
#include <base/object_pool.h>
#include <base/rpc_server.h>
namespace Noux {
using namespace Genode;
/*
* XXX not used yet
*/
struct Dataspace_destroyer
{
virtual void destroy(Dataspace_capability) = 0;
};
class Dataspace_registry;
@ -39,19 +31,18 @@ namespace Noux {
size_t _size;
Dataspace_capability _ds_cap;
Dataspace_destroyer &_destroyer;
public:
Dataspace_info(Dataspace_capability ds_cap,
Dataspace_destroyer &destroyer)
Dataspace_info(Dataspace_capability ds_cap)
:
Object_pool<Dataspace_info>::Entry(ds_cap),
_size(Dataspace_client(ds_cap).size()),
_ds_cap(ds_cap),
_destroyer(destroyer)
_ds_cap(ds_cap)
{ }
virtual ~Dataspace_info() { }
size_t size() const { return _size; }
Dataspace_capability ds_cap() const { return _ds_cap; }
@ -67,7 +58,6 @@ namespace Noux {
* \return capability for the new dataspace
*/
virtual Dataspace_capability fork(Ram_session_capability ram,
Dataspace_destroyer &destroyer,
Dataspace_registry &ds_registry,
Rpc_entrypoint &ep) = 0;
@ -79,8 +69,6 @@ namespace Noux {
* \param len length of source buffer in bytes
*/
virtual void poke(addr_t dst_offset, void const *src, size_t len) = 0;
Dataspace_destroyer &destroyer() { return _destroyer; }
};
@ -92,6 +80,26 @@ namespace Noux {
public:
~Dataspace_registry()
{
/*
* At the time the destructor is called, most 'Dataspace_info'
* objects are expected to be gone already because
* 'Child::_resources' and 'Child::_child' are destructed
* before the 'Child::_ds_registry'. However, RM dataspaces
* created via 'Rm_dataspace_info::fork', are not handled by
* those destructors. So we have to clean them up here.
*/
for (;;) {
Dataspace_info *info = _pool.first();
if (!info)
return;
_pool.remove(info);
destroy(Genode::env()->heap(), info);
}
}
void insert(Dataspace_info *info)
{
_pool.insert(info);

View File

@ -30,6 +30,7 @@ namespace Noux {
struct Directory_service
{
virtual Genode::Dataspace_capability dataspace(char const *path) = 0;
virtual void release(Genode::Dataspace_capability) = 0;
virtual Vfs_handle *open(Sysio *sysio, char const *path) = 0;

View File

@ -0,0 +1,109 @@
/*
* \brief Helper for handling the relationship between Noux processes
* \author Norman Feske
* \date 2012-02-25
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _NOUX__FAMILY_MEMBER_H_
#define _NOUX__FAMILY_MEMBER_H_
/* Genode includes */
#include <util/list.h>
#include <base/lock.h>
namespace Noux {
class Family_member : public List<Family_member>::Element
{
private:
int const _pid;
Lock _lock;
List<Family_member> _list;
Family_member * const _parent;
bool _has_exited;
int _exit_status;
Semaphore _wait4_blocker;
void _wakeup_wait4() { _wait4_blocker.up(); }
public:
Family_member(int pid, Family_member *parent)
: _pid(pid), _parent(parent), _has_exited(false), _exit_status(0)
{ }
virtual ~Family_member() { }
int pid() const { return _pid; }
Family_member *parent() { return _parent; }
int exit_status() const { return _exit_status; }
/**
* Called by the parent at creation time of the process
*/
void insert(Family_member *member)
{
Lock::Guard guard(_lock);
_list.insert(member);
}
/**
* Called by the parent from the return path of the wait4 syscall
*/
void remove(Family_member *member)
{
Lock::Guard guard(_lock);
_list.remove(member);
}
/**
* Tell the parent that we exited
*/
void wakeup_parent(int exit_status)
{
_exit_status = exit_status;
_has_exited = true;
if (_parent)
_parent->_wakeup_wait4();
}
Family_member *poll4()
{
Lock::Guard guard(_lock);
/* check if any of our children has exited */
Family_member *curr = _list.first();
for (; curr; curr = curr->next()) {
if (curr->_has_exited)
return curr;
}
return 0;
}
/**
* Wait for the exit of any of our children
*/
Family_member *wait4()
{
for (;;) {
Family_member *result = poll4();
if (result)
return result;
_wait4_blocker.down();
}
}
};
}
#endif /* _NOUX__FAMILY_MEMBER_H_ */

View File

@ -0,0 +1,42 @@
/*
* \brief Locally-provided Noux service
* \author Norman Feske
* \date 2011-02-17
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _NOUX__LOCAL_NOUX_SERVICE_H_
#define _NOUX__LOCAL_NOUX_SERVICE_H_
/* Genode includes */
#include <base/service.h>
namespace Noux {
using namespace Genode;
struct Local_noux_service : public Service
{
Genode::Session_capability _cap;
/**
* Constructor
*
* \param cap capability to return on session requests
*/
Local_noux_service(Genode::Session_capability cap)
: Service(Session::service_name()), _cap(cap) { }
Genode::Session_capability session(const char *args) { return _cap; }
void upgrade(Genode::Session_capability, const char *args) { }
void close(Genode::Session_capability) { }
};
}
#endif /* _NOUX__LOCAL_NOUX_SERVICE_H_ */

View File

@ -30,38 +30,52 @@ namespace Noux {
{
private:
struct Dummy_destroyer : Dataspace_destroyer
{
void destroy(Dataspace_capability) { }
} _dummy_destroyer;
Rm_session_component &_sub_rm;
Rm_session_component * const _sub_rm;
Rpc_entrypoint &_ep;
Rm_session_capability _rm_cap;
public:
Rm_dataspace_info(Rm_session_component &sub_rm)
/**
* Constructor
*
* \param sub_rm pointer to 'Rm_session_component' that belongs
* to the 'Rm_dataspace_info' object
* \param ep entrypoint to manage the 'Rm_session_component'
*
* The ownership of the pointed-to object gets transferred to the
* 'Rm_dataspace_info' object. I.e., 'sub_rm' will get destructed
* on the destruction of its corresponding 'Rm_dataspace_info'
* object. Also, 'Rm_dataspace_info' takes care of associating
* 'sub_rm' with 'ep'.
*/
Rm_dataspace_info(Rm_session_component *sub_rm,
Rpc_entrypoint &ep)
:
Dataspace_info(sub_rm.dataspace(), _dummy_destroyer),
_sub_rm(sub_rm)
Dataspace_info(sub_rm->dataspace()),
_sub_rm(sub_rm), _ep(ep), _rm_cap(_ep.manage(_sub_rm))
{ }
~Rm_dataspace_info()
{
_ep.dissolve(_sub_rm);
destroy(Genode::env()->heap(), _sub_rm);
}
Rm_session_capability rm_cap() { return _rm_cap; }
Dataspace_capability fork(Ram_session_capability ram,
Dataspace_destroyer &,
Dataspace_registry &ds_registry,
Rpc_entrypoint &ep)
{
Rm_session_component *new_sub_rm =
new Rm_session_component(ds_registry, 0, size());
Rm_session_capability rm_cap = ep.manage(new_sub_rm);
Rm_dataspace_info *rm_info = new Rm_dataspace_info(new_sub_rm, ep);
/*
* XXX Where to dissolve the RM session?
*/
_sub_rm->replay(ram, rm_info->rm_cap(), ds_registry, ep);
_sub_rm.replay(ram, rm_cap, ds_registry, ep);
ds_registry.insert(new Rm_dataspace_info(*new_sub_rm));
ds_registry.insert(rm_info);
return new_sub_rm->dataspace();
}
@ -72,7 +86,7 @@ namespace Noux {
PERR("illegal attemt to write beyond RM boundary");
return;
}
_sub_rm.poke(dst_offset, src, len);
_sub_rm->poke(dst_offset, src, len);
}
};
@ -100,18 +114,34 @@ namespace Noux {
Rm_session_component *rm =
new Rm_session_component(_ds_registry, start, size);
Genode::Session_capability cap = _ep.manage(rm);
_ds_registry.insert(new Rm_dataspace_info(*rm));
return cap;
Rm_dataspace_info *info = new Rm_dataspace_info(rm, _ep);
_ds_registry.insert(info);
return info->rm_cap();
}
void upgrade(Genode::Session_capability, const char *args) { }
void close(Genode::Session_capability)
void close(Genode::Session_capability session)
{
PWRN("Local_rm_service::close not implemented, leaking memory");
Rm_session_component *rm_session =
dynamic_cast<Rm_session_component *>(_ep.obj_by_cap(session));
if (!rm_session) {
PWRN("Unexpected call of close with non-RM-session argument");
return;
}
/* use RM dataspace as key to obtain the dataspace info object */
Dataspace_capability ds_cap = rm_session->dataspace();
/* release dataspace info */
Dataspace_info *info = _ds_registry.lookup_info(ds_cap);
if (info) {
_ds_registry.remove(info);
destroy(Genode::env()->heap(), info);
} else {
PWRN("Could not lookup dataspace info for local RM session");
}
}
};
}

View File

@ -176,6 +176,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
_assign_io_channels_to(child);
/* signal main thread to remove ourself */
PINF("submit signal to _execve_cleanup_context_cap");
Genode::Signal_transmitter(_execve_cleanup_context_cap).submit();
/* start executing the new process */
@ -294,7 +295,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
* unique name that includes the PID instead of just
* reusing the name of the parent.
*/
Child *child = new Child(name(),
Child *child = new Child(_child_policy.name(),
this,
new_pid,
_sig_rec,
@ -342,6 +343,11 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
/* destroy 'Noux::Child' */
destroy(Genode::env()->heap(), exited);
PINF("quota: avail=%zd, used=%zd",
Genode::env()->ram_session()->avail(),
Genode::env()->ram_session()->used());
} else {
_sysio->wait4_out.pid = 0;
_sysio->wait4_out.status = 0;
@ -519,7 +525,7 @@ int main(int argc, char **argv)
args_of_init_process(),
env_string_of_init_process(),
&cap,
&parent_services,
parent_services,
resources_ep,
false);

View File

@ -24,7 +24,7 @@
#define _NOUX__RAM_SESSION_COMPONENT_H_
/* Genode includes */
#include <ram_session/capability.h>
#include <ram_session/client.h>
#include <base/rpc_server.h>
#include <base/env.h>
@ -38,12 +38,10 @@ namespace Noux {
struct Ram_dataspace_info : Dataspace_info,
List<Ram_dataspace_info>::Element
{
Ram_dataspace_info(Ram_dataspace_capability ds_cap,
Dataspace_destroyer &destroyer)
: Dataspace_info(ds_cap, destroyer) { }
Ram_dataspace_info(Ram_dataspace_capability ds_cap)
: Dataspace_info(ds_cap) { }
Dataspace_capability fork(Ram_session_capability ram,
Dataspace_destroyer &destroyer,
Dataspace_registry &,
Rpc_entrypoint &)
{
@ -101,8 +99,7 @@ namespace Noux {
};
class Ram_session_component : public Rpc_object<Ram_session>,
public Dataspace_destroyer
class Ram_session_component : public Rpc_object<Ram_session>
{
private:
@ -136,19 +133,6 @@ namespace Noux {
}
/***********************************
** Dataspace_destroyer interface **
***********************************/
/*
* XXX not used yet
*/
void destroy(Dataspace_capability ds)
{
free(static_cap_cast<Ram_dataspace>(ds));
}
/***************************
** Ram_session interface **
***************************/
@ -158,7 +142,7 @@ namespace Noux {
Ram_dataspace_capability ds_cap = env()->ram_session()->alloc(size);
Ram_dataspace_info *ds_info = new (env()->heap())
Ram_dataspace_info(ds_cap, *this);
Ram_dataspace_info(ds_cap);
_used_quota += ds_info->size();

View File

@ -105,16 +105,6 @@ namespace Noux {
Dataspace_registry &ds_registry,
Rpc_entrypoint &ep)
{
/*
* XXX remove this
*/
struct Dummy_destroyer : Dataspace_destroyer
{
void destroy(Dataspace_capability) { }
};
static Dummy_destroyer dummy_destroyer;
for (Region *curr = _regions.first(); curr; curr = curr->next()) {
Dataspace_capability ds;
@ -123,11 +113,7 @@ namespace Noux {
if (info) {
/*
* XXX Using 'this' as destroyer may be false, the
* destroyer should better correspond to dst_ram.
*/
ds = info->fork(dst_ram, dummy_destroyer, ds_registry, ep);
ds = info->fork(dst_ram, ds_registry, ep);
/*
* XXX We could detect dataspaces that are attached
@ -148,7 +134,6 @@ namespace Noux {
* like to detect unexpected dataspaces.
*/
ds = curr->ds;
PWRN("replay: unknown dataspace type, assume ROM");
}
if (!ds.valid()) {

View File

@ -274,19 +274,25 @@ namespace Noux {
}
try {
Attached_ram_dataspace *ds = new (env()->heap())
Attached_ram_dataspace(env()->ram_session(), record->size());
Ram_dataspace_capability ds_cap =
env()->ram_session()->alloc(record->size());
PDBG("copying %s (%zd bytes) into new dataspace", path, record->size());
void *local_addr = env()->rm_session()->attach(ds_cap);
memcpy(local_addr, record->data(), record->size());
env()->rm_session()->detach(local_addr);
memcpy(ds->local_addr<void>(), record->data(), record->size());
return ds->cap();
return ds_cap;
}
catch (...) { PDBG("Could not create new dataspace"); }
return Dataspace_capability();
}
void release(Genode::Dataspace_capability ds_cap)
{
env()->ram_session()->free(static_cap_cast<Ram_dataspace>(ds_cap));
}
bool stat(Sysio *sysio, char const *path)
{
Lookup_exact lookup_criterion(path);

View File

@ -46,6 +46,16 @@ namespace Noux {
return Genode::Dataspace_capability();
}
void release_dataspace_for_file(char const *filename,
Genode::Dataspace_capability ds_cap)
{
for (File_system *fs = _file_systems.first(); fs; fs = fs->next()) {
char const *fs_local_path = fs->local_path(filename);
if (fs_local_path)
fs->release(ds_cap);
}
}
void add_file_system(File_system *file_system)
{
_file_systems.insert(file_system);

View File

@ -51,6 +51,8 @@ namespace Noux {
return Genode::Dataspace_capability();
}
void release(Genode::Dataspace_capability) { }
bool stat(Sysio *, char const *) { return _msg("stat"); }
Vfs_handle *open(Sysio *, char const *) { _msg("open"); return 0; }
void close(Vfs_handle *) { _msg("close"); }