# Unified RTAI real-time memory management.

## Files

file | rtai_nam2num.h
| Conversion between characters strings and unsigned long identifiers.

file | rtai_scb.h
| SCB stand for Shared (memory) Circular Buffer.

file | rtai_shm.h
| Interface of the RTAI SHM module.

file | shm.c
| Implementation of the RTAI SHM module.

file | malloc.c
| Dynamic memory allocation services.

## Defines

#define | rtai_kmalloc(name, size) rt_shm_alloc(name, size, USE_VMALLOC)
| Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.
#define | rtai_kfree(name) rt_shm_free(name)
| Free a chunk of shared memory being shared inter-intra kernel modules and Linux processes.
#define | rtai_malloc(name, size) _rt_shm_alloc(0, name, size, USE_VMALLOC, 0)
| Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.
#define | rt_shm_alloc_adr(start_address, name, size, suprt) _rt_shm_alloc(start_address, name, size, suprt, 0)
| Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.
#define | rtai_malloc_adr(start_address, name, size) _rt_shm_alloc(start_address, name, size, USE_VMALLOC, 0)
| Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.
#define | rtai_free(name, adr) rt_shm_free(name)
| Free a chunk of shared memory being shared inter-intra kernel modules and Linux processes.
#define | rt_heap_close(name, adr) rt_shm_free(name)
| Close a real time group heap being shared inter-intra kernel modules and Linux processes.
#define | rt_global_heap_open() rt_heap_open(GLOBAL_HEAP_ID, 0, 0)
| Open the global real time heap to be shared inter-intra kernel modules and Linux processes.
#define | rt_global_heap_close() rt_heap_close(GLOBAL_HEAP_ID, 0)
| Close the global real time heap being shared inter-intra kernel modules and Linux processes.

## Functions

int | rt_shm_free (unsigned long name)
| Free a chunk of shared memory being shared inter-intra kernel modules and Linux processes.
void * | rt_halloc (int size)
| Allocate a chunk of a group real time heap in kernel/user space.
void | rt_hfree (void *addr)
| Free a chunk of a group real time heap.
void * | rt_named_halloc (unsigned long name, int size)
| Allocate a chunk of a group real time heap in kernel/user space.
void | rt_named_hfree (void *addr)
| Free a chunk of a group real time heap.
void * | rt_named_malloc (unsigned long name, int size)
| Allocate a chunk of the global real time heap in kernel/user space.
void | rt_named_free (void *addr)
| Free a named chunk of the global real time heap.
void * | rt_shm_alloc (unsigned long name, int size, int suprt)
| Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.
void * | rt_heap_open (unsigned long name, int size, int suprt)
| Open/create a named group real time heap to be shared inter-intra kernel modules and Linux processes.
int | rtheap_init (rtheap_t *heap, void *heapaddr, u_long heapsize, u_long pagesize)
| Initialize a memory heap.
void | rtheap_destroy (rtheap_t *heap)
| Destroys a memory heap.
void * | rtheap_alloc (rtheap_t *heap, u_long size, int mode)
| Allocate a memory block from a memory heap.
int | rtheap_free (rtheap_t *heap, void *block)
| Release a memory block to a memory heap.

## Define Documentation

#define rt_global_heap_close | (

)

rt_heap_close(GLOBAL_HEAP_ID, 0)

Close the global real time heap being shared inter-intra kernel modules and Linux processes.

For internal use only.

rt_global_heap_close is used to close the global real time heap.

Closing a global heap in user space has just the effect of deregistering its use and unmapping the related memory from a process address space. In kernel tasks just the deregistration is performed. The global real time heap is destroyed just a the rmmoding of the shared memory module.

#define rt_global_heap_open | (

)

rt_heap_open(GLOBAL_HEAP_ID, 0, 0)

Open the global real time heap to be shared inter-intra kernel modules and Linux processes.

For internal use only.

rt_global_heap_open is used to open the global real time heap.

The global heap is created by the shared memory module and its opening is needed in user space to map it to the process address space. In kernel space opening the global heap in a task is not required but should be done anyhow, both for symmetry and to register its usage.

