Example of Creating and Using a Shared-Memory User Heap

The following program shows how you might implement a heap shared between a parent and several child processes.

Example of a User Heap - Parent Process shows the parent process, which creates the shared heap. First the main program calls the init function to allocate shared memory from the operating system (using CreateFileMapping) and name the memory so that other processes can use it by name. The init function then creates and opens the heap. The loop in the main program performs operations on the heap, and also starts other processes. The program then calls the term function to close and destroy the heap.

Example of a Shared User Heap- Child Process shows the process started by the loop in the parent process. This process uses OpenFileMapping to access the shared memory by name, then extracts the heap handle for the heap created by the parent process. The process then opens the heap, makes it the default heap, and performs some operations on it in the loop. After the loop, the process replaces the old default heap, closes the user heap, and ends.

 

Example of a User Heap - Parent Process

/* The following program shows how you might implement
 a heap shared between a parent and several child processes.

 Example of a Shared User Heap - Parent Process shows the parent
 process, which creates the shared heap. First
 the main program calls the init function to allocate shared memory from the operating system (using
 CreateFileMapping) and name the memory so that other processes can use it by name. The init function
 then creates and opens the heap. The loop in the main program performs operations on the heap, and also
 starts other processes. The program then calls the term function to close and destroy the heap.

 */

 #include <umalloc.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 #define PAGING_FILE  0xFFFFFFFF
 #define MEMORY_SIZE  65536
 #define BASE_MEM     (VOID*)0x01000000

 static HANDLE hFile;       /* Handle to memory file                       */
 static void*  hMap;        /* Handle to allocated memory                  */

 typedef struct mem_info {
    void  * pBase;
    Heap_t  pHeap;
 } MEM_INFO_T;

 /*------------------------------------------------------------------------*/
 /* inithp:                                                                */
 /* Function to create and open the heap with a named shared memory object */
 /*------------------------------------------------------------------------*/
 static Heap_t inithp(size_t heap_size)
 {
    MEM_INFO_T info;                       /* Info structure               */

    /* Allocate shared memory from the system by creating a shared memory  */
    /* pool basing it out of the system paging (swapper) file.             */

    hFile = CreateFileMapping( (HANDLE) PAGING_FILE,
                                NULL,
                                PAGE_READWRITE,
                                0,
                                heap_size + sizeof(Heap_t),
                                "MYNAME_SHAREMEM" );
    if (hFile == NULL) {
      return NULL;
    }

    /* Map the file to this process' address space, starting at an address  */
    /* that should also be available in child processe(s)                   */

    hMap = MapViewOfFileEx( hFile, FILE_MAP_WRITE, 0, 0, 0, BASE_MEM );

    info.pBase = hMap;
    if (info.pBase == NULL) {
      return NULL;
    }

    /* Create a fixed sized heap.  Put the heap handle as well as the      */
    /* base heap address at the beginning of the shared memory.            */

    info.pHeap = _ucreate((char *)info.pBase + sizeof(info),
                     heap_size - sizeof(info),
                     !_BLOCK_CLEAN,
                     _HEAP_SHARED | _HEAP_REGULAR,
                     NULL, NULL);

     if (info.pBase == NULL) {
       return NULL;
     }

    memcpy(info.pBase, info, sizeof(info));

    if (_uopen(info.pHeap)) {            /* Open heap and check result    */
       return NULL;
    }

    return info.pHeap;

 }

 /*------------------------------------------------------------------------*/
 /* termhp:                                                                */
 /* Function to close and destroy the heap                                 */
 /*------------------------------------------------------------------------*/
 static int termhp(Heap_t uheap)
 {
    if (_uclose(uheap))                       /* close heap                */
       return 1;
    if (_udestroy(uheap, _FORCE))             /* force destruction of heap */
       return 1;

    UnmapViewOfFile(hMap);                    /* return memory to system   */
    CloseHandle(hFile);

    return 0;
 }

 /*------------------------------------------------------------------------*/
 /* main:                                                                  */
 /* Main function to test creating, writing to and destroying a shared     */
 /* heap.                                                                  */
 /*------------------------------------------------------------------------*/
 int main(void)
 {
    int i, rc;                            /* Index and return code          */
    Heap_t uheap;                         /* heap to create                 */
    void *init_block;                     /* initial block to use           */
    char *p;                              /* for allocating from heap       */

    /*                                                                      */
    /* call init function to create and open the heap                       */
    /*
    uheap = inithp(MEMORY_SIZE);
    if (uheap == NULL)                    /* check for success              */
       return 1;                          /* if failure, return non zero    */

    /*                                                                      */
    /* perform operations on uheap                                          */
    /*                                                                      */
    for (i = 1; i <= 5; i++)
    {
       p = _umalloc(uheap, 10);           /* allocate from uheap            */
       if (p == NULL)
          return 1;
       memset(p, 'M', _msize(p));         /* set all bytes in p to 'M'      */
       p = realloc(p,50);                 /* reallocate from uheap          */
       if (p == NULL)
          return 1;
       memset(p, 'R', _msize(p));         /* set all bytes in p to 'R'      */
    }

    /*                                                                      */
    /* Start a second process which accesses the heap                       */
    /*                                                                      */
    if (system("memshr2.exe"))
      return 1;

    /*                                                                      */
    /* Take a look at the memory that we just wrote to. Note that memshr.c  */
    /* and memshr2.c should have been compiled specifying the /Tm+ flag.    */
    /*                                                                      */
    #ifdef DEBUG
      _udump_allocated(uheap, -1);
    #endif

    /*                                                                      */
    /* call term function to close and destroy the heap                     */
    /*                                                                      */
    rc = termhp(uheap);

    #ifdef DEBUG
      printf("memshr ending... rc = %d\n", rc);
    #endif

    return rc;
}

 

