Skip to content

Customizing a memory allocator

Wang Renxin edited this page May 31, 2022 · 3 revisions

Get started

The memory is limited in embedded systems which can run for years and cause a severe waste of memory due to fragmentation. Besides, it's efficient for MY-BASIC to customizing a memory allocator, even on systems with a plenty of memory.

An allocator need to be in form of:

typedef char* (* mb_memory_allocate_func_t)(unsigned s);

And a freer:

typedef void (* mb_memory_free_func_t)(char* p);

Then you can tell MY-BASIC to use them globally instead of standard malloc and free by calling:

MBAPI int mb_set_memory_manager(mb_memory_allocate_func_t a, mb_memory_free_func_t f);

Note these functors only affect allocation inside my_basic.c, but main.c still uses the standard C allocator.

Tutorial

There is already a simple memory pool implementation in main.c. You need to make sure the _USE_MEM_POOL macro is defined as 1 to enable this pool.

There are four functions in this implementation as a tutorial: _open_mem_pool opens the pool when setting up an interpreter; _close_mem_pool closes the pool when terminating; a pair of _pop_mem and _push_mem will be registered to MY-BASIC. Note _pop_mem will call the standard malloc if an expected size is not a common size in MY-BASIC; and it will take sizeof(union _pool_tag_t) extra bytes to store meta data with each allocation. At the moment, this pool algorithm manages several types by pool: int, intptr_t, _ls_node_t, _ht_node_t, _object_t, _func_t, _array_t, _var_t, _label_t, _routine_t, _class_t, and also some common sizes such as 32 bytes, 128 bytes, 512 bytes, etc. The allocator will lookup for a minimum pool which can allocate an expected size (may be a little larger) of memory, it will use the standard C allocator if no pool met.

A typical workflow as follow:

_open_mem_pool(); /* Open it */
mb_set_memory_manager(_pop_mem, _push_mem); /* Set them */
{
	mb_init();
	mb_open(&bas);
	/* Other deals with MY-BASIC */
	mb_close(&bas);
	mb_dispose();
}
_close_mem_pool(); /* Finish */

Strictly speaking, this algorithm doesn't guarantee to allocate memory at continuous spaces, it is an object pool other than a memory pool, which pops a free chunk of memory with an expected size to user, and pushes it to the stack back when user frees it instead of freeing it to system. Replace it with efficient algorithms to get bet performance and ballance between space and speed.

Clone this wiki locally