#define rt_heap_close | ( | name,
|  | adr |  | ) | rt_shm_free(name)

Close a real time group heap being shared inter-intra kernel modules and Linux processes.

For internal use only.

rt_heap_close is used to close a previously opened real time group heap.

Parameters:

  | name | is the unsigned long identifier used to identify the heap.
  | adr | is not used.

Analogously to what done by any allocation function this group real time heap closing call have just the effect of decrementing a usage count, unmapping any user space heap being closed, till the last is done, as that is the one the really closes the group heap, freeing any allocated memory.

Returns:
  the size of the succesfully freed heap, 0 on failure.

#define rt_shm_alloc_adr | ( | start_address,
|  | name,
|  | size,
|  | suprt |  | ) | _rt_shm_alloc(start_address, name, size, suprt, 0)

Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.

rt_shm_alloc_adr is used to allocate in user space.

Parameters:

  | start_address | is a user desired address where the allocated memory should be mapped in user space;
  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory.

  suprt

  is the kernel allocation method to be used, it can be:
  - USE_VMALLOC, use vmalloc;
  - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
  - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
  - USE_GFP_DMA, use kmalloc with GFP_DMA.

Since `name` can be a clumsy identifier, services are provided to convert 6 characters identifiers to unsigned long, and vice versa.

See also:
  the functions nam2num() and num2nam().

It must be remarked that only the very first call does a real allocation, any subsequent call to allocate with the same name from anywhere will just increase the usage count and map the area to user space, or return the related pointer to the already allocated space in kernel space. The function returns a pointer to the allocated memory, appropriately mapped to the memory space in use. So if one is really sure that the named shared memory has been allocated already parameters size and suprt are not used and can be assigned any value.

Note:
  If the same process calls rtai_malloc_adr and rtai_malloc() twice in the same process it get a zero return value on the second call.

Returns:
  a valid address on succes, 0 on failure.

#define rtai_free | ( | name,
|  | adr |  | ) | rt_shm_free(name)

Free a chunk of shared memory being shared inter-intra kernel modules and Linux processes.

rtai_free is used to free a shared memory chunk from user space.

Parameters:

  | name | is the unsigned long identifier used when the memory was allocated;
  | adr | is not used.

rtai_free is a legacy helper macro, the real job is carried out by a call to rt_shm_free with the same name. This function should not be used in newly developed applications. See rt_shm_alloc_adr for more details.

Returns:
  the size of the succesfully freed memory, 0 on failure.

#define rtai_kfree | ( | name |  | ) | rt_shm_free(name)

Free a chunk of shared memory being shared inter-intra kernel modules and Linux processes.

rtai_kfree is used to free a shared memory chunk from kernel space.

Parameters:

  | name | is the unsigned long identifier used when the memory was allocated;

rtai_kfree is a legacy helper macro, the real job is carried out by a call to rt_shm_free with the same name. This function should not be used in newly developed applications. See rt_shm_free for more details.

Returns:
  the size of the succesfully freed memory, 0 on failure.

#define rtai_kmalloc | ( | name,
|  | size |  | ) | rt_shm_alloc(name, size, USE_VMALLOC)

Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.

For internal use only.

rtai_kalloc is used to allocate shared memory from kernel space.

Parameters:

  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

rtai_kmalloc is a legacy helper macro, the real job is carried out by a call to rt_shm_alloc() with the same name, size and with vmalloc support. This function should not be used in newly developed applications. See rt_shm_alloc for more details.

Returns:
  a valid address on succes, 0 on failure.

#define rtai_malloc | ( | name,
|  | size |  | ) | _rt_shm_alloc(0, name, size, USE_VMALLOC, 0)

Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.

For internal use only.

rtai_malloc is used to allocate shared memory from user space.

Parameters:

  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

rtai_malloc is a legacy helper macro, the real job is carried out by a call to rt_shm_alloc() with the same name, size and with vmalloc support. This function should not be used in newly developed applications. See rt_shm_alloc fro more details.

