0

I've created my own buddy allocator with a bitmap (for managing my kernel's physical memory), with each bit corresponding to a page block of particular size. Since I map the whole 4GiB address space, logically the 1st bit would represent a 4GiB block, the next two bits will represent blocks of 2GiB, the next four bits will represent blocks of 1GiB and so on until we reach just single blocks of 4KiB (page size). Getting the children of a bit would be as simple as noting the bit position, bitN, and:
leftNode = bitN * 2
rightNode =bitN * 2 + 1
Getting the parent of any bit would be calculated as bitN / 2.

In a sense, the whole bitmap would look like:

bit number: [1] [2 3] [4 5 6 7] [8 9 10 11 12 13 14 15] [16 ... etc.]
holds block: 4G  2G    1G        512M                    256M  - 4KiB


I can map unique physical addresses for each block of identical size, but because of the way this scheme is employed, the addresses will overlap, meaning that the same physical address can be returned, for example, for a 4KiB block or a 16KiB block. This is true especially for bit numbers that are power of 2 -- bits 1, 2, 4, 8, etc. will always point to the leftmost physical block, which is address 0. Bits 3, 6, 12, 24, etc. will also always point to the same block beginning at address 2GiB, but this block may be of any (valid) size! A good example output would be:

(assume address 0 is valid and isn't considered NULL for the sake of the example)
allocate(1) -- allocate 1 page, returns address 0x00000000. Valid usable range is 0-4095 (0x00000000 - 0x00001000).
allocate(524288) -- allocate 512k pages (2GiB), returns address 0x80000000. Valid usable range is 0x80000000-0xFFFFFFFF.
free((uint32_t *)0) -- free address 0. Page is reclaimed and merged with its free buddies.
allocate(16) -- allocate 16 pages, returns address 0x00000000! Same address but now with a bigger usable range of 0-65535!


As you can see, with this implementation the same address can point to a block of any size and I want to know how to get this block size so I can index into the bitmap and start merging buddies. But I've spent hours trying to figure out how to do this reverse mapping of finding the bit from the bitmap that corresponds to the address! I don't have problems allocating any number of pages and I get unique addresses back, but I don't know how to index back into the bitmap once I have to free them! Any ideas how to go about this?

Ivan Stanev
  • 133
  • 1
  • 11

1 Answers1

0

Seems to me that you need at least two bits of information per block. One bit to keep track of whether a block has been split, and another bit to keep track of whether the block is allocated or free. One possible encoding:

00 - page is part of a larger block
01 - block has been split
10 - free block
11 - allocated block
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • I already managed to allocate memory with just 1 bit per entry, with 0 representing that the node is free, and 1 meaning it is occupied. If a node and its buddy are occupied then the parent node must also be marked as occupied. Searching within the tree (assuming it is per-node) stops at the first occupied node encountered. – Ivan Stanev Mar 16 '15 at 15:07
  • Well done, but... Assume that the system has been running for some time, many allocations and frees have occurred, and a single 4KiB block is the only block currently occupied. So out of the 2097151 bits in the bitmap, exactly 1 bit is set. The first bit in the bitmap is a 0, meaning that either it's free or it has been split, but you can't know which unless you search the entire table to find the one bit that's set. – user3386109 Mar 16 '15 at 19:37
  • @IvanStanev Bottom line, this a classic tradeoff between *space* and *time*. If you minimize the *space* used to keep track of allocations, you maximize the *time* it takes to perform allocation and free operations. Using more *space* wisely will reduce the amount of *time* needed for allocations/frees. That's what I was trying to suggest. My answer is not complete by any means, and in fact still keeps far too little information about allocations, and therefore would be painfully slow. I was just giving you a little nudge in the right direction. – user3386109 Mar 16 '15 at 19:45
  • You're right, and the allocator does take more time to allocate entries after some thousands of allocations, even though the depth of the tree is not that large. However, I feel like there's not a way to store/represent the mapped address with just bits and it's just better to store this in a struct... Otherwise you can just allocate but never free! – Ivan Stanev Mar 17 '15 at 05:23
  • @IvanStanev Sounds like you're headed in the right direction. Best of luck ! – user3386109 Mar 17 '15 at 06:08