9fc579f9dafe2f2055fc639c5396487fb77a22a5
[cacao.git] / src / mm / boehm-gc / MacOS.c
1 /*
2         MacOS.c
3         
4         Some routines for the Macintosh OS port of the Hans-J. Boehm, Alan J. Demers
5         garbage collector.
6         
7         <Revision History>
8         
9         11/22/94  pcb  StripAddress the temporary memory handle for 24-bit mode.
10         11/30/94  pcb  Tracking all memory usage so we can deallocate it all at once.
11         02/10/96  pcb  Added routine to perform a final collection when
12 unloading shared library.
13         
14         by Patrick C. Beard.
15  */
16 /* Boehm, February 15, 1996 2:55 pm PST */
17
18 #include "config.h"
19
20 #include <Resources.h>
21 #include <Memory.h>
22 #include <LowMem.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "gc.h"
28 #include "gc_priv.h"
29
30 // use 'CODE' resource 0 to get exact location of the beginning of global space.
31
32 typedef struct {
33         unsigned long aboveA5;
34         unsigned long belowA5;
35         unsigned long JTSize;
36         unsigned long JTOffset;
37 } *CodeZeroPtr, **CodeZeroHandle;
38
39 void* GC_MacGetDataStart()
40 {
41         CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
42         if (code0) {
43                 long belowA5Size = (**code0).belowA5;
44                 ReleaseResource((Handle)code0);
45                 return (LMGetCurrentA5() - belowA5Size);
46         }
47         fprintf(stderr, "Couldn't load the jump table.");
48         exit(-1);
49         return 0;
50 }
51
52 /* track the use of temporary memory so it can be freed all at once. */
53
54 typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle;
55
56 struct TemporaryMemoryBlock {
57         TemporaryMemoryHandle nextBlock;
58         char data[];
59 };
60
61 static TemporaryMemoryHandle theTemporaryMemory = NULL;
62 static Boolean firstTime = true;
63
64 void GC_MacFreeTemporaryMemory(void);
65
66 Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
67 {
68         static Boolean firstTime = true;
69         OSErr result;
70         TemporaryMemoryHandle tempMemBlock;
71         Ptr tempPtr = nil;
72
73         tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result);
74         if (tempMemBlock && result == noErr) {
75                 HLockHi((Handle)tempMemBlock);
76                 tempPtr = (**tempMemBlock).data;
77                 if (clearMemory) memset(tempPtr, 0, size);
78                 tempPtr = StripAddress(tempPtr);
79
80                 // keep track of the allocated blocks.
81                 (**tempMemBlock).nextBlock = theTemporaryMemory;
82                 theTemporaryMemory = tempMemBlock;
83         }
84         
85 #     if !defined(SHARED_LIBRARY_BUILD)
86         // install an exit routine to clean up the memory used at the end.
87         if (firstTime) {
88                 atexit(&GC_MacFreeTemporaryMemory);
89                 firstTime = false;
90         }
91 #     endif
92         
93         return tempPtr;
94 }
95
96 extern word GC_fo_entries; 
97
98 static void perform_final_collection()
99 {
100   unsigned i;
101   word last_fo_entries = 0;
102   
103   /* adjust the stack bottom, because CFM calls us from another stack
104      location. */
105      GC_stackbottom = (ptr_t)&i;
106
107   /* try to collect and finalize everything in sight */
108     for (i = 0; i < 2 || GC_fo_entries < last_fo_entries; i++) {
109         last_fo_entries = GC_fo_entries;
110         GC_gcollect();
111     }
112 }
113
114
115 void GC_MacFreeTemporaryMemory()
116 {
117 # if defined(SHARED_LIBRARY_BUILD)
118     /* if possible, collect all memory, and invoke all finalizers. */
119       perform_final_collection();
120 # endif
121
122     if (theTemporaryMemory != NULL) {
123         long totalMemoryUsed = 0;
124         TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
125         while (tempMemBlock != NULL) {
126                 TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
127                 totalMemoryUsed += GetHandleSize((Handle)tempMemBlock);
128                 DisposeHandle((Handle)tempMemBlock);
129                 tempMemBlock = nextBlock;
130         }
131         theTemporaryMemory = NULL;
132
133 #       if !defined(SHARED_LIBRARY_BUILD)
134           if (GC_print_stats) {
135             fprintf(stdout, "[total memory used:  %ld bytes.]\n",
136                   totalMemoryUsed);
137             fprintf(stdout, "[total collections:  %ld.]\n", GC_gc_no);
138           }
139 #       endif
140     }
141 }
142
143 #if __option(far_data)
144
145   void* GC_MacGetDataEnd()
146   {
147         CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
148         if (code0) {
149                 long aboveA5Size = (**code0).aboveA5;
150                 ReleaseResource((Handle)code0);
151                 return (LMGetCurrentA5() + aboveA5Size);
152         }
153         fprintf(stderr, "Couldn't load the jump table.");
154         exit(-1);
155         return 0;
156   }
157
158 #endif /* __option(far_data) */