Startup Memory Allocation in PoprC

Posted on August 15, 2020

Arbitrary limits are bad

I’ve written PoprC in an embedded style of C, where malloc() is avoided. This has a lot of benefits: no dynamic allocation overhead, repeatable addresses which can be used as identifiers, and the ability to use watchpoints when debugging, as well as being able to easily iterate over arrays.

It does have one large drawback, though: because memory is statically allocated, the sizes cannot change. I generally try to set the limits around 2x a reasonable amount, but while this works okay for development, I know it’s not acceptable for end use.

Startup “static” allocation

To address this, I implemented an easy way to perform “static” allocation on startup (in static_alloc.c. The idea is to perform all allocations with arbitrary limits on startup, which allows the opportunity to adjust the sizes based on flags or a configuration file.

Doing this manually would be annoying, so I used the code generation system that I’ve used elsewhere to collect macros of the form STATIC_ALLOC(name, type, default_size). Then, I would translate allocations of the form type name[size] into that macro throughout PoprC’s source. In addition, there are extended forms of the macro to specify alignment (STATIC_ALLOC_ALIGNED) and sizes that are dependent on another (STATIC_ALLOC_DEPENDENT.)

There are a few drawbacks to this system:

All of these limitations were fairly easy to work with.

A nice added feature for debugging is the compiler can identify pointers in the allocated region, which is most of the pointers I’m interested in during debugging. I can type pp (some pointer) in LLDB now to display a description of the form variable[offset] (see print_static_alloc().)

Future work

Some allocations aren’t needed all of the time. I would like to implement a way to perform temporary allocations in an area allocated on startup (using static_alloc.c) which is large enough to hold the maximum temporary allocation. This would be like a statically allocated union where the fields can be declared anywhere.

I have yet to implement reading allocation sizes from a configuration file, so PoprC is just using the default sizes. After implementing this, it would be good to have assertion messages that indicate which size needs to be adjusted.

Previous Post
comments powered by Disqus