summaryrefslogtreecommitdiff
path: root/extra/MacOS.c
blob: a2a978a64b337a19ba41cd5e3d6ee30a0d794bb5 (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>

#define GC_BUILD
#include "gc.h"
#include "private/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(void)
{
        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);
# if !defined(CPPCHECK)
        return 0; /* to avoid compiler complain about missing return */
# endif
}

#ifdef USE_TEMPORARY_MEMORY

/* 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;

void GC_MacFreeTemporaryMemory(void);

Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
{
#     if !defined(SHARED_LIBRARY_BUILD)
        static Boolean firstTime = true;
#     endif
        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;
}

static void perform_final_collection(void)
{
  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(void)
{
# if defined(SHARED_LIBRARY_BUILD)
    /* if possible, collect all memory, and invoke all finalizers. */
      perform_final_collection();
# endif

    if (theTemporaryMemory != NULL) {
        TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
        while (tempMemBlock /* != NULL */) {
                TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
                DisposeHandle((Handle)tempMemBlock);
                tempMemBlock = nextBlock;
        }
        theTemporaryMemory = NULL;
    }
}

#endif /* USE_TEMPORARY_MEMORY */

#if __option(far_data)

  void* GC_MacGetDataEnd(void)
  {
        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);
#   if !defined(CPPCHECK)
        return 0;
#   endif
  }

#endif /* __option(far_data) */