Back to index

lightning-sunbird  0.9+nobinonly
MacOS.c
Go to the documentation of this file.
00001 /*
00002        MacOS.c
00003        
00004        Some routines for the Macintosh OS port of the Hans-J. Boehm, Alan J. Demers
00005        garbage collector.
00006        
00007        <Revision History>
00008        
00009        11/22/94  pcb  StripAddress the temporary memory handle for 24-bit mode.
00010        11/30/94  pcb  Tracking all memory usage so we can deallocate it all at once.
00011        02/10/96  pcb  Added routine to perform a final collection when
00012 unloading shared library.
00013        
00014        by Patrick C. Beard.
00015  */
00016 /* Boehm, February 15, 1996 2:55 pm PST */
00017 
00018 #include <Resources.h>
00019 #include <Memory.h>
00020 #include <LowMem.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 
00025 #include "gc.h"
00026 #include "gc_priv.h"
00027 
00028 void GC_init_MacOS()
00029 {
00030     int i;
00031     
00032     MaxApplZone();
00033     for (i = 0; i < 8; ++i)
00034         MoreMasters();
00035 }
00036 
00037 // use 'CODE' resource 0 to get exact location of the beginning of global space.
00038 
00039 typedef struct {
00040        unsigned long aboveA5;
00041        unsigned long belowA5;
00042        unsigned long JTSize;
00043        unsigned long JTOffset;
00044 } *CodeZeroPtr, **CodeZeroHandle;
00045 
00046 void* GC_MacGetDataStart()
00047 {
00048        CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
00049        if (code0) {
00050               long belowA5Size = (**code0).belowA5;
00051               ReleaseResource((Handle)code0);
00052               return (LMGetCurrentA5() - belowA5Size);
00053        }
00054        fprintf(stderr, "Couldn't load the jump table.");
00055        exit(-1);
00056        return 0;
00057 }
00058 
00059 /* track the use of temporary memory so it can be freed all at once. */
00060 
00061 typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle;
00062 
00063 struct TemporaryMemoryBlock {
00064        TemporaryMemoryHandle nextBlock;
00065        char data[];
00066 };
00067 
00068 static TemporaryMemoryHandle theTemporaryMemory = NULL;
00069 static Boolean firstTime = true;
00070 
00071 void GC_MacFreeTemporaryMemory(void);
00072 
00073 Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
00074 {
00075        static Boolean firstTime = true;
00076        OSErr result;
00077        TemporaryMemoryHandle tempMemBlock;
00078        Ptr tempPtr = nil;
00079 
00080        tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result);
00081        if (tempMemBlock && result == noErr) {
00082               HLockHi((Handle)tempMemBlock);
00083               tempPtr = (**tempMemBlock).data;
00084               if (clearMemory) memset(tempPtr, 0, size);
00085               tempPtr = StripAddress(tempPtr);
00086 
00087               // keep track of the allocated blocks.
00088               (**tempMemBlock).nextBlock = theTemporaryMemory;
00089               theTemporaryMemory = tempMemBlock;
00090        }
00091        
00092 #     if !defined(SHARED_LIBRARY_BUILD)
00093        // install an exit routine to clean up the memory used at the end.
00094        if (firstTime) {
00095               atexit(&GC_MacFreeTemporaryMemory);
00096               firstTime = false;
00097        }
00098 #     endif
00099        
00100        return tempPtr;
00101 }
00102 
00103 extern word GC_fo_entries; 
00104 
00105 static void perform_final_collection()
00106 {
00107   unsigned i;
00108   word last_fo_entries = 0;
00109   
00110   /* adjust the stack bottom, because CFM calls us from another stack
00111      location. */
00112      GC_stackbottom = (ptr_t)&i;
00113 
00114   /* try to collect and finalize everything in sight */
00115     for (i = 0; i < 2 || GC_fo_entries < last_fo_entries; i++) {
00116         last_fo_entries = GC_fo_entries;
00117         GC_gcollect();
00118     }
00119 }
00120 
00121 
00122 void GC_MacFreeTemporaryMemory()
00123 {
00124 # if defined(SHARED_LIBRARY_BUILD)
00125     /* if possible, collect all memory, and invoke all finalizers. */
00126       perform_final_collection();
00127 # endif
00128 
00129     if (theTemporaryMemory != NULL) {
00130               long totalMemoryUsed = 0;
00131               TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
00132               while (tempMemBlock != NULL) {
00133                      TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
00134                      totalMemoryUsed += GetHandleSize((Handle)tempMemBlock);
00135                      DisposeHandle((Handle)tempMemBlock);
00136                      tempMemBlock = nextBlock;
00137               }
00138               theTemporaryMemory = NULL;
00139 
00140 #       if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD)
00141           fprintf(stdout, "[total memory used:  %ld bytes.]\n",
00142                   totalMemoryUsed);
00143           fprintf(stdout, "[total collections:  %ld.]\n", GC_gc_no);
00144 #       endif
00145     }
00146 }