Hallo Stefan,
thank you for your extensive answer. It helped me a lot. I will talk about your advice to implement the mechanism in user-space of Genode with my advisor.
But if I have to implement it in core, how can I find an object in the object pool? * Publicly, it has only the insert, remove, and apply functionality. * Privatly, it uses an Avl_tree<Entry> structure and a method called find_by_obj_id(unsigned long obj_id) in Entry.
Can I use this method to find my object? And how do I get the obj_id of a specific PD session with a certain label?
Kind regards Denis
On 02.08.2016 11:20, Stefan Kalkowski wrote:
Hello Denis,
On 07/29/2016 12:15 PM, Denis Huber wrote:
Dear Genode community,
I want to implement a new service (class Cr_session) residing in core which provides an Rpc method to checkpoint the state of a specific component (given its label string). I am using Genode 16.05 and the foc kernel (pbxa9 build). The first step is to store the content of the address space of the compoent. My approach is the following:
- First a test component is created which shall be checkpointed. The
component counts an integer every second.
In base/src/test/cr_service/counter/main.cc (newly created file): !void Component::construct(Genode::Env &env) !{ ! unsigned int n = 0; ! Timer::Connection timer(env); ! ! while(1) ! { ! Genode::log(n); ! n++; ! timer.msleep(1000); ! } !}
- To realize the CR service in core, I want to find the specific PD
session of the test component. Therefore a separate Sliced_heap exclusively for Pd_session_component objects is created in core's main function.
In base/src/core/main.cc: !static Sliced_heap pd_sliced_heap(env()->ram_session(), env()->rm_session()); ![...] !static Pd_root pd_root(e, e, pager_ep, &pd_sliced_heap);
- The CR service is registered and the special Sliced_heap is passed to
the Root_component<Cr_session_component> object.
In base/src/core/main.cc: !static Cr_root cr_root(e, &sliced_heap, &pd_sliced_heap); ![...] !static Local_service ls[] = { ! Local_service(Cr_session::service_name(), &cr_root), ![...] !}
- In the implementation of the checkpoint method the Sliced_heap
(stored in _alloced_pds) is searched for a Pd_session_component with a specific label string. The class implementing the Cr service (Genode::Cr_session_component : Rpc_object<Cr_session>) is a friend class in Sliced_heap and is allowed to access the _blocks member variable containing the Pd_session_component objects.
In base/src/core/include/cr_session_component.h (newly created file): !bool checkpoint(String<64> label) !{ ! Pd_session_component *pd = nullptr; ! bool found = false; ! Sliced_heap::Block *b = _alloced_pds->_blocks.first(); ! for(; (b != 0) && !found; b = b->next()) ! { ! pd = reinterpret_cast<Pd_session_component*>(b + 1); ! if(label == pd->_label.string) found = true; ! }
I would strongly recommend to not use the heap abstraction for retrieving any objects. Your implementation is extremely error-prone when depending on internals of the Sliced_heap implementation, and indiscriminately casting to some objects. It would be much better to retrieve the PD object either by running through the object pool where they reside in, or if you do not want that for some reason, register them in a special data-structure to retrieve them more easily, e.g., a list.
- The Pd_session_component object is known and now it shall be used to
access the test component's address space content. To retrieve the content I want to attach the Dataspace of the component's Region_map to core's Region_map.
In base/src/core/include/cr_session_component.h (newly created file): ! Capability<Region_map> rm_cap = pd->address_space(); ! Region_map_client rm_client(rm_cap); ! void* addr = core_env()->rm_session()->attach(rm_client.dataspace()); ! return true; !}
- After invoking rm_client.dataspace() the Rpc method never returns and
the test scenario times out.
What am I doing wrong? I compared the source code of other core services with the CR service and found no usage of classes derived from Rpc_client belonging to other core services. Is it not possible to use Rpc methods in core?
In general, it is possible to use RPC functions within core, but if you call a core-service itself within the execution context that provides these services you fall into a deadlock. Your new service probably uses the same entrypoint (thereby execution context) like for instance the RM service. So then it is not possible to invoke this service via RPC calls from your context.
I tested another solution where I only use Rpc_objects directly. I used pd_session_component::address_space_region_map() to access the address_space directly, where I think to find the memory content of the test component (Please correct me, if I am wrong). The following listing replaces the listing in step 4.
In base/src/core/include/cr_session_component.h (newly created file): ! Dataspace_capability ds_cap = pd->address_space_region_map().dataspace(); ! char* addr = core_env()->rm_session()->attach(ds_cap); ! log("Attaching dataspace: Returned pointer: ", addr); ! ! Dataspace_component *ds_comp = pd->address_space_region_map().dataspace_component(); ! log("Reading dataspace component"); ! log("phys_addr = ", ds_comp->phys_addr(), " size = ", ds_comp->size(), " writable = ", ds_comp->writable() ? "true" : "false");
The output of the log function was the following: Attaching dataspace: Returned pointer: 0x00000000 Reading dataspace component phys_addr = 0 size = 3221221376 writable = false
Now I got a null pointer and cannot read the content of the Region_map of the test component.
Can someone help me to answer the following questions:
- Can I use Capability invokation in core, where the Rpc_object belongs
to another core service? If yes, how? Perhaps, my problem is the correct retrieval of the Pd_session_component, thus I can invalid Capabilities.
- Why do I get an invalid pointer from the attach method of core's
Region_map? Is it not allowed to attach dataspaces in core? Are they already attached in core, and I only need the pointer to the memory? Is the Dataspace_capability invalid?
As already mentioned, you can call core services within core, but only from a different execution context than the entrypoint itself, which implements the core services. Anyway this is not recommended in general, because you can easily produce circular dependencies.
The correct retrieval of PD components indeed is a problem given your example. As already explained it is not recommended at all to use the memory allocator to find objects. This practice is not related to Genode specifically.
You can of course attach dataspaces in core. This is used for instance before core hands out a dataspace when clearing its content. Nevertheless, when it comes to non-physical dataspaces, which means not simple dataspaces representing only physical memory, e.g., the representation of a region-map, you cannot simply attach them within core. The reason is that core's RM service implementation is much simpler than the one core provides for all other components, again due to possible circular dependencies. When you attach a dataspace in core, the corresponding memory mappings are established immediately. For all other components than core, a pager service within core resolves page-faults lazily when they occur. Thereby, more complex dataspaces like the region map representation are identified too.
I would strongly recommend to you to *not* implement your checkpoint-service within core. It is far more easy to write an extra component, which wraps the relevant core services, e.g. PD, RM etc.. That component can hold the capabilities to the relevant core services in a data-structure that matches your demands. You won't run into trouble of circular dependencies. You can easily attach region map representations to its region map, etc.. You can route all relevant services to that component instead of core. If you really want to target all components you could even place your component underneath of the init component. Thereby, you can use most currently available run-scripts with minor changes only.
Best regards Stefan
Kind regards Denis
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main