Zbr's days.

About :: TODO :: Blog :: RSS :: Old blog :: Projects :: GIT :: Gallery :: Notes

Fri, 28 Jul 2006

Network tree allocator.


And to complicate thins even more let's do everything simple.

Each allocated physical page (or pointers to larger contiguous blocks, they must differ and there must exist some way to obtain pointer to the start of the block from it's internal pointer, for example it is trivial to obtain pointer to the physical page (do not confuse with struct page) from the pointer inside that page - one just needs to AND given address with PAGE_MASK) is inserted into the AVL tree and live there forever. Each node has a bitmask of free and empty regions inside that page (if minimum allowed allocation block is 32 bytes, this bitmask takes PAGE_SIZE/32 bits), where each bit corresponds to part of the page which is used or free.
Each free region is placed into array of single-linked lists, where each list entry stores pointer to the actual free region and a pointer to the next entry. Array is indexed using allocation size (aligned to the minimum allowed allocation size).

When region is freed, appropriate page pointer is calculated (using trivial AND with PAGE_MASK) and page is selected inside the tree. Using offset from the page address to freed address we can select two neighbour regions which are either used or free and theirs sizes using search inside bitmask of free and used regions in each node. Free ones are searched inside lists for the appropriate sizes (yes, using slow search inside single-linked list, call me a loser), removed from that lists and concatenated (with node's bitmask update), then new free region is placed into the list for appropriate size.

When system is asked to allocate new region it checks list of free regions for the appropriate size, if it is empty it tries to get next list (with increased size). Eventually it will find the list with free region, which will be splitted into the used one (and appropriate pointer will be returned to the caller), and free one which will be moved into the new list for appropriate size. Bitmask of free and used regions for the node, which hosts page where returned region is allocated, will be updated accordingly.

If search (through single-linked list) for the free region which should be concatenated with freed one will take too much time (for example SLOB allocator works with similar searching for free object and no one complains), it is possible to replace it with double-linked one and set of pointers inside node which will point directly to the free region, so it can be removed and concatenated without speed overhead, but that will require list or array of pointers inside each node, so we will have additional memory overhead.

There is also a problem with jumbo frames and more than one page allocations. For the above scheme to work with more than a page contiguous blocks it is required that there is a way to determine initial pointer (start of the contiguous block) from any pointer inside that block (which is trivial with page sized chunks). It can be solved by allocation of the big sized pages from special address ranges (i.e. we can get page address and if it is from big sized pool of addresses, it will be updated accordingly).

But enough for theory, talks are cheap, so I plan to create initial implementation today.

P.S. And how that could be easier if I would not care too much about memory overhead... But it is another story.

/devel/networking/nta :: Link / Comments ()