Extending xdc.runtime Memory

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  [offline version]offline version generated on 24-Feb-2019 01:02 UTC 

Extending xdc.runtime Memory

How to create customized heap managers

Contents

Introduction

The xdc.runtime package contains several modules that work together to provide modular and extensible memory management support. This support is centered around the Memory module that enables the application to allocate and free memory. All memory allocations are eventually "handled" by a module that implements the IHeap interface. These modules are responsible for managing a region of memory in a manner appropriate for the application.

Two such modules are provided in the xdc.runtime package:

  1. HeapMin - a module that simply maintains a "high water" mark for each managed memory block and never frees memory, and
  2. HeapStd - a module that uses the ANSI C Standard Library functions malloc() and free().

In addition, it is possible to create new implementations of the IHeap interface that provide more sophisticated or even application-specific memory management policies. For example, a heap may limit the memory allocated by specific tasks, monitor ownership of each memory block (to allow reclamation of memory from terminated threads), and even implement custom allocation algorithms to minimize fragmentation (first-fit, best-fit, etc.).

In the following sections we focus on how to use and create modules that implement the IHeap interface.

Overview

Memory management in embedded systems, especially DSPs with their high-speed but relatively small on-chip memories and lack of virtual memory, can be a critical factor in getting full entitlement from the hardware. The performance difference between on-chip static RAM and external dynamic RAM makes it especially important that the on-chip memory be allocated only to the performance critical portions of a system. But, from the point of view of an individual module, it's often not be possible to know in advance whether the module's memory should be in on-chip memory or in bulk external memory; two different applications may have very different usages of the module. As a result, it's important that the system integrator have control over the management of each module's data memory placement.

The xdc.runtime memory architecture enables developers to write their code once, deliver modules in binary form, and still allow the system integrator to, on a per module basis,

  • monitor and track allocations,
  • control the type and amount of memory allocated, and
  • select alternate allocation strategies, striking a balance between deterministic performance and minimal fragmentation loss.

In other words, modules can be written once, delivered in binary form, and be reused in virtually any application without limiting the flexibility required by system integrators to get full entitlement from their unique hardware platform.

Architecture

The Memory module provides an interface that allows any client code to allocate and free memory. However, each Memory function is passed a handle of a heap instance and it is this instance that performs the requested service. As a result, each heap can manage a different memory space, such as on-chip DARAM or external bulk DDR memory, using unique allocation and management algorithms, such as fixed-length deterministic or variable-length first-fit allocation.

All "heaps" are modules that implement the IHeap interface. The relationship between heaps and the Memory module is depicted in the figure below.

Memory Architecture

Using each heap instance to reference the actual memory management code provides a great deal of flexibility, but now clients have to pass an IHeap instance object on each allocation. Since these handles are heap-specific, it appears that clients must tie themselves to a specific heap - defeating the goal of keeping the clients unaware of any particular heap manager. To solve this problem and enable client code to be 100% independent of the heaps it uses, it is possible to pass NULL as a heap instance handle and, in this case, the distinguished heap instance defined by the Memory.defaultHeapInstance configuration parameter is used.

In addition, every module that supports instances has a unique heap instance, a "generic" means to get this heap, and a means for the system integrator to define this heap at configuration time. These RTSC modules reference their configured heap instance from the module's C code using Mod_Object_heap() where Mod is the name of the module.

Of course, most systems do not create a unique heap for each module but, as we'll see in the examples, the ability to associate a unique heap for selected modules can be extremely useful. Not only is it possible to control or redirect access to various memories within different sub-systems of an application, but you can also "chain" heaps to provide sophisticated application-specific memory validation atop any other heap manager (see Example 1).

Configuration

Since heaps are often required very early during runtime startup, they are usually created at configuration time. The most common configuration, illustrated in the figure below, is to have a single heap for the entire application. In this figure, the application consists of the modules xdc.runtime.Main, xdc.runtime.Memory, an IHeap manager (xdc.runtime.HeapStd), and some number of modules Mod0 through ModN, where xdc.runtime.Main represents all code not in any module and HeapStd is a module that implements the xdc.runtime.IHeap interface.

Image:RuntimeHeapConfig.png

Notice that if the heap instance passed to Memory is NULL, the Memory.defaultHeapInstance configuration parameter is used. In addition, the default value of the Memory.defaultHeapInstance configuration parameter is an instance of xdc.runtime.HeapStd created with Memory.defaultHeapSize MAUS of capacity. Because of these defaults, the configuration script that corresponds to the figure above is quite simple.

app.cfg
 
var Memory = xdc.useModule("xdc.runtime.Memory");

In fact, the configuration script above is equivalent to the more explicit script shown below. We show this more explicit script because it hints at the some powerful capabilities provided to the system integrator with respect to controlling each part of a system's access to and use of memory.

app.cfg
 
 
 
 
 
var Memory = xdc.useModule("xdc.runtime.Memory");
var HeapStd = xdc.useModule("xdc.runtime.HeapStd");
var params = new HeapStd.Params;
params.size = Memory.defaultHeapSize;
Memory.defaultHeapInstance = HeapStd.create(params);

Suppose, for example, you want to use standard variable-length memory allocations in an existing code base but you want to limit all RTSC modules to a simple deterministic growth-only memory manager. The following configuration script can be used to achive this effect.

twoHeaps.cfg
 
 
 
 
 
 
var Memory = xdc.useModule("xdc.runtime.Memory");
var Defaults = xdc.useModule("xdc.runtime.Defaults");
var HeapMin = xdc.useModule("xdc.runtime.HeapMin");
var params = new HeapMin.Params;
params.size = Memory.defaultHeapSize;
Defaults.common$.heap = HeapMin.create(params);

This configuration script results in a configuration depicted in the figure below. As with the first example, even though HeapStd is not directly named in the configuration script, it is part of the configuration because the Memory.defaultHeapInstance is not set by the script.

Image:Runtime2HeapConfig.png

Examples

The best way to understand how to use and create new heap managers is to study some simple examples. In the table below, we list examples that illustrate the key requirements of heap managers and provide links to more advanced topics.

Examples Description Purpose
Example 1 Simple heap monitor illustrate the ability to add custom heap management without changing any existing sources

Related Topics

Using the Runtime Memory Manager

[printable version]  [offline version]offline version generated on 24-Feb-2019 01:02 UTC 
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Personal tools
package reference