ChorusOS 4.0 Hot Restart Programmer's Guide

3.3 Allocating and Retrieving a Persistent Memory Block

The "hello world" application uses a block of persistent memory to store a counter indicating whether it has been restarted. The value of the counter controls the program's flow of execution. This is a very common use of persistent memory. A counter or flag such as this is usually necessary as it is the only way an actor can know whether it has been restarted.

A block of persistent memory is described in the system by a structure of the following type:

#include <chPmm.h> 
typedef struct { PmmMedium   medium = "RAM";
                 PmmMemName  name; } 
PmmName;

Within the structure, medium is a character string which identifies the memory bank to be used. In the current implementation, it must always be set to RAM. name is a user-defined, null-terminated character string which uniquely identifies the block of memory in the memory bank. The lifetime of a block name is the same as the lifetime of the block itself in persistent memory. A system tunable parameter, pmm.maxBlocks, defines the number of distinct persistent memory blocks (and therefore names) which can be allocated at any one time. The default value is 30.


Caution - Caution -

Sharing persistent memory blocks between user actors, or between user and supervisor actors is not supported. Persistent memory blocks can only be shared between supervisor actors.


To allocate a block of persistent memory, or retrieve a block of memory which has already been allocated, use the pmmAllocate() function call, defined as follows:

#include <chPmm.h>
KnError pmmAllocate(  VmAddr     *addr,
                      PmmName    *name,
                      size_t      size,
                      PmmDelKey   delKey,
                      size_t      delKeySize);

If no memory block corresponding to the specified PmmName structure is present in persistent memory, pmmAllocate() allocates a block of size size in persistent memory, fills it with nulls, and returns the pointer *addr to the address of the block. The address is determined by the system and cannot be specified or changed.

If a block identified with the specified PmmName already exists in persistent memory, pmmAllocate() simply returns a pointer to the existing memory block as an address (*addr), and the size parameter is ignored. Persistent memory blocks are always mapped at the same address. In other words, the address returned by the first and subsequent calls to pmmAllocate() is always the same for a given block.

As a result of this dual functionality of the pmmAllocate() call, the difference between initially allocating and subsequently retrieving a persistent memory block is transparent at the programming level. The first time the code of the "hello world" example is executed, the call to pmmAllocate() allocates an integer-sized block of persistent memory which contains the initialized value of counter (0).

res=pmmAllocate((VmAddr *)&counter_p,
                        &name,sizeof(int),
                        HR_GROUP,
                        sizeof(HR_GROUP));

The second time the code is executed, the same function call returns a pointer to the value of counter in persistent memory.

The delKey and delKeySize parameters passed to pmmAllocate() are used to define the deletion key associated with the memory block. A deletion key is a user-defined binary array, used to mark a set of persistent memory blocks which can be freed simultaneously, using the pmmFreeAll() function, described in "3.4.2 Freeing a Persistent Memory Block Explicitly".