aboutsummaryrefslogtreecommitdiff
path: root/boehm-gc/MacOS.c
blob: cc12cd15d988c8665caf0c358fc18cb84ecd9a76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
	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) */