The pvmd and libpvm manage message buffers,
which potentially hold large amounts of dynamic data.
Buffers need to be shared efficiently,
for example, to attach a multicast message to several send queues
(see Section ).
To avoid copying,
all pointers are to a single instance of the data (a databuf),
which is
refcounted
by
allocating a few extra bytes for
an integer at the head of the data.
A pointer to the data itself is passed around,
and routines subtract
from it to access the refcount or free the block.
When the refcount of a databuf decrements to zero,
it is freed.
PVM messages are composed without declaring a maximum length ahead of time. The pack functions allocate memory in steps, using databufs to store the data, and frag descriptors to chain the databufs together.
A frag descriptor struct frag
holds a pointer (fr_dat) to a block of data
and its length (fr_len).
It also keeps a pointer (fr_buf) to the databuf
and its total length (fr_max);
these reserve space to prepend or append data.
Frags can also reference static (non-databuf) data.
A frag has link pointers so it
can be chained into a list.
Each frag keeps a count of references to it;
when the refcount decrements to zero,
the frag is freed
and the underlying databuf refcount is decremented.
In the case where a frag descriptor is the head of a list,
its refcount applies to the entire list.
When it reaches zero,
every frag in the list is freed.
Figure
shows a list of fragments storing a message.