cyg_mempool_fix_*(), cyg_mempool_var_*() — Additional Memory Pools


#include <cyg/kernel/kapi.h>

void cyg_mempool_fix_create (void* base , cyg_int32 size , cyg_int32 blocksize , cyg_handle_t* handle , cyg_mempool_fix* fix );

void cyg_mempool_fix_delete (cyg_handle_t fixpool );

void* cyg_mempool_fix_alloc (cyg_handle_t fixpool );

void* cyg_mempool_fix_timed_alloc (cyg_handle_t fixpool , cyg_tick_count_t abstime );

void* cyg_mempool_fix_try_alloc (cyg_handle_t fixpool );

void cyg_mempool_fix_free (cyg_handle_t fixpool , void* ptr );

cyg_bool_t cyg_mempool_fix_waiting (cyg_handle_t fixpool );

void cyg_mempool_fix_get_info (cyg_handle_t fixpool , cyg_mempool_info* info );

void cyg_mempool_var_create (void* base , cyg_int32 size , cyg_handle_t* handle , cyg_mempool_var* var );

void cyg_mempool_var_delete (cyg_handle_t varpool );

void* cyg_mempool_var_alloc (cyg_handle_t varpool , size_t size );

void* cyg_mempool_var_timed_alloc (cyg_handle_t varpool , size_t size , cyg_tick_count_t abstime );

void* cyg_mempool_var_try_alloc (cyg_handle_t varpool , size_t size );

void cyg_mempool_var_free (cyg_handle_t varpool , void* ptr );

cyg_bool_t cyg_mempool_var_waiting (cyg_handle_t varpool );

void cyg_mempool_var_get_info (cyg_handle_t varpool , cyg_mempool_info* info );


The memory allocation package provides support for additional memory pools, to complement the system heap. These pools are not created automatically by the system, they have to be created by application code or by other packages. There are exported APIs for two types of pool: fixed and variable.

Allocating memory from a fixed memory pool is very fast and, more importantly, deterministic. However the size of each allocation is fixed at the time the pool is created. This is not a problem if the required allocations are all the same size, or nearly so, but otherwise the memory will be used inefficiently. The pool cannot become fragmented.

Variable memory pools provide essentially the same functionality as the system heap, so are rarely used. However on some targets not all free memory is assigned automatically to the system heap. For example there may be a small area of fast on-chip memory as well as the slower external memory. The system heap will only use the latter. A variable memory pool can be created for the former, allowing application code to dynamically allocate fast memory where appropriate.

If the eCos configuration includes the kernel then by default the memory pool functions will be thread-safe. The pool functions do not implement the malloc() guard and free-fill debug facilities, nor the debug data support.

Fixed Memory Pools

A fixed memory pool must be created explicitly, for example:

#define BLOCK_SIZE    1024
#define BLOCK_COUNT   64

static cyg_uint32      pool_memory[((BLOCK_COUNT * BLOCK_SIZE)+3) / 4];
static cyg_handle_t    pool_handle;
static cyg_mempool_fix pool_data;


cyg_mempool_fix_create( (void*) pool_memory,
                        BLOCK_COUNT * BLOCK_SIZE,
                        &pool_handle, &pool_data );

This creates a pool of 63 1K blocks. pool_memory is normally allocated statically, but could also be a pointer to a special area of memory such as on-chip RAM, or it could even be dynamically allocated using malloc(). The pointer should be suitably aligned for the target architecture, usually to either a 32 or a 64 bit boundary. pool_handle can be used for subsequent pool operations. pool_data is a small data structure providing the space needed to administer the pool.

The above pool only provides 63 blocks, not 64. The administration overhead depends on the number of blocks so cannot all be allowed for in the pool_data structure. A small amount of the pool memory is consumed as well, effectively using up all of the first block. To eliminate this inefficiency:

#define BLOCK_SIZE    1024
#define BLOCK_COUNT   64
#define OVERHEAD      (((BLOCK_COUNT + 31) / 32) * sizeof(cyg_uint32))

static cyg_uint32      pool_memory[(ACTUAL_SIZE + 3) / 4];
static cyg_handle_t    pool_handle;
static cyg_mempool_fix pool_data;


cyg_mempool_fix_create( pool_memory,
                        &pool_handle, &pool_data );

There are three functions for allocating memory. cyg_mempool_fix_try_alloc() is analogous to malloc(): it attempts to allocate a block from the pool, returning a null pointer if all blocks are currently in use. There is no need to specify the allocation size because all blocks are the same size. The other two functions are only available in configurations containing the eCos kernel. cyg_mempool_fix_alloc() will allocate a free block if there is one available, otherwise the current thread will be suspended until a block becomes available. A null pointer will only be returned if the thread is woken up again via cyg_thread_release(). cyg_mempool_fix_timed_alloc() may also suspend the current thread, but only for a number of clock ticks. If no block becomes free before the specified time is reached then a null pointer will be returned. The abstime argument is an absolute time, typically calculated by adding a cyg_tick_count_t timeout to the result of cyg_current_time(). In other words the pool API works in exactly the same way as kernel functions such as cyg_semaphore_timed_wait(). cyg_mempool_fix_waiting() can be used to check whether any threads are currently suspended waiting for a free block.

A block can be released using cyg_mempool_fix_free(). If a pool is no longer required it can be destroyed by a call to cyg_mempool_fix_delete(). Information about the current state of a pool can be obtained with cyg_mempool_fix_get_info(), in the form of a cyg_mempool_info structure:

typedef struct {
    cyg_int32 totalmem;
    cyg_int32 freemem;
    void*     base;
    cyg_int32 size;
    cyg_int32 blocksize;
    cyg_int32 maxfree;                  // The largest free block
} cyg_mempool_info;

Variable Memory Pools

The variable memory pool API is very similar to the fixed pool API. The key differences are:

  1. cyg_mempool_var_create() does not take a block size parameter since the pool supports allocations of any size.
  2. There is no special need to worry about overheads when creating the pool. The overheads will be shared between the allocations so spread throughout the pool
  3. The block size is no longer implicit, so the three allocation routines need an explicit size argument.
  4. Allocation operations are not deterministic and may take significantly longer than a fixed pool allocation. A variable pool is also vulnerable to memory fragmentation.