Example of a Shared User Heap - Child Process

/* Example of a Shared User Heap - Child Process shows
   the process started by the loop in the parent process.
   This process uses OpenFileMapping to access the shared memory
   by name, then extracts the heap handle for the heap created
   by the parent process. The process then opens the heap,
   makes it the default heap, and performs some operations
   on it in the loop. After the loop, the process replaces
   the old default heap, closes the user heap, and ends.


 */

 #include <umalloc.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 static HANDLE hFile;       /* Handle to memory file                       */
 static void*  hMap;        /* Handle to allocated memory                  */

 typedef struct mem_info {
    void  * pBase;
    Heap_t  pHeap;
 } MEM_INFO_T;

 /*------------------------------------------------------------------------*/
 /* inithp:  Subprocess Version                                            */
 /* Function to create and open the heap with a named shared memory object */
 /*------------------------------------------------------------------------*/
 static Heap_t inithp(void)
 {

    MEM_INFO_T info;                       /* Info structure               */

    /* Open the shared memory file by name.  The file is based on the      */
    /* system paging (swapper) file.                                       */

    hFile = OpenFileMapping(FILE_MAP_WRITE, FALSE, "MYNAME_SHAREMEM");

    if (hFile == NULL) {
      return NULL;
    }

    /* Figure out where to map this file by looking at the address in the   */
    /* shared memory where the memory was mapped in the parent process.     */

    hMap = MapViewOfFile( hFile, FILE_MAP_WRITE, 0, 0, sizeof(info) );

    if (hMap == NULL) {
      return NULL;
    }

    /* Extract the heap and base memory address from shared memory          */

    memcpy(info, hMap, sizeof(info));
    UnmapViewOfFile(hMap);

    hMap = MapViewOfFileEx( hFile, FILE_MAP_WRITE, 0, 0, 0, info.pBase );

    if (_uopen(info.pHeap)) {          /* Open heap and check result       */
       return NULL;
    }

    return info.pHeap;
 }

 /*------------------------------------------------------------------------*/
 /* termhp:                                                                */
 /* Function to close my view of the heap                                  */
 /*------------------------------------------------------------------------*/
 static int termhp(Heap_t uheap)
 {
    if (_uclose(uheap))                       /* close heap                */
       return 1;

    UnmapViewOfFile(hMap);                    /* return memory to system   */
    CloseHandle(hFile);

    return 0;
 }

 /*------------------------------------------------------------------------*/
 /* main:                                                                  */
 /* Main function to test creating, writing to and destroying a shared     */
 /* heap.                                                                  */
 /*------------------------------------------------------------------------*/
 int main(void)
 {
    int rc, i;                      /* for return code, loop iteration    */
    Heap_t uheap, oldheap;          /* heap to create, old default heap   */
    char *p;                        /* for allocating from the heap       */

    /*                                                                    */
    /* Get the heap storage from the shared memory                        */
    /*                                                                    */
    uheap = inithp();
    if (uheap == NULL)
      return 1;

    /*                                                                    */
    /* Register uheap as default runtime heap, save old default           */
    /*                                                                    */
    oldheap = _udefault(uheap);
    if (oldheap == NULL) {
       return termhp(uheap);
}

    /*                                                                    */
    /* Perform operations on uheap                                        */
    /*                                                                    */
    for (i = 1; i <= 5; i++)
    {
       p = malloc(10);     /* malloc uses default heap, which is now uheap*/
       memset(p, 'M', _msize(p));
    }

    /*                                                                    */
    /* Replace original default heap and check result                     */
    /*                                                                    */
    if (uheap != _udefault(oldheap)) {
       return termhp(uheap);
}

    /*                                                                    */
    /* Close my views of the heap                                         */
    /*                                                                    */
    rc = termhp(uheap);

    #ifdef DEBUG
      printf("Returning from memshr2 rc = %d\n", rc);
    #endif
    return rc;

 }


Memory Management Functions
Managing Memory with Multiple Memory Heaps
Types of Memory
Debugging Memory Heaps


Creating and Using a Fixed Size Heap
Creating and Using an Expandable Heap
Debugging Problems with Heap Memory
Changing the Default Heap Used in a Program
Example of Creating and Using a User Heap