Philippe Gerum wrote: > On Thu, 2007-06-07 at 21:27 +0200, Jan Kiszka wrote: >> NZG wrote: >>>>> Write does stop throwing errors with a pool of 16384. >>>> Just repeating for confirmation: rt_pipe_create with smaller, but >>>> non-zero pool sizes doesn't report some error? >>> Incorrect, if it's created with smaller it does report an error. If it's >>> created with 0 however, it seems ok. (at least it doesn't throw an error) >> You mean the write fails, but rt_pipe_create is fine. At least here, and >> Philippe noticed the same. Looks like the margin for minimal-sized heaps >> is broken. 2*PAGE_SIZE should be 3*PAGE_SIZE net space, Philippe? > > Actually, rt_pipe_create() already rounds this value to 3*PAGE_SIZE, > right before calling the sysalloc service. > > Here is the sequence of events that leads to the situation Nathan is > seeing: > > - Passing poolsize = 1024 to rt_pipe_create() creates a local heap of > 12288 bytes (3 * PAGE_SZ), with 32 bytes of overhead taken from one of > these pages to hold the meta-data. > > - 4112 bytes (4096 + sizeof(message header)) are then requested to this > local pool to hold the internal streaming buffer > (XENO_OPT_NATIVE_PIPE_BUFSZ), which ends up consuming two pages, i.e. > 8192 bytes, from this pool. The reason for this is due to the way the > McKusick allocation scheme we use works; basically, block sizes greater > than the page size are always rounded to a multiple of the page size. > Requested block sizes are always rounded up to the nearest power of two, > which the allocator groups in pages holding blocks of the same size. > This is not pretty wrt internal fragmentation, but quite efficient > CPU-wise, when the page size is properly chosen wrt the most common > allocation pattern, that is. Most importantly, blocks greater than a > page will never lay on partially consumed pages (by other blocks). So, > in our case, we started with three free pages, one already holds some > meta-data, and we need two pages to fullfil the current allocation > request. Therefore, after this request has suceeded, we have no page > left in the pool. > > - When the write() call is issued, the pipe driver requests a 32 bytes > block to hold the data moving from user-space to kernel space. Too bad, > we have no other page left to dedicate to blocks holding that size, so > no block is available, which in turn causes write() to return -ENOMEM.
Ah, I see. > > This situation illustrates the conflict which is raised when small heaps > (1k) are mapped on large page sizes (4k). Even when rounding them to a > (small) multiple of the page size, the pool might rapidly run short of > free pages, depending on the allocation pattern. Reminds me of the TLSF allocator claiming to perform smartly also on smaller hunks. But that code is still 32-bit-focused, and would still need someone to define and run comparative tests on representative Xenomai setups. :-/ > > IOW, when configuring a heap, it is better to know which kind of block > sizes are going to be requested from it, and reserve the appropriate > number of pages for each different size when evaluating the total size > of the heap. > > Yes, it's not that simple. No, I'm not that sorry. > For now, can we take XENO_OPT_NATIVE_PIPE_BUFSZ into account when picking a reasonable minimum size in rt_pipe_create on behalf of a close-fisted user? Jan
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Xenomai-help mailing list [email protected] https://mail.gna.org/listinfo/xenomai-help
