os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacAlloc.c
Update contrib.
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.
9 * Copyright (c) 1983 Regents of the University of California.
10 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
12 * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson
14 * See the file "license.terms" for information on usage and redistribution
15 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17 * RCS: @(#) $Id: tclMacAlloc.c,v 1.5 2001/11/23 01:27:09 das Exp $
21 #include "tclMacInt.h"
29 * Flags that are used by ConfigureMemory to define how the allocator
30 * should work. They can be or'd together.
32 #define MEMORY_ALL_SYS 1 /* All memory should come from the system
34 #define MEMORY_DONT_USE_TEMPMEM 2 /* Don't use temporary memory but system memory. */
37 * Amount of space to leave in the application heap for the Toolbox to work.
40 #define TOOLBOX_SPACE (512 * 1024)
42 static int memoryFlags = 0;
43 static Handle toolGuardHandle = NULL;
44 /* This handle must be around so that we don't
45 * have NewGWorld failures. This handle is
46 * purgeable. Before we allocate any blocks,
47 * we see if this handle is still around.
48 * If it is not, then we try to get it again.
49 * If we can get it, we lock it and try
50 * to do the normal allocation, unlocking on
51 * the way out. If we can't, we go to the
52 * system heap directly. */
54 static int tclUseMemTracking = 0; /* Are we tracking memory allocations?
55 * On recent versions of the MacOS this
56 * is no longer necessary, as we can use
57 * temporary memory which is freed by the
58 * OS after a quit or crash. */
60 static size_t tclExtraHdlSize = 0; /* Size of extra memory allocated at the start
61 * of each block when using memory tracking
62 * ( == 0 otherwise) */
65 * The following typedef and variable are used to keep track of memory
66 * blocks that are allocated directly from the System Heap. These chunks
67 * of memory must always be freed - even if we crash.
70 typedef struct listEl {
76 static ListEl * systemMemory = NULL;
77 static ListEl * appMemory = NULL;
80 * Prototypes for functions used only in this file.
83 static pascal void CleanUpExitProc _ANSI_ARGS_((void));
84 void ConfigureMemory _ANSI_ARGS_((int flags));
85 void FreeAllMemory _ANSI_ARGS_((void));
88 *----------------------------------------------------------------------
92 * This function reallocates a chunk of system memory. If the
93 * chunk is already big enough to hold the new block, then no
97 * Returns a pointer to the newly allocated block.
100 * May copy the contents of the original block to the new block
101 * and deallocate the original block.
103 *----------------------------------------------------------------------
108 VOID *oldPtr, /* Original block */
109 unsigned int size) /* New size of block. */
116 if (tclUseMemTracking) {
117 hand = ((ListEl *) ((Ptr) oldPtr - tclExtraHdlSize))->memoryHandle;
119 hand = RecoverHandle((Ptr) oldPtr);
121 maxsize = GetHandleSize(hand) - sizeof(Handle);
122 if (maxsize < size) {
124 SetHandleSize(hand,size + tclExtraHdlSize);
128 newPtr=(*hand + tclExtraHdlSize);
130 newPtr = TclpSysAlloc(size, 1);
132 memmove(newPtr, oldPtr, maxsize);
143 *----------------------------------------------------------------------
147 * Allocate a new block of memory free from the System.
150 * Returns a pointer to a new block of memory.
153 * May obtain memory from app or sys space. Info is added to
154 * overhead lists etc.
156 *----------------------------------------------------------------------
161 long size, /* Size of block to allocate. */
162 int isBin) /* Is this a bin allocation? */
165 ListEl * newMemoryRecord;
167 static int initialized=0;
174 /* Check if we can use temporary memory */
176 err = Gestalt(gestaltOSAttr, &response);
178 useTempMem = response & (1 << gestaltRealTempMemory);
180 tclUseMemTracking = !useTempMem || (memoryFlags & MEMORY_DONT_USE_TEMPMEM);
181 if(tclUseMemTracking) {
182 tclExtraHdlSize = sizeof(ListEl);
184 * We are allocating memory directly from the system
185 * heap. We need to install an exit handle
186 * to ensure the memory is cleaned up.
188 TclMacInstallExitToShellPatch(CleanUpExitProc);
192 if (!(memoryFlags & MEMORY_ALL_SYS)) {
195 * If the guard handle has been purged, throw it away and try
196 * to allocate it again.
199 if ((toolGuardHandle != NULL) && (*toolGuardHandle == NULL)) {
200 DisposeHandle(toolGuardHandle);
201 toolGuardHandle = NULL;
205 * If we have never allocated the guard handle, or it was purged
206 * and thrown away, then try to allocate it again.
209 if (toolGuardHandle == NULL) {
210 toolGuardHandle = NewHandle(TOOLBOX_SPACE);
211 if (toolGuardHandle != NULL) {
212 HLock(toolGuardHandle);
213 HPurge(toolGuardHandle);
218 * If we got the handle, lock it and do our allocation.
221 if (toolGuardHandle != NULL) {
222 HLock(toolGuardHandle);
223 hand = NewHandle(size + tclExtraHdlSize);
224 HUnlock(toolGuardHandle);
229 * Ran out of memory in application space. Lets try to get
230 * more memory from system. Otherwise, we return NULL to
233 if(!tclUseMemTracking) {
234 /* Use Temporary Memory instead of System Heap when available */
236 isBin = 1; /* always HLockHi TempMemHandles */
237 hand = TempNewHandle(size + tclExtraHdlSize,&err);
238 if(err!=noErr) { hand=NULL; }
240 /* Use system heap when tracking memory */
243 hand = NewHandleSys(size + tclExtraHdlSize);
254 if(tclUseMemTracking) {
255 /* Only need to do this when tracking memory */
256 newMemoryRecord = (ListEl *) *hand;
257 newMemoryRecord->memoryHandle = hand;
258 newMemoryRecord->prec = NULL;
260 newMemoryRecord->next = systemMemory;
261 systemMemory = newMemoryRecord;
263 newMemoryRecord->next = appMemory;
264 appMemory = newMemoryRecord;
266 if(newMemoryRecord->next!=NULL) {
267 newMemoryRecord->next->prec=newMemoryRecord;
271 return (*hand + tclExtraHdlSize);
275 *----------------------------------------------------------------------
279 * Free memory that we allocated back to the system.
287 *----------------------------------------------------------------------
292 void * ptr) /* Free this system memory. */
294 if(tclUseMemTracking) {
295 /* Only need to do this when tracking memory */
298 memRecord = (ListEl *) ((Ptr) ptr - tclExtraHdlSize);
299 /* Remove current record from linked list */
300 if(memRecord->next!=NULL) {
301 memRecord->next->prec=memRecord->prec;
303 if(memRecord->prec!=NULL) {
304 memRecord->prec->next=memRecord->next;
306 if(memRecord==appMemory) {
307 appMemory=memRecord->next;
308 } else if(memRecord==systemMemory) {
309 systemMemory=memRecord->next;
311 DisposeHandle(memRecord->memoryHandle);
313 DisposeHandle(RecoverHandle((Ptr) ptr));
318 *----------------------------------------------------------------------
322 * This procedure is invoked as an exit handler when ExitToShell
323 * is called. It removes any memory that was allocated directly
324 * from the system heap. This must be called when the application
325 * quits or the memory will never be freed.
331 * May free memory in the system heap.
333 *----------------------------------------------------------------------
341 if(tclUseMemTracking) {
342 /* Only need to do this when tracking memory */
343 while (systemMemory != NULL) {
344 memRecord = systemMemory;
345 systemMemory = memRecord->next;
346 DisposeHandle(memRecord->memoryHandle);
352 *----------------------------------------------------------------------
356 * This procedure frees all memory blocks allocated by the memory
357 * sub-system. Make sure you don't have any code that references
364 * Frees all memory allocated by TclpAlloc.
366 *----------------------------------------------------------------------
374 if(tclUseMemTracking) {
375 /* Only need to do this when tracking memory */
376 while (systemMemory != NULL) {
377 memRecord = systemMemory;
378 systemMemory = memRecord->next;
379 DisposeHandle(memRecord->memoryHandle);
381 while (appMemory != NULL) {
382 memRecord = appMemory;
383 appMemory = memRecord->next;
384 DisposeHandle(memRecord->memoryHandle);
390 *----------------------------------------------------------------------
394 * This procedure sets certain flags in this file that control
395 * how memory is allocated and managed. This call must be made
396 * before any call to TclpAlloc is made.
402 * Certain state will be changed.
404 *----------------------------------------------------------------------
409 int flags) /* Flags that control memory alloc scheme. */