| /* |
| MacOS.c |
| |
| Some routines for the Macintosh OS port of the Hans-J. Boehm, Alan J. Demers |
| garbage collector. |
| |
| <Revision History> |
| |
| 11/22/94 pcb StripAddress the temporary memory handle for 24-bit mode. |
| 11/30/94 pcb Tracking all memory usage so we can deallocate it all at once. |
| 02/10/96 pcb Added routine to perform a final collection when |
| unloading shared library. |
| |
| by Patrick C. Beard. |
| */ |
| /* Boehm, February 15, 1996 2:55 pm PST */ |
| |
| #include <Resources.h> |
| #include <Memory.h> |
| #include <LowMem.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "gc.h" |
| #include "gc_priv.h" |
| |
| // use 'CODE' resource 0 to get exact location of the beginning of global space. |
| |
| typedef struct { |
| unsigned long aboveA5; |
| unsigned long belowA5; |
| unsigned long JTSize; |
| unsigned long JTOffset; |
| } *CodeZeroPtr, **CodeZeroHandle; |
| |
| void* GC_MacGetDataStart() |
| { |
| CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0); |
| if (code0) { |
| long belowA5Size = (**code0).belowA5; |
| ReleaseResource((Handle)code0); |
| return (LMGetCurrentA5() - belowA5Size); |
| } |
| fprintf(stderr, "Couldn't load the jump table."); |
| exit(-1); |
| return 0; |
| } |
| |
| /* track the use of temporary memory so it can be freed all at once. */ |
| |
| typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle; |
| |
| struct TemporaryMemoryBlock { |
| TemporaryMemoryHandle nextBlock; |
| char data[]; |
| }; |
| |
| static TemporaryMemoryHandle theTemporaryMemory = NULL; |
| static Boolean firstTime = true; |
| |
| void GC_MacFreeTemporaryMemory(void); |
| |
| Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory) |
| { |
| static Boolean firstTime = true; |
| OSErr result; |
| TemporaryMemoryHandle tempMemBlock; |
| Ptr tempPtr = nil; |
| |
| tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result); |
| if (tempMemBlock && result == noErr) { |
| HLockHi((Handle)tempMemBlock); |
| tempPtr = (**tempMemBlock).data; |
| if (clearMemory) memset(tempPtr, 0, size); |
| tempPtr = StripAddress(tempPtr); |
| |
| // keep track of the allocated blocks. |
| (**tempMemBlock).nextBlock = theTemporaryMemory; |
| theTemporaryMemory = tempMemBlock; |
| } |
| |
| # if !defined(SHARED_LIBRARY_BUILD) |
| // install an exit routine to clean up the memory used at the end. |
| if (firstTime) { |
| atexit(&GC_MacFreeTemporaryMemory); |
| firstTime = false; |
| } |
| # endif |
| |
| return tempPtr; |
| } |
| |
| extern word GC_fo_entries; |
| |
| static void perform_final_collection() |
| { |
| unsigned i; |
| word last_fo_entries = 0; |
| |
| /* adjust the stack bottom, because CFM calls us from another stack |
| location. */ |
| GC_stackbottom = (ptr_t)&i; |
| |
| /* try to collect and finalize everything in sight */ |
| for (i = 0; i < 2 || GC_fo_entries < last_fo_entries; i++) { |
| last_fo_entries = GC_fo_entries; |
| GC_gcollect(); |
| } |
| } |
| |
| |
| void GC_MacFreeTemporaryMemory() |
| { |
| # if defined(SHARED_LIBRARY_BUILD) |
| /* if possible, collect all memory, and invoke all finalizers. */ |
| perform_final_collection(); |
| # endif |
| |
| if (theTemporaryMemory != NULL) { |
| long totalMemoryUsed = 0; |
| TemporaryMemoryHandle tempMemBlock = theTemporaryMemory; |
| while (tempMemBlock != NULL) { |
| TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock; |
| totalMemoryUsed += GetHandleSize((Handle)tempMemBlock); |
| DisposeHandle((Handle)tempMemBlock); |
| tempMemBlock = nextBlock; |
| } |
| theTemporaryMemory = NULL; |
| |
| # if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD) |
| fprintf(stdout, "[total memory used: %ld bytes.]\n", |
| totalMemoryUsed); |
| fprintf(stdout, "[total collections: %ld.]\n", GC_gc_no); |
| # endif |
| } |
| } |
| |
| #if __option(far_data) |
| |
| void* GC_MacGetDataEnd() |
| { |
| CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0); |
| if (code0) { |
| long aboveA5Size = (**code0).aboveA5; |
| ReleaseResource((Handle)code0); |
| return (LMGetCurrentA5() + aboveA5Size); |
| } |
| fprintf(stderr, "Couldn't load the jump table."); |
| exit(-1); |
| return 0; |
| } |
| |
| #endif /* __option(far_data) */ |