Returns:
  a valid address on succes, 0 on failure.

#define rtai_malloc_adr | ( | start_address,
|  | name,
|  | size |  | ) | _rt_shm_alloc(start_address, name, size, USE_VMALLOC, 0)

Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.

For internal use only.

rtai_malloc_adr is used to allocate shared memory from user space.

Parameters:

  | start_address | is the adr were the shared memory should be mapped.
  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

rtai_malloc_adr is a legacy helper macro, the real job is carried out by a call to rt_shm_alloc_adr() with the same name, size and with vmalloc support. This function should not be used in newly developed applications. See rt_shm_alloc_adr for more details.

Returns:
  a valid address on succes, 0 on failure.

## Function Documentation

void * rt_halloc | ( | int | size | ) | `[inline]`

Allocate a chunk of a group real time heap in kernel/user space.

Since it is not named there is no chance to retrieve and share it elsewhere.

For internal use only.

rt_halloc is used to allocate a non sharable piece of a group real time heap.

Parameters:

  | size | is the size of the requested memory in bytes;

A process/task must have opened the real time group heap to use and can use just one real time group heap. Be careful and avoid opening more than one group real time heap per process/task. If more than one is opened then just the last will used.

Returns:
  the pointer to the allocated memory, 0 on failure.

void* rt_heap_open | ( | unsigned long | name,
|  | int | size,
|  | int | suprt
| ) |

Open/create a named group real time heap to be shared inter-intra kernel modules and Linux processes.

For internal use only.

rt_heap_open is used to allocate open/create a shared real time heap.

Parameters:

  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

  suprt

  is the kernel allocation method to be used, it can be:
  - USE_VMALLOC, use vmalloc;
  - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
  - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
  - USE_GFP_DMA, use kmalloc with GFP_DMA.

Since name can be a clumsy identifier, services are provided to convert 6 characters identifiers to unsigned long, and vice versa.

See also:
  nam2num() and num2nam().

It must be remarked that only the very first open does a real allocation, any subsequent one with the same name from anywhere will just map the area to the user space, or return the related pointer to the already allocated memory in kernel space. In any case the functions return a pointer to the allocated memory, appropriately mapped to the memory space in use. Be careful and avoid opening more than one group heap per process/task, if more than one is opened then just the last will used.

Returns:
  a valid address on succes, 0 on failure.

void rt_hfree | ( | void * | adr | ) | `[inline]`

Free a chunk of a group real time heap.

For internal use only.

rt_hfree is used to free a previously allocated chunck of a group real time heap.

Parameters:

  | adr | is the addr of the memory to be freed.

void rt_named_free | ( | void * | adr | ) | `[inline]`

Free a named chunk of the global real time heap.

For internal use only.

rt_named_free is used to free a previously allocated chunk of the global real time heap.

Parameters:

  | adr | is the addr of the memory to be freed.

Analogously to what done by all the named allocation functions the freeing calls of named memory chunks have just the effect of decrementing its usage count, any shared piece of the global heap being freed only when the last is done, as that is the one the really frees any allocated memory. So one must be carefull not to use rt_free on a named global heap chunk, since it will force its unconditional immediate freeing.

void * rt_named_halloc | ( | unsigned long | name,
|  | int | size
| ) | `[inline]`

Allocate a chunk of a group real time heap in kernel/user space.

Since it is named it can be retrieved and shared everywhere among the group peers, i.e all processes/tasks that have opened the same group heap.

For internal use only.

rt_named_halloc is used to allocate a sharable piece of a group real time heap.

Parameters:

  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

Since name can be a clumsy identifier, services are provided to convert 6 characters identifiers to unsigned long, and vice versa.

See also:
  nam2num() and num2nam().

A process/task must have opened the real time group heap to use and can use just one real time group heap. Be careful and avoid opening more than one group real time heap per process/task. If more than one is opened then just the last will used. It must be remarked that only the very first call does a real allocation, any subsequent call with the same name will just increase the usage count and receive the appropriate pointer to the already allocated memory having the same name.

