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:
1) 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); ! } !}
2) 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);
2) 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), ![...] !}
3) 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; ! }
4) 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; !}
5) 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?
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?
Kind regards Denis