Fusion:Shared memory

Fusion shared memory is implemented in user space and is based on GNU malloc but mmaps a file on a RAM-based (tmpfs or shmfs) file system as the backing store for a shared heap. The mmap-ing is at the same starting address (0x20000000) in every process, so pointers to shared memory allocations can be passed between processes without translation.

When the direct library is built with debugging, the allocation calls are wrapped to tag each allocation with the file/line where the allocation took place, and when fusion is terminated any memory leaks are detected and reported. Macros are provided so you don’t have to be concerned whether debugging is enabled or not. The macros resemble typical memory allocation calls:

void *SHMALLOC (size); void *SHCALLOC (nmemb, size); void *SHREALLOC (ptr, size); void  SHFREE (ptr); char *SHSTRDUP (str);

There is one file-backed heap per fusion world, which is shared between all fusionees in that world. Each instance of the fusion library can access just one shared heap, so you only get to use the heap for the world you specified at initialization.

The backing file is put in the root of the first tmpfs or shmfs mountpoint found, and is named according to the fusion world number (e.g. /tmp/fusion.0). The fusion runtime configuration may specify a directory to use instead of looking for the tmpfs root, but I don’t know how to actually specify that configuration.

Each heap is initially sized at 4M (64K if integers are 16-bits or smaller) and can grow as needed at runtime up to 512M. The heap is divided into 4K “blocks” (512 bytes if integers are 16-bits or smaller). Blocks may be divided into smaller “fragments” that are some power of two in size. If a block is broken into fragments, all fragments in that block will be the same size.

Allocations larger than half a block will get one or more whole blocks. If the required number of contiguous free blocks aren’t available, the heap will grow to create them. Smaller allocations get a single fragment that is the smallest power of two big enough to hold the requested size. (e.g. an allocation of 200 bytes will use a 256-byte fragment) If no fragments of the appropriate size exist, a block will be allocated and broken into fragments of the required size.

There’s some code to "cure" bad memory accesses by mremap-ing in a larger file as needed, but I’m not clear on when this actually happens since it seems like the file is mremap-ed already when allocations are made. ??? I guess this happens when pointers are shared across processes.

Shared memory only makes sense in the multi-app configuration, and won’t work in the single app configuration since no attempt will be made to mmap any heap.