diff --git a/base-foc/lib/mk/env.mk b/base-foc/lib/mk/env.mk index fc7176970..17ac5b253 100644 --- a/base-foc/lib/mk/env.mk +++ b/base-foc/lib/mk/env.mk @@ -1,6 +1,7 @@ -SRC_CC = env.cc context_area.cc cap_sel_alloc.cc +SRC_CC = env.cc context_area.cc cap_sel_alloc.cc reload_parent_cap.cc LIBS = ipc heap log_console lock -vpath env.cc $(BASE_DIR)/src/base/env -vpath context_area.cc $(BASE_DIR)/src/base/env -vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env +vpath env.cc $(BASE_DIR)/src/base/env +vpath context_area.cc $(BASE_DIR)/src/base/env +vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env +vpath reload_parent_cap.cc $(BASE_DIR)/src/base/env diff --git a/base-nova/lib/mk/env.mk b/base-nova/lib/mk/env.mk index 439e6e2d7..1f8ada9a8 100644 --- a/base-nova/lib/mk/env.mk +++ b/base-nova/lib/mk/env.mk @@ -1,7 +1,9 @@ -SRC_CC = env.cc cap_sel_alloc.cc main_thread.cc context_area.cc +SRC_CC = env.cc cap_sel_alloc.cc main_thread.cc context_area.cc \ + reload_parent_cap.cc LIBS = ipc heap lock log_console -vpath env.cc $(BASE_DIR)/src/base/env -vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env -vpath main_thread.cc $(REP_DIR)/src/base/env -vpath context_area.cc $(BASE_DIR)/src/base/env +vpath env.cc $(BASE_DIR)/src/base/env +vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env +vpath main_thread.cc $(REP_DIR)/src/base/env +vpath context_area.cc $(BASE_DIR)/src/base/env +vpath reload_parent_cap.cc $(BASE_DIR)/src/base/env diff --git a/base/include/base/heap.h b/base/include/base/heap.h index a8ee5bc87..14e4efb4b 100644 --- a/base/include/base/heap.h +++ b/base/include/base/heap.h @@ -77,6 +77,9 @@ namespace Genode { * \return 0 on success or negative error code */ int expand(size_t size, Range_allocator *alloc); + + void reassign_resources(Ram_session *ram, Rm_session *rm) { + _ram_session = ram, _rm_session = rm; } }; /* @@ -128,6 +131,12 @@ namespace Genode { */ int quota_limit(size_t new_quota_limit); + /** + * Re-assign RAM and RM sessions + */ + void reassign_resources(Ram_session *ram, Rm_session *rm) { + _ds_pool.reassign_resources(ram, rm); } + /************************* ** Allocator interface ** diff --git a/base/include/base/platform_env.h b/base/include/base/platform_env.h index 33ad18684..906644661 100644 --- a/base/include/base/platform_env.h +++ b/base/include/base/platform_env.h @@ -106,15 +106,28 @@ namespace Genode { private: - Parent_client _parent_client; - Parent *_parent; - Ram_session_capability _ram_session_cap; - Expanding_ram_session_client _ram_session_client; - Cpu_session_client _cpu_session_client; - Expanding_rm_session_client _rm_session_client; - Pd_session_client _pd_session_client; - Heap _heap; + Parent_client _parent_client; + struct Resources + { + Ram_session_capability ram_cap; + Expanding_ram_session_client ram; + Cpu_session_client cpu; + Expanding_rm_session_client rm; + Pd_session_client pd; + + Resources(Parent &parent) + : + ram_cap(static_cap_cast(parent.session("Env::ram_session", ""))), + ram(ram_cap), + cpu(static_cap_cast(parent.session("Env::cpu_session", ""))), + rm(static_cap_cast(parent.session("Env::rm_session", ""))), + pd(static_cap_cast(parent.session("Env::pd_session", ""))) + { } + }; + + Resources _resources; + Heap _heap; public: @@ -123,26 +136,37 @@ namespace Genode { */ Platform_env() : - _parent_client(Genode::parent_cap()), _parent(&_parent_client), - _ram_session_cap(static_cap_cast(parent()->session("Env::ram_session", ""))), - _ram_session_client(_ram_session_cap), - _cpu_session_client(static_cap_cast(parent()->session("Env::cpu_session", ""))), - _rm_session_client(static_cap_cast(parent()->session("Env::rm_session", ""))), - _pd_session_client(static_cap_cast(parent()->session("Env::pd_session", ""))), - _heap(ram_session(), rm_session()) + _parent_client(Genode::parent_cap()), + _resources(_parent_client), + _heap(&_resources.ram, &_resources.rm) { } + /** + * Reload parent capability and reinitialize environment resources + * + * This function is solely used for implementing fork semantics. + * After forking a process, the new child process is executed + * within a copy of the address space of the forking process. + * Thereby, the new process inherits the original 'Platform_env' + * object of the forking process, which is meaningless in the + * context of the new process. By calling this function, the new + * process is able to reinitialize its 'Platform_env' with + * meaningful capabilities obtained via its updated parent + * capability. + */ + void reload_parent_cap(); + /******************* ** Env interface ** *******************/ - Parent *parent() { return _parent; } - Ram_session *ram_session() { return &_ram_session_client; } - Ram_session_capability ram_session_cap() { return _ram_session_cap; } - Cpu_session *cpu_session() { return &_cpu_session_client; } - Rm_session *rm_session() { return &_rm_session_client; } - Pd_session *pd_session() { return &_pd_session_client; } + Parent *parent() { return &_parent_client; } + Ram_session *ram_session() { return &_resources.ram; } + Ram_session_capability ram_session_cap() { return _resources.ram_cap; } + Cpu_session *cpu_session() { return &_resources.cpu; } + Rm_session *rm_session() { return &_resources.rm; } + Pd_session *pd_session() { return &_resources.pd; } Allocator *heap() { return &_heap; } }; } diff --git a/base/lib/mk/env.mk b/base/lib/mk/env.mk index 651e430ce..37e3b53ac 100644 --- a/base/lib/mk/env.mk +++ b/base/lib/mk/env.mk @@ -1,5 +1,6 @@ -SRC_CC = env.cc context_area.cc +SRC_CC = env.cc context_area.cc reload_parent_cap.cc LIBS = ipc heap log_console lock -vpath env.cc $(REP_DIR)/src/base/env -vpath context_area.cc $(BASE_DIR)/src/base/env +vpath env.cc $(REP_DIR)/src/base/env +vpath context_area.cc $(BASE_DIR)/src/base/env +vpath reload_parent_cap.cc $(BASE_DIR)/src/base/env diff --git a/base/src/base/env/reload_parent_cap.cc b/base/src/base/env/reload_parent_cap.cc new file mode 100644 index 000000000..d55d132ba --- /dev/null +++ b/base/src/base/env/reload_parent_cap.cc @@ -0,0 +1,44 @@ +/* + * \brief Environment reinitialization + * \author Norman Feske + * \date 2012-02-16 + */ + +/* + * 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. + */ + +#include + + +void Genode::Platform_env::reload_parent_cap() +{ + /* + * This function is unused during the normal operation of Genode. It is + * relevant only for implementing fork semantics such as provided by the + * Noux execution environment. + * + * The function is called by the freshly created process right after the + * fork happened. During the fork, the Noux environment is expected to have + * updated the '_parent_cap' of the new process. + * + * The existing 'Platform_env' object contains capabilities that are + * meaningful for the forking process but not the new process. Before the + * the environment can be used, it must be reinitialized with the resources + * provided by the actual parent. + */ + _parent_client = Parent_client(Genode::parent_cap()); + _resources = Resources(_parent_client); + + /* + * Keep information about dynamically allocated memory but use the new + * resources as backing store. Note that the capabilites of the already + * allocated backing-store dataspaces are rendered meaningless. But this is + * no problem because they are used by the 'Heap' destructor only, which is + * never called for heap instance of 'Platform_env'. + */ + _heap.reassign_resources(&_resources.ram, &_resources.rm); +}