Size of kernel post-boot changes based on code

(David Robert Olsen) #1

My group has run into an interesting observation - when we added a few lines of code, none of which is called during the kernel startup sequence, the output for khu immediately after booting was exactly one page larger than it was before adding the code.

Is kernel heap usage actually tied to the amount of code the kernel has? Is it possible that adding a few lines of code filled a sub-page allocation somewhere and caused it to allocate a new page?

(Geoffrey Challen) #2

No. Kernel code isn’t stored on the heap. So something else is going on.

(David Robert Olsen) #3

Weird. Our khu on bootup literally increased by one page by literally only adding a few lines of code in a function that isn’t even called.

We also noticed that increasing the amount of memory available to the system increased the initial khu as well. However, this doesn’t seem to be negatively affecting any tests. Could this potentially be a “hidden” memmory leak that will bite us in 3.3?

(Geoffrey Challen) #4

Oh, actually, I know why this is probably happening.

On OS/161, the right way to set up your coremap is to do the math at the beginning so that coremap index 0 maps to the first free page. This is not that hard.

However, some people have decided to account for the space taken up by the coremap by marking some pages at the beginning of their coremap as permanently used. These are the pages that the coremap sits on. This is OK—although not as elegant a solution and you could have. (See above.) In this case, if khu counts these pages, the number of pages initially used will vary based on the size of the coremap—and, thus, on the size of memory. This explains your second observation (“increasing the amount of memory available to the system increased the initial khu as well.”)

Your first observation (“khu on bootup literally increased on page by literally only adding a few lines of code”) is explained by the fact that you coremap probably has used entries to account for the memory taken up by the kernel itself. Some course staff members have been telling people to do this because it “makes the math simpler”, although it’s not a great idea. So in this case, when the size of your kernel changes—which it does when you add code—the number of coremap entries that have to be reserved for the kernel image may change if the kernel image size crosses a page boundary. So that’s what’s happening.

To summarize:

  • Ideally, coremap[0] points to the first available page: i.e., the first page of memory past the end of the coremap. In this case coremap_get_used_bytes should be 0 at boot.
  • Sub-optimally, coremap[0] points to the page where the coremap starts. In this case, coremap_get_used_bytes at boot should be ROUNDUP(sizeof(coremap), PAGE_SIZE).
  • Sub-sub-optimally, coremap[0] points to physical address 0x0, which is where the kernel starts. (Ugh.) In this case, coremap_get_used_bytes at boot is ROUNDUP(sizeof(kernel), 4096) + ROUNDUP(sizeof(coremap), 4096).

That said, you can always correct this problem by noticing that pages marked as used in the coremap for the kernel image or coremap itself will never be freed. So it’s safe for coremap_get_used_bytes to ignore them. During boot you can calculate the number of wasted coremap entries and have coremap_get_used_bytes subtract this from its return. So right after coremap initialization coremap_get_used_bytes should always return 0, regardless of how many coremap indices your design needs to (unnecessarily) reserve.

(David Robert Olsen) #5

That makes a lot of sense, and is consistent with what I am seeing from messing around with the code. Thanks GWA!