On 24-Jul-09, at 3:42 PM, Eliot Miranda wrote:
...stinks.
I'm talking about sqAllocateMemory. Here's the base definition from platforms/Cross/vm/sq.h:
#define sqAllocateMemory(minHeapSize, desiredHeapSize) malloc(desiredHeapSize)
The problem here is that there's no obvious way for the client to know how much memory is returned. The signature implies it is somewhere between minHeapSize & desiredHeapSize inclusive (or null, if allocation failed). But how do you tell? Well, one could always ask to grow memory by 0 and see what you get back, except for the small chicken-and-egg problem that sqGrowMemory:By: and sqShrinkMemory:By: require the ammount of memory allocated as an argument:
#define sqGrowMemoryBy(oldLimit, delta) oldLimit #define sqShrinkMemoryBy(oldLimit, delta) oldLimit
So one has to go to extraordinary lengths that are completely non- obvious in the client code to actually pass-back the ammount allocated. Here's a client in readImageFromFile:
"allocate a contiguous block of memory for the Squeak heap" memory := self cCode: 'sqAllocateMemory(minimumMemory,
heapSize)'. memory = nil ifTrue: [self insufficientMemoryAvailableError].
memStart := self startOfMemory. self setMemoryLimit: (memStart + heapSize) - 24. "decrease
memoryLimit a tad for safety" self setEndOfMemory: memStart + dataSize.
Somehow that looks dated? Since it now reads
"allocate a contiguous block of memory for the Squeak heap" memory := self allocateMemory: heapSize minimum: minimumMemory imageFile: f headerSize: headerSize. memory = nil ifTrue: [self insufficientMemoryAvailableError].
which turns into
memory = allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, f, headerSize); if (memory == null) { insufficientMemoryAvailableError(); }
which is #define allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, fileStream, headerSize) \ sqAllocateMemory(minimumMemory, heapSize) #endif
but on iPhone and mac is
#define allocateMemoryMinimumImageFileHeaderSize(heapSize, minimumMemory, fileStream, headerSize) \ sqAllocateMemoryMac(heapSize, minimumMemory, fileStream, headerSize)
and
sqAllocateMemoryMac
On the iPhone let's you vmap in the image from offset 500*1024*1024 plus header size to the size of the image file rounded up 4K pages. After that the free space is mmap anonymous upto the total heapsize, we ignore minimumMemory. For WikiServer a 10MB image, then 6MB gets paged in from flash, 4MB is not touched. The sqImageFileReadEntireImage does nothing.
On the macintosh the total heap size is mmapped anonymously at the 500*1024*1024 boundary plus header size, the sqImageFileReadEntireImage then reads the image file into the mmap region. I note that I had the same code here from the iPhone but it was discovered there is a bug with mmapped files being read from NFS disks so the feature was made optional. It does btw save a few 100 ms at startup time on slower machines (500 Mhz) But the macintosh virtual memory system does read all the pages from the file into RAM, versus the iPhone which does not. -- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================