[Vm-dev] mmap,
changes to co-ordinate mapping to particular address to
avoid oops address remapping at startup time.
John M McIntosh
johnmci at smalltalkconsulting.com
Sat Oct 11 04:36:51 UTC 2008
In the past year or so there has been discussion of using mmap to set
a start address for the offset of object memory so that memory address
swizzling does not occur.
Also various operating systems vendors say using mmap to page in large
files is faster than using fread, this in fact is true and noticeable
on the iPhone.
This requires a change to VMMaker so that sqAllocateMemory can pass
the file pointer and the header size, since in the
sqAllocateMemory we need to figure out the file (image size) and also
understand the headersize of the image file to return a proper address
to work with.
#define sqAllocateMemory(x,y,f,headersize)
(a) map in the image file as MAP_PRIVATE (copy on write) at a set
location,
noting that on os-x mmap (file offset) does not allow for non-
multiples of page size, so we return the offset into the file as the
address.
(b) map in the free space at the page boundary rounded up based on the
file size, plus the set location. This should give two mmap memory
regions side by side.
Obvious issues, if any mmap fails we exit. We cannot be sure what will
happen for memory mapping in the future, should we attempt recover at
some other start location?
Source code below for comment.
?bug memory refers to (startOfAnonymousMemory+headersize) yet
calculation in sqGrowMemoryBy uses memory and gMaxHeapSize.
lazy adding of extra page size to freeSpaceRoundedUpToPageSize is
preventing disaster, proper fix is exercise for the reader...
extern usqInt gMaxHeapSize;
static usqInt gHeapSize;
static void *startOfmmapForANONMemory,*startOfmmapForImageFile;
static size_t fileRoundedUpToPageSize,freeSpaceRoundedUpToPageSize;
/* compute the desired memory allocation */
extern unsigned char *memory;
usqInt sqGetAvailableMemory() {
return gMaxHeapSize;
}
usqInt sqAllocateMemoryMac(sqInt minHeapSize, sqInt
*desiredHeapSize, FILE * f,usqInt headersize) {
void *possibleLocation,*startOfAnonymousMemory;
off_t fileSize;
struct stat sb;
size_t pageSize= getpagesize();
size_t pageMask= ~(pageSize - 1);
#define valign(x) ((x) & pageMask)
#pragma unused(minHeapSize,desiredHeapSize)
possibleLocation = 500*1024*1024;
gHeapSize = gMaxHeapSize;
/* Lets see about mmap the image file into a chunk of memory at the
500MB boundary rounding up to the page size
Then we on the next page anonymously allocate the required free
space for young space*/
/* Thanks to David Pennell for suggesting this */
fstat(fileno((FILE *)f), &sb);
fileSize = sb.st_size;
fileRoundedUpToPageSize = valign(fileSize+pageSize-1);
startOfAnonymousMemory = (void *) ((size_t) fileRoundedUpToPageSize
+ (size_t) possibleLocation);
startOfmmapForImageFile = mmap(possibleLocation,
fileRoundedUpToPageSize, PROT_READ|PROT_WRITE, MAP_FILE|
MAP_PRIVATE,fileno((FILE *)f), 0);
if (startOfmmapForImageFile != possibleLocation) {
fprintf(stderr, "errno %d\n", errno);
perror("startOfmmapForImageFile failed");
exit(42);
}
freeSpaceRoundedUpToPageSize = valign(gMaxHeapSize)-
fileRoundedUpToPageSize+pageSize;
startOfmmapForANONMemory = mmap(startOfAnonymousMemory,
freeSpaceRoundedUpToPageSize, PROT_READ|PROT_WRITE, MAP_ANON|
MAP_SHARED,0,0);
if (startOfmmapForANONMemory != startOfAnonymousMemory) {
fprintf(stderr, "errno %d\n", errno);
perror("startOfmmapForANONMemory failed");
exit(42);
}
return (usqInt) startOfmmapForImageFile+headersize;
}
sqInt sqGrowMemoryBy(sqInt memoryLimit, sqInt delta) {
if ((usqInt) memoryLimit + (usqInt) delta - (usqInt) memory >
gMaxHeapSize)
return memoryLimit;
gHeapSize += delta;
return memoryLimit + delta;
}
sqInt sqShrinkMemoryBy(sqInt memoryLimit, sqInt delta) {
returnsqGrowMemoryBy(memoryLimit,0-delta);
}
sqInt sqMemoryExtraBytesLeft(sqInt flag) {
return gMaxHeapSize - gHeapSize;
}
void sqMacMemoryFree() {
if (memory == NULL)
return;
munmap(startOfmmapForImageFile,fileRoundedUpToPageSize);
munmap(startOfmmapForANONMemory,freeSpaceRoundedUpToPageSize);
memory = NULL;
}
More information about the Vm-dev
mailing list