|
Introduction
PUPS/P3 implements threadsafe shared heaps (see the code
fragment below), which are a form of
persistent object store. Objects may be created on these
heaps using
malloc semantics (in fact the PUPS/P3 shmheap library is based on
GNU-malloc but uses
mmap rather than
brk
to extend the heap and objects
within it). PUPS/P3 processes
may map multiple shared heaps into their
address spaces.
Objects created by one process (which is attached to the heap) will
be seen by all other client processes which are attached to it. Exclusive
access to objects in the shared heaps (by a given client) is provided using
a combination of
semaphores and
NFS
file locking.
Mechanism
PUPS/P3 shared heaps are based on Mike Haertel's GNU-malloc implementation.
PUPS/P3 shared heaps are thread/process safe and may be simultaneously mapped into
the address spaces of many processes. If backing store for the shared heap resides on a
network filesytem (e.g.
NFS or MFS), these processes may reside on any host which
elects to mount that file system. Furthermore, it is possible to use 32 bit shared heaps
on 64 bit architectures (e.g.
Alpha or
X86_64). This means that 32 and 64 bit hosts can share
common persistent objects.
|
Schematic of a shared heap. Note the the processes mapping the heap objects may be resident on different physical
hosts and that a given process may map multiple heap objects.
|
Because of the way that
mmap works, the location of the shared
heap (in the address space of a process which has attached it) is not known until it is
mapped. Because of this, shared heaps maintain a table of the objects which they contain.
When the heap is mapped into the process address space, the appropriate offsets are added
to the addresses of objects in the heap, so they appear at the correct addresses in the
address space of all the processes which have mapped them.
In addition to maintaining a list of addresses for heap objects PUPS/P3 shared heaps also
maintain a list of names; Routines are provided in the shared heap library
to translate between these names and the addresses of the objects on the (mapped) heap.
An information table is also provided so the types of heap objects (and any other information
which may be required by a process attaching a heap is available to it).
The code fragment below should give some insight into how shared heaps may be used
within PUPS/P3 applications.
/* Lets attach a shared heap */
if((hdes = msm_heap_attach("heap1",
O_RDWR | O_CREAT,
PROT_READ | PROT_WRITE,
MAP_SHARED,
LIVE)) == (-1))
pups_exit(-1);
/* And another */
/*if(msm_heap_attach("heap2",
O_RDWR | O_CREAT,
PROT_READ | PROT_WRITE,
MAP_SHARED,
LIVE) == (-1))
pups_exit(-1);
*/
/* And another */
/*if(msm_heap_attach("heap3",
O_RDWR | O_CREAT,
PROT_READ | PROT_WRITE,
MAP_SHARED,
LIVE) == (-1))
pups_exit(-1);
*/
/* Allocate some objects on the first shared heap */
if(shmalloc(hdes,260000,"object1") == (void *)NULL)
{ fprintf(stderr,"test: failed to allocated shared heap object (%s)\n","object1");
fflush(stderr);
/* If this object already exists - which is the reason that the */
/* attempt to allocate it failed, lets take a look at the shared */
/* memory associated with it */
h_ptr_1 = msm_lockobjectname(hdes,F_LOCK,"object1",WRITE);
fprintf(stderr,"INITIAL VALUE: %s\n",h_ptr_1,h_ptr_1);
msm_lockobjectname(hdes,F_ULOCK,"object1",READ);
}
if(shmalloc(hdes,55000,"object2") == (void *)NULL)
{ fprintf(stderr,"test: failed to allocated shared heap object (%s)\n","object2");
fflush(stderr);
}
/* Remove the object "object2" from the shared heap "heap1" */
h_ptr_1 = msm_lockobjectname(hdes,F_LOCK,"object2",READWRITE);
(void)shfree(hdes,h_ptr_1);
/* And add another shared object */
if(shmalloc(hdes,355000,"object3") == (void *)NULL)
{ fprintf(stderr,"test: failed to allocated shared heap object (%s)\n","object3");
fflush(stderr);
}
/* Display the current objects and clients */
(void)map_show(hdes,stderr);
(void)client_show(hdes,stderr);
/* This loop repeatedly locks an object on the shared */
/* heap "heap1", updates it, and then unlcoks it (so other */
/* clients of the heap can access it) */
while(1)
{ char strdum[256];
unsigned long ldum;
int i,
idum;
/* Update shared heap object "object1" on heap "heap1" */
/* Lock "object1" and return a (local) pointer to it */
h_ptr_1 = msm_lockobjectname(hdes,F_LOCK,"object1",READWRITE);
/* Update "object1" */
(void)sscanf(h_ptr_1,"%s %s %s %s %s %d",
strdum,strdum,strdum,strdum,strdum,&cnt);
(void)sprintf(h_ptr_1,"[0x%x] %s [%d@%s] cnt is %d!",
(unsigned long)h_ptr_1,appl_name,appl_pid,appl_host,++cnt);
fprintf(stderr,"%s\n",h_ptr_1);
fflush(stderr);
(void)usleep(100);
/* Unlock "object1" so other clients can access it */
(void)msm_lockobjectname(hdes,F_ULOCK,"object1",READWRITE);
(void)usleep(10);
}
|
PUPS/P3 (c) Mark A. O'Neill 2007
|