Checkpointing dataspaces in core

Denis Huber huber.denis at ...435...
Wed Aug 3 11:51:31 CEST 2016


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:
>>
>> 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;
>> !    }
>>
>
> 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.
>
>> 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?
>
> 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 at lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/genode-main
>>
>




More information about the users mailing list