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