OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [mac/] [tclMacAlloc.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclMacAlloc.c --
3
 *
4
 *      This is a very fast storage allocator.  It allocates blocks of a
5
 *      small number of different sizes, and keeps free lists of each size.
6
 *      Blocks that don't exactly fit are passed up to the next larger size.
7
 *      Blocks over a certain size are directly allocated by calling NewPtr.
8
 *
9
 * Copyright (c) 1983 Regents of the University of California.
10
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
11
 *
12
 * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson
13
 *.
14
 * See the file "license.terms" for information on usage and redistribution
15
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
 *
17
 * RCS: @(#) $Id: tclMacAlloc.c,v 1.1.1.1 2002-01-16 10:25:30 markom Exp $
18
 */
19
 
20
#include "tclMacInt.h"
21
#include "tclInt.h"
22
#include <Memory.h>
23
#include <stdlib.h>
24
#include <string.h>
25
 
26
 
27
/*
28
 * Flags that are used by ConfigureMemory to define how the allocator
29
 * should work.  They can be or'd together.
30
 */
31
#define MEMORY_ALL_SYS 1        /* All memory should come from the system
32
heap. */
33
 
34
/*
35
 * Amount of space to leave in the application heap for the Toolbox to work.
36
 */
37
 
38
#define TOOLBOX_SPACE (32 * 1024)
39
 
40
static int memoryFlags = 0;
41
static Handle toolGuardHandle = NULL;
42
                                /* This handle must be around so that we don't
43
                                 * have NewGWorld failures. This handle is
44
                                 * purgeable. Before we allocate any blocks,
45
                                 * we see if this handle is still around.
46
                                 * If it is not, then we try to get it again.
47
                                 * If we can get it, we lock it and try
48
                                 * to do the normal allocation, unlocking on
49
                                 * the way out. If we can't, we go to the
50
                                 * system heap directly. */
51
 
52
 
53
/*
54
 * The following typedef and variable are used to keep track of memory
55
 * blocks that are allocated directly from the System Heap.  These chunks
56
 * of memory must always be freed - even if we crash.
57
 */
58
 
59
typedef struct listEl {
60
    Handle              memoryHandle;
61
    struct listEl *     next;
62
} ListEl;
63
 
64
ListEl * systemMemory = NULL;
65
ListEl * appMemory = NULL;
66
 
67
/*
68
 * Prototypes for functions used only in this file.
69
 */
70
 
71
static pascal void      CleanUpExitProc _ANSI_ARGS_((void));
72
void                    ConfigureMemory _ANSI_ARGS_((int flags));
73
void                    FreeAllMemory _ANSI_ARGS_((void));
74
 
75
/*
76
 *----------------------------------------------------------------------
77
 *
78
 * TclpSysRealloc --
79
 *
80
 *      This function reallocates a chunk of system memory.  If the
81
 *      chunk is already big enough to hold the new block, then no
82
 *      allocation happens.
83
 *
84
 * Results:
85
 *      Returns a pointer to the newly allocated block.
86
 *
87
 * Side effects:
88
 *      May copy the contents of the original block to the new block
89
 *      and deallocate the original block.
90
 *
91
 *----------------------------------------------------------------------
92
 */
93
 
94
VOID *
95
TclpSysRealloc(
96
    VOID *oldPtr,               /* Original block */
97
    unsigned int size)          /* New size of block. */
98
{
99
    Handle hand;
100
    void *newPtr;
101
    int maxsize;
102
 
103
    hand = * (Handle *) ((Ptr) oldPtr - sizeof(Handle));
104
    maxsize = GetHandleSize(hand) - sizeof(Handle);
105
    if (maxsize < size) {
106
        newPtr = TclpSysAlloc(size, 1);
107
        memcpy(newPtr, oldPtr, maxsize);
108
        TclpSysFree(oldPtr);
109
    } else {
110
        newPtr = oldPtr;
111
    }
112
    return newPtr;
113
}
114
 
115
/*
116
 *----------------------------------------------------------------------
117
 *
118
 * TclpSysAlloc --
119
 *
120
 *      Allocate a new block of memory free from the System.
121
 *
122
 * Results:
123
 *      Returns a pointer to a new block of memory.
124
 *
125
 * Side effects:
126
 *      May obtain memory from app or sys space.  Info is added to
127
 *      overhead lists etc.
128
 *
129
 *----------------------------------------------------------------------
130
 */
131
 
132
VOID *
133
TclpSysAlloc(
134
    long size,          /* Size of block to allocate. */
135
    int isBin)          /* Is this a bin allocation? */
136
{
137
    Handle hand = NULL;
138
    ListEl * newMemoryRecord;
139
 
140
    if (!(memoryFlags & MEMORY_ALL_SYS)) {
141
 
142
        /*
143
         * If the guard handle has been purged, throw it away and try
144
         * to allocate it again.
145
         */
146
 
147
        if ((toolGuardHandle != NULL) && (*toolGuardHandle == NULL)) {
148
            DisposeHandle(toolGuardHandle);
149
            toolGuardHandle = NULL;
150
        }
151
 
152
        /*
153
         * If we have never allocated the guard handle, or it was purged
154
         * and thrown away, then try to allocate it again.
155
         */
156
 
157
        if (toolGuardHandle == NULL) {
158
            toolGuardHandle = NewHandle(TOOLBOX_SPACE);
159
            if (toolGuardHandle != NULL) {
160
                HPurge(toolGuardHandle);
161
            }
162
        }
163
 
164
        /*
165
         * If we got the handle, lock it and do our allocation.
166
         */
167
 
168
        if (toolGuardHandle != NULL) {
169
            HLock(toolGuardHandle);
170
            hand = NewHandle(size + sizeof(Handle));
171
            HUnlock(toolGuardHandle);
172
        }
173
    }
174
    if (hand != NULL) {
175
        newMemoryRecord = (ListEl *) NewPtr(sizeof(ListEl));
176
        if (newMemoryRecord == NULL) {
177
            DisposeHandle(hand);
178
            return NULL;
179
        }
180
        newMemoryRecord->memoryHandle = hand;
181
        newMemoryRecord->next = appMemory;
182
        appMemory = newMemoryRecord;
183
    } else {
184
        /*
185
         * Ran out of memory in application space.  Lets try to get
186
         * more memory from system.  Otherwise, we return NULL to
187
         * denote failure.
188
         */
189
        isBin = 0;
190
        hand = NewHandleSys(size + sizeof(Handle));
191
        if (hand == NULL) {
192
            return NULL;
193
        }
194
        if (systemMemory == NULL) {
195
            /*
196
             * This is the first time we've attempted to allocate memory
197
             * directly from the system heap.  We need to now install the
198
             * exit handle to ensure the memory is cleaned up.
199
             */
200
            TclMacInstallExitToShellPatch(CleanUpExitProc);
201
        }
202
        newMemoryRecord = (ListEl *) NewPtrSys(sizeof(ListEl));
203
        if (newMemoryRecord == NULL) {
204
            DisposeHandle(hand);
205
            return NULL;
206
        }
207
        newMemoryRecord->memoryHandle = hand;
208
        newMemoryRecord->next = systemMemory;
209
        systemMemory = newMemoryRecord;
210
    }
211
    if (isBin) {
212
        HLockHi(hand);
213
    } else {
214
        HLock(hand);
215
    }
216
    (** (Handle **) hand) = hand;
217
 
218
    return (*hand + sizeof(Handle));
219
}
220
 
221
/*
222
 *----------------------------------------------------------------------
223
 *
224
 * TclpSysFree --
225
 *
226
 *      Free memory that we allocated back to the system.
227
 *
228
 * Results:
229
 *      None.
230
 *
231
 * Side effects:
232
 *      Memory is freed.
233
 *
234
 *----------------------------------------------------------------------
235
 */
236
 
237
void
238
TclpSysFree(
239
    void * ptr)         /* Free this system memory. */
240
{
241
    Handle hand;
242
    OSErr err;
243
 
244
    hand = * (Handle *) ((Ptr) ptr - sizeof(Handle));
245
    DisposeHandle(hand);
246
    *hand = NULL;
247
    err = MemError();
248
}
249
 
250
/*
251
 *----------------------------------------------------------------------
252
 *
253
 * CleanUpExitProc --
254
 *
255
 *      This procedure is invoked as an exit handler when ExitToShell
256
 *      is called.  It removes any memory that was allocated directly
257
 *      from the system heap.  This must be called when the application
258
 *      quits or the memory will never be freed.
259
 *
260
 * Results:
261
 *      None.
262
 *
263
 * Side effects:
264
 *      May free memory in the system heap.
265
 *
266
 *----------------------------------------------------------------------
267
 */
268
 
269
static pascal void
270
CleanUpExitProc()
271
{
272
    ListEl * memRecord;
273
 
274
    while (systemMemory != NULL) {
275
        memRecord = systemMemory;
276
        systemMemory = memRecord->next;
277
        if (*(memRecord->memoryHandle) != NULL) {
278
            DisposeHandle(memRecord->memoryHandle);
279
        }
280
        DisposePtr((void *) memRecord);
281
    }
282
}
283
 
284
/*
285
 *----------------------------------------------------------------------
286
 *
287
 * FreeAllMemory --
288
 *
289
 *      This procedure frees all memory blocks allocated by the memory
290
 *      sub-system.  Make sure you don't have any code that references
291
 *      any malloced data!
292
 *
293
 * Results:
294
 *      None.
295
 *
296
 * Side effects:
297
 *      Frees all memory allocated by TclpAlloc.
298
 *
299
 *----------------------------------------------------------------------
300
 */
301
 
302
void
303
FreeAllMemory()
304
{
305
    ListEl * memRecord;
306
 
307
    while (systemMemory != NULL) {
308
        memRecord = systemMemory;
309
        systemMemory = memRecord->next;
310
        if (*(memRecord->memoryHandle) != NULL) {
311
            DisposeHandle(memRecord->memoryHandle);
312
        }
313
        DisposePtr((void *) memRecord);
314
    }
315
    while (appMemory != NULL) {
316
        memRecord = appMemory;
317
        appMemory = memRecord->next;
318
        if (*(memRecord->memoryHandle) != NULL) {
319
            DisposeHandle(memRecord->memoryHandle);
320
        }
321
        DisposePtr((void *) memRecord);
322
    }
323
}
324
 
325
/*
326
 *----------------------------------------------------------------------
327
 *
328
 * ConfigureMemory --
329
 *
330
 *      This procedure sets certain flags in this file that control
331
 *      how memory is allocated and managed.  This call must be made
332
 *      before any call to TclpAlloc is made.
333
 *
334
 * Results:
335
 *      None.
336
 *
337
 * Side effects:
338
 *      Certain state will be changed.
339
 *
340
 *----------------------------------------------------------------------
341
 */
342
 
343
void
344
ConfigureMemory(
345
    int flags)          /* Flags that control memory alloc scheme. */
346
{
347
    memoryFlags = flags;
348
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.