Returns:
  a valid address on succes, 0 on failure.

void rt_named_hfree | ( | void * | adr | ) | `[inline]`

Free a chunk of a group real time heap.

For internal use only.

rt_named_hfree is used to free a previously allocated chunk of the global real time heap.

Parameters:

  | adr | is the address of the memory to be freed.

Analogously to what done by all the named allocation functions the freeing calls of named memory chunks have just the effect of decrementing a usage count, any shared piece of the global heap being freed only when the last is done, as that is the one the really frees any allocated memory. So one must be carefull not to use rt_hfree on a named global heap chunk, since it will force its unconditional immediate freeing.

void * rt_named_malloc | ( | unsigned long | name,
|  | int | size
| ) | `[inline]`

Allocate a chunk of the global real time heap in kernel/user space.

Since it is named it can be retrieved and shared everywhere.

For internal use only.

rt_named_malloc is used to allocate a sharable piece of the global real time heap.

Parameters:

  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

Since name can be a clumsy identifier, services are provided to convert 6 characters identifiers to unsigned long, and vice versa.

See also:
  nam2num() and num2nam().

It must be remarked that only the very first call does a real allocation, any subsequent call to allocate with the same name will just increase the usage count and return the appropriate pointer to the already allocated memory having the same name. So if one is really sure that the named chunk has been allocated already the size parameter is not used and can be assigned any value.

Returns:
  a valid address on succes, 0 on failure.

void* rt_shm_alloc | ( | unsigned long | name,
|  | int | size,
|  | int | suprt
| ) |

Allocate a chunk of memory to be shared inter-intra kernel modules and Linux processes.

For internal use only.

rt_shm_alloc is used to allocate shared memory.

Parameters:

  | name | is an unsigned long identifier;
  | size | is the amount of required shared memory;

  suprt

  is the kernel allocation method to be used, it can be:
  - USE_VMALLOC, use vmalloc;
  - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
  - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
  - USE_GFP_DMA, use kmalloc with GFP_DMA.

Since name can be a clumsy identifier, services are provided to convert 6 characters identifiers to unsigned long, and vice versa.

See also:
  nam2num() and num2nam().

It must be remarked that only the very first call does a real allocation, any following call to allocate with the same name from anywhere will just increase the usage count and maps the area to the user space, or return the related pointer to the already allocated space in kernel space. In any case the functions return a pointer to the allocated memory, appropriately mapped to the memory space in use. So if one is really sure that the named shared memory has been allocated already parameters size and suprt are not used and can be assigned any value.

Returns:
  a valid address on succes, 0 on failure.

int rt_shm_free | ( | unsigned long | name | ) | `[inline, static]`

Free a chunk of shared memory being shared inter-intra kernel modules and Linux processes.

For internal use only.

rt_shm_free is used to free a previously allocated shared memory.

Parameters:

  | name | is the unsigned long identifier used when the memory was allocated;

Analogously to what done by all the named allocation functions the freeing calls have just the effect of decrementing a usage count, unmapping any user space shared memory being freed, till the last is done, as that is the one the really frees any allocated memory.

Returns:
  the size of the succesfully freed memory, 0 on failure.

void * rtheap_alloc | ( | rtheap_t * | heap,
|  | u_long | size,
|  | int | flags
| ) |

Allocate a memory block from a memory heap.

Allocates a contiguous region of memory from an active memory heap. Such allocation is guaranteed to be time-bounded if the heap is non-extendable (see rtheap_init()). Otherwise, it might trigger a dynamic extension of the storage area through an internal request to the Linux allocation service (kmalloc/vmalloc).

Parameters:

  | heap | The descriptor address of the heap to get memory from.
  | size | The size in bytes of the requested block. Sizes lower or equal to the page size are rounded either to the minimum allocation size if lower than this value, or to the minimum alignment size if greater or equal to this value. In the current implementation, with MINALLOC = 16 and MINALIGN = 16, a 15 bytes request will be rounded to 16 bytes, and a 17 bytes request will be rounded to 32.
  | flags | A set of flags affecting the operation. Unless RTHEAP_EXTEND is passed and the heap is extendable, this service will return NULL without attempting to extend the heap dynamically upon memory starvation.

