Hi all,
I'm trying to allocate a dataspace dynamically at runtime and transfer quota accordingly. However, it seems the allocation always requires more quota than the actual allocation size.
E.g.
Genode::Ram_connection ram; ram.ref_account(Genode::env()->ram_session_cap()); Genode::Ram_dataspace_capability ds; Genode::env()->ram_session()->transfer_quota(ram.cap(), 32*1024); PDBG("Quota: %d/%d\n", ram.used(), ram.quota()); ds = ram.alloc(28*1024); PDBG("Quota: %d/%d\n", ram.used(), ram.quota());
This shows 0/32769 on the first print and 28672/32769 on the second which is exactly what you'd expect. Allocating 29 KiB with a 32 KiB quota, however, will throw a Quota_exceeded exception, still printing 0/32769 on the first print.
It seems you need about 4 KiB of spare quota but I can't seem to find any doc on this. How much quota should I actually reserve for simple allocations like this and why isn't it simply the same as the actual allocation size? I'd like to avoid magic numbers and wasteful allocation if possible.
Cheers, Georg
Hi Georg,
welcome to the mailing list!
On 22.12.2015 14:00, Georg Guba wrote:
This shows 0/32769 on the first print and 28672/32769 on the second which is exactly what you'd expect. Allocating 29 KiB with a 32 KiB quota, however, will throw a Quota_exceeded exception, still printing 0/32769 on the first print.
It seems you need about 4 KiB of spare quota but I can't seem to find any doc on this. How much quota should I actually reserve for simple allocations like this and why isn't it simply the same as the actual allocation size? I'd like to avoid magic numbers and wasteful allocation if possible.
Dataspaces have a granularity of 4KiB. The granularity is dictated by the size of the smallest possible virtual memory page supported by the the MMU. This is documented in Section 3.4.1. "Dataspaces" in the manual [1]. If you allocate a dataspace of a size that is not a multiple of 4 KiB, core will create the smallest-possible dataspace that satisfies the restriction of the hardware, in your case 32 KiB.
[1] http://genode.org/documentation/genode-foundations-15-05.pdf
Cheers Norman
Hi Georg,
in addition to Norman's remarks I further investigated your issue (mostly because the value 32769 which is 0x8001 puzzled me).
On 22.12.2015 14:00, Georg Guba wrote:
This shows 0/32769 on the first print and 28672/32769 on the second which is exactly what you'd expect. Allocating 29 KiB with a 32 KiB quota, however, will throw a Quota_exceeded exception, still printing 0/32769 on the first print.
It seems you need about 4 KiB of spare quota but I can't seem to find any doc on this. How much quota should I actually reserve for simple allocations like this and why isn't it simply the same as the actual allocation size? I'd like to avoid magic numbers and wasteful allocation if possible.
With the patch applied I get the following output on linux_x86.
[init -> test-printf] 0/0 [init -> test-printf] 0/32768 [init -> test-printf] 16384/32768
So it's 0x8000 indeed and I assume a typo on your side. But, the actual question is: Why can't one use the final 4 KiB of the RAM quota? The answer leads us to the implementation of Ram_session_component in core, which dates back several years and includes the following comment in Ram_session_component::alloc().
/* * Check quota! * * In the worst case, we need to allocate a new slab block for the * meta data of the dataspace to be created - therefore, we add * the slab block size here. */
Unfortunately, this piece of code does not (and currently can't) use the available bytes in the meta-data allocator but in the RAM session itself. It is remnant of the ongoing process of decoupling RAM allocations from meta-data handling.
Thanks for sharing your findings, we'll address the issue with
https://github.com/genodelabs/genode/issues/1831
For now, the last 4 KiB of the RAM session quota are beyond reach, sorry.
Regards