The program below shows how you might create and use a heap that uses regular memory.
#include <stdlib.h>
#include <stdio.h>
#include <umalloc.h>
static void *get_fn(Heap_t usrheap, size_t *length, int *clean)
{
void *p;
/* Round up to the next chunk size */
*length = ((*length) / 65536) * 65536 + 65536;
*clean = _BLOCK_CLEAN;
p = calloc(*length,1);
return (p);
}
static void release_fn(Heap_t usrheap, void *p, size_t size)
{
free( p );
return;
}
int main(void)
{
void *initial_block;
long rc;
Heap_t myheap;
char *ptr;
int initial_sz;
/* Get initial area to start heap */
initial_sz = 65536;
initial_block = malloc(initial_sz);
if(initial_block == NULL) return (1);
/* create a user heap */
myheap = _ucreate(initial_block, initial_sz, _BLOCK_CLEAN,
_HEAP_REGULAR, get_fn, release_fn);
if (myheap == NULL) return(2);
/* allocate from user heap and cause it to grow */
ptr = _umalloc(myheap, 100000);
_ufree(ptr);
/* destroy user heap */
if (_udestroy(myheap, _FORCE)) return(3);
/* return initial block used to create heap */
free(initial_block);
return 0;
}
The following program shows how you might implement a heap shared between a parent and several child processes. This program 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 */
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 */
/* alloc(debug[, yes]) 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;
}
The following program 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;
}