Returns:
  The address of the allocated region upon success, or NULL if no memory is available from the specified non-extendable heap, or no memory can be obtained from Linux to extend the heap.

Side-effect: This routine does not call the rescheduling procedure.

Context: This routine can always be called on behalf of a thread context. It can also be called on behalf of an IST context if the heap storage area has been statically-defined at initialization time (see rtheap_init()).

void rtheap_destroy | ( | rtheap_t * | heap | ) |

Destroys a memory heap.

Destroys a memory heap. Dynamically allocated extents are returned to Linux.

Parameters:

  | heap | The descriptor address of the destroyed heap.

Side-effect: This routine does not call the rescheduling procedure.

Context: This routine must be called on behalf of a thread context.

int rtheap_free | ( | rtheap_t * | heap,
|  | void * | block
| ) |

Release a memory block to a memory heap.

Releases a memory region to the memory heap it was previously allocated from.

Parameters:

  | heap | The descriptor address of the heap to release memory to.
  | block | The address of the region to release returned by a previous call to rtheap_alloc().

Returns:
  0 is returned upon success, or RTHEAP_PARAM is returned whenever the block is not a valid region of the specified heap.

Side-effect: This routine does not call the rescheduling procedure.

Context: This routine can be called on behalf of a thread or IST context

int rtheap_init | ( | rtheap_t * | heap,
|  | void * | heapaddr,
|  | u_long | heapsize,
|  | u_long | pagesize
| ) |

Initialize a memory heap.

Initializes a memory heap suitable for dynamic memory allocation requests. The heap manager can operate in two modes, whether time-bounded if the heap storage area and size are statically defined at initialization time, or dynamically extendable at the expense of a less deterministic behaviour.

Parameters:

  | heap | The address of a heap descriptor the memory manager will use to store the allocation data. This descriptor must always be valid while the heap is active therefore it must be allocated in permanent memory.

  heapaddr

  The address of a statically-defined heap storage area. If this parameter is non-zero, all allocations will be made from the given area in fully time-bounded mode. In such a case, the heap is non-extendable. If a null address is passed, the heap manager will attempt to extend the heap each time a memory starvation is encountered. In the latter case, the heap manager will request additional chunks of core memory to Linux when needed, voiding the real-time guarantee for the caller.

  heapsize

  If heapaddr is non-zero, heapsize gives the size in bytes of the statically-defined storage area. Otherwise, heapsize defines the standard length of each extent that will be requested to Linux when a memory starvation is encountered for the heap. heapsize must be a multiple of pagesize and lower than 16 Mbytes. Depending on the Linux allocation service used, requests for extent memory might be limited in size. For instance, heapsize must be lower than 128Kb for kmalloc()-based allocations. In the current implementation, heapsize must be large enough to contain an internal header. The following formula gives the size of this header: hdrsize = (sizeof(rtextent_t) + ((heapsize - sizeof(rtextent_t))) / (pagesize + 1) + 15) & ~15;

  pagesize

  The size in bytes of the fundamental memory page which will be used to subdivide the heap internally. Choosing the right page size is important regarding performance and memory fragmentation issues, so it might be a good idea to take a look at http://docs.FreeBSD.org/44doc/papers/kernmalloc.pdf to pick the best one for your needs. In the current implementation, pagesize must be a power of two in the range [ 8 .. 32768] inclusive.

Returns:
  0 is returned upon success, or one of the following error codes:
  - RTHEAP_PARAM is returned whenever a parameter is invalid.
  - RTHEAP_NOMEM is returned if no initial extent can be allocated for a dynamically extendable heap (i.e. heapaddr == NULL).

Side-effect: This routine does not call the rescheduling procedure.

Context: This routine must be called on behalf of a thread context.