Hi TK.,
Since my project MIDIbox Quad Genesis uses dynamic memory allocation in C, I need to know at all times what percentage of the heap is in use. The umm_info function in umm_malloc.c gives this information, but it takes a couple hundred milliseconds to iterate through the heap (and send a ton of debug information to the terminal), and this causes the synth to freeze for this amount of time which is unacceptable.
So instead I modified umm_malloc and added a variable, umm_numusedblocks, which gets updated every time umm_malloc, umm_free, and umm_realloc are called. It just keeps track of the changes in the number of blocks allocated, it doesn’t traverse the whole heap. (The additional overhead is a couple of adds and 4 bytes of memory.)
After some debugging, this system works in my synth. I created some test cases to make sure the block count increases and decreases correctly in the cases of malloc and free, and also in the cases of realloc to a larger and a smaller size.
In the process of working on this, I discovered that heap blocks are actually 12 bytes, not 8 bytes like the comments say. This is because (the size of the block is defined in umm_malloc.c at line 564) the union ‘header’ is 4 bytes and the union ‘body’ ends up being 8 bytes because portBYTE_ALIGNMENT is 8 bytes. Now, obviously this system is working for all MIOS32 projects, but it doesn’t look quite right to me. In fact it looks like someone changed the size of data from 4 (or maybe sizeof(umm_ptr) or whatever) to portBYTE_ALIGNMENT, thinking this would cause all addresses returned by malloc to be aligned to 8 bytes. There’s three reasons this isn’t true:
- Obviously, this makes the blocks 12 bytes, which means every other one starts on an 8-byte boundary; so on average half the returned addresses won’t be 8-byte-aligned.
- Even if this wasn’t the case, the block has 4 bytes of header data, so if the block was aligned to 8 bytes, the returned pointer would be aligned to 4 bytes.
- Besides all that, there’s no guarantee the heap itself is aligned to 8 bytes. In fact when I first defined umm_numusedblocks, I made it unsigned short int (i.e. u16), because this is how all the blocks are addressed in this library. It turns out that this caused the heap itself to get aligned to a 2-byte boundary, which caused mallocs to fail and the synth to go up in flames. Now it’s an unsigned int (i.e. u32), so the heap is aligned to 4 bytes, but I can’t guarantee it’ll be aligned to 8 bytes.
Moreover, I don’t know of anything in ARM32 which would need to be aligned to anything larger than 4 bytes. And in fact, we know there isn’t, because the current system isn’t aligning half of its contents!
Therefore I tried changing data[portBYTE_ALIGNMENT] to data[4], and it seems to work fine. My synth runs fine, and in fact uses 0.1% less memory this way due to the smaller block size.
And I also compiled MIDIbox SEQ V4 with this modified umm_malloc.c, and it starts up and appears to run just fine.
So I would like to commit my modifications, so that I can continue using this code in my synth (and maybe other people can benefit from the RAM usage tracking too). But I wanted to get your approval before modifying a critical part of MIOS32 for everybody. Would you like me to commit it somewhere else and you can test it first? Or do you just want me to commit it normally, and you’ll test it in place, and if there’s an issue you can roll back the files with SVN?
Thanks,
Sauraen