Before proceeding with a description of the different functions in the Persistent Memory Manager API, consider the following basic restartable application, an implementation of the "hello world" example. When the process is run for the first time, it displays the following message on the host console:
Hello world! |
When the process is restarted, it will display the following message on the target console:
Hello again! I have been restarted. |
The basic flow of execution is as follows:
The restartable process begins at the start of its main() program -- initialization of program data.
The process uses the pmmAllocate(2RESTART) function to allocate a block of persistent memory. This block is used to store a status counter (which the process will set to zero).
The first message is displayed, and the counter is incremented by one.
The process attempts to access an invalid pointer value, thereby causing a crash that will require the process to be restarted. Note that the ChorusOS VIRTUAL_ADDRESS_SPACE optional feature must be set to true for this crash to be invoked.
The restarting process recommences execution at the start of its main() program, and will call pmmAllocate() a second time to retrieve the value of the status counter.
Because the counter is no longer set to zero, the process will display the second message.
The process calls pmmFree(2RESTART) to free the persistent memory block where the counter is stored, and then exits cleanly.
#include <stdio.h> #include <pmm/chPmm.h> #include <hr/hr.h> #define HR_GROUP "HELLO_GROUP" int main() { int res; int any = 1; int* counter_p; /* It will be stored in persistent memory */ long *p; PmmName name; KnRgnDesc rgn; /* * Initialize the name and medium fields * to identify the persistent memory block in the system. */ bzero(&name, sizeof(name)); strcpy(name.medium,"RAM"); strcpy(name.name,"PM1"); /* * Initialize the block fields */ bzero(&rgn, sizeof(rgn)); rgn.options = K_ANYWHERE | K_RESERVED; rgn.size = vmPageSize(); res = rgnAllocate(K_MYprocess, &rgn); if (res != K_OK) { printf("rgnAllocate() failed res=%d\n", res); HR_EXIT_HDL(); exit(-1); } p = (long*) rgn.startAddr; /* * From now on p is a bad pointer, since * VIRTUAL_ADDRESS_SPACE is true. */ /* * Allocate the persistent memory block that stores * counter_p. */ res=pmmAllocate((VmAddr *)&counter_p, &name,sizeof(int), HR_GROUP, sizeof(HR_GROUP)); if (res != K_OK) { printf("Cannot allocate or map the persistent memory block called %s." " Error = %d\n", name.name, res); HR_EXIT_HDL(); exit(-1); } /* * From the value of *counter_p the process detects * whether it has been hot restarted or not. */ if ( *counter_p==0 ) { /* * This is the first time the process is run. */ printf("Hello world!\n"); /* * Increment the counter */ (*counter_p)++; /* * Normally the next instruction causes a core dump and * a hot restart of the process */ *p = 0xDeadBeef; } else { /* * The process has been restarted * NOTE: this message will appear on the console! */ printf("The process has been restarted.\n"); /* * Free the persistent memory block before exiting */ res = pmmFree(&name); if (res != K_OK) { printf(" pmmFree failed, res=%d. Exit\n", res); HR_EXIT_HDL(); exit(-1); } /* * Terminate cleanly. */ printf("Example finished. Exit.\n"); HR_EXIT_HDL(); exit(0); } /* Never reached */ }
The aspects of this program that are of interest to users of the Persistent Memory Manager API are discussed in the rest of this section.