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 
GC_MacGetDataStart()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 
GC_MacTemporaryNewPtr(size_t size,Boolean clearMemory)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 
perform_final_collection()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 
GC_MacFreeTemporaryMemory()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 
GC_MacGetDataEnd()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) */
155