os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacAlloc.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacAlloc.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,412 @@
     1.4 +/*
     1.5 + * tclMacAlloc.c --
     1.6 + *
     1.7 + *	This is a very fast storage allocator.  It allocates blocks of a
     1.8 + *	small number of different sizes, and keeps free lists of each size.
     1.9 + *	Blocks that don't exactly fit are passed up to the next larger size.
    1.10 + *	Blocks over a certain size are directly allocated by calling NewPtr.
    1.11 + *
    1.12 + * Copyright (c) 1983 Regents of the University of California.
    1.13 + * Copyright (c) 1996-1997 Sun Microsystems, Inc.
    1.14 + *
    1.15 + * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson
    1.16 + *.
    1.17 + * See the file "license.terms" for information on usage and redistribution
    1.18 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1.19 + *
    1.20 + * RCS: @(#) $Id: tclMacAlloc.c,v 1.5 2001/11/23 01:27:09 das Exp $
    1.21 + */
    1.22 +
    1.23 +#include "tclInt.h"
    1.24 +#include "tclMacInt.h"
    1.25 +#include <Memory.h>
    1.26 +#include <Gestalt.h>
    1.27 +#include <stdlib.h>
    1.28 +#include <string.h>
    1.29 +
    1.30 +
    1.31 +/*
    1.32 + * Flags that are used by ConfigureMemory to define how the allocator
    1.33 + * should work.  They can be or'd together.
    1.34 + */
    1.35 +#define MEMORY_ALL_SYS 1	/* All memory should come from the system
    1.36 +heap. */
    1.37 +#define MEMORY_DONT_USE_TEMPMEM 2	/* Don't use temporary memory but system memory. */
    1.38 +
    1.39 +/*
    1.40 + * Amount of space to leave in the application heap for the Toolbox to work.
    1.41 + */
    1.42 +
    1.43 +#define TOOLBOX_SPACE (512 * 1024)
    1.44 +
    1.45 +static int memoryFlags = 0;
    1.46 +static Handle toolGuardHandle = NULL;
    1.47 +				/* This handle must be around so that we don't
    1.48 +				 * have NewGWorld failures. This handle is
    1.49 +				 * purgeable. Before we allocate any blocks,
    1.50 +				 * we see if this handle is still around.
    1.51 +				 * If it is not, then we try to get it again.
    1.52 +				 * If we can get it, we lock it and try
    1.53 +				 * to do the normal allocation, unlocking on
    1.54 +				 * the way out. If we can't, we go to the
    1.55 +				 * system heap directly. */
    1.56 +
    1.57 +static int tclUseMemTracking = 0; /* Are we tracking memory allocations?
    1.58 +								   * On recent versions of the MacOS this
    1.59 +								   * is no longer necessary, as we can use
    1.60 +								   * temporary memory which is freed by the
    1.61 +								   * OS after a quit or crash. */
    1.62 +								   
    1.63 +static size_t tclExtraHdlSize = 0; /* Size of extra memory allocated at the start
    1.64 +									* of each block when using memory tracking
    1.65 +									* ( == 0 otherwise) */
    1.66 +
    1.67 +/*
    1.68 + * The following typedef and variable are used to keep track of memory
    1.69 + * blocks that are allocated directly from the System Heap.  These chunks
    1.70 + * of memory must always be freed - even if we crash.
    1.71 + */
    1.72 +
    1.73 +typedef struct listEl {
    1.74 +    Handle		memoryHandle;
    1.75 +    struct listEl *	next;
    1.76 +    struct listEl *	prec;
    1.77 +} ListEl;
    1.78 +
    1.79 +static ListEl * systemMemory = NULL;
    1.80 +static ListEl * appMemory = NULL;
    1.81 +
    1.82 +/*
    1.83 + * Prototypes for functions used only in this file.
    1.84 + */
    1.85 +
    1.86 +static pascal void	CleanUpExitProc _ANSI_ARGS_((void));
    1.87 +void 			ConfigureMemory _ANSI_ARGS_((int flags));
    1.88 +void			FreeAllMemory _ANSI_ARGS_((void));
    1.89 +
    1.90 +/*
    1.91 + *----------------------------------------------------------------------
    1.92 + *
    1.93 + * TclpSysRealloc --
    1.94 + *
    1.95 + *	This function reallocates a chunk of system memory.  If the
    1.96 + *	chunk is already big enough to hold the new block, then no
    1.97 + *	allocation happens.
    1.98 + *
    1.99 + * Results:
   1.100 + *	Returns a pointer to the newly allocated block.
   1.101 + *
   1.102 + * Side effects:
   1.103 + *	May copy the contents of the original block to the new block
   1.104 + *	and deallocate the original block.
   1.105 + *
   1.106 + *----------------------------------------------------------------------
   1.107 + */
   1.108 +
   1.109 +VOID *
   1.110 +TclpSysRealloc(
   1.111 +    VOID *oldPtr,		/* Original block */
   1.112 +    unsigned int size)		/* New size of block. */
   1.113 +{
   1.114 +    Handle hand;
   1.115 +    void *newPtr;
   1.116 +    int maxsize;
   1.117 +    OSErr err;
   1.118 +
   1.119 +	if (tclUseMemTracking) {
   1.120 +    hand = ((ListEl *) ((Ptr) oldPtr - tclExtraHdlSize))->memoryHandle;
   1.121 +    } else {
   1.122 +    hand = RecoverHandle((Ptr) oldPtr);
   1.123 +	}
   1.124 +    maxsize = GetHandleSize(hand) - sizeof(Handle);
   1.125 +    if (maxsize < size) {
   1.126 +    HUnlock(hand);
   1.127 +    SetHandleSize(hand,size + tclExtraHdlSize);
   1.128 +    err = MemError();
   1.129 +    HLock(hand);
   1.130 +    if(err==noErr){
   1.131 +    	newPtr=(*hand + tclExtraHdlSize);
   1.132 +    } else {
   1.133 +	newPtr = TclpSysAlloc(size, 1);
   1.134 +	if(newPtr!=NULL) {
   1.135 +	memmove(newPtr, oldPtr, maxsize);
   1.136 +	TclpSysFree(oldPtr);
   1.137 +	}
   1.138 +	}
   1.139 +    } else {
   1.140 +	newPtr = oldPtr;
   1.141 +    }
   1.142 +    return newPtr;
   1.143 +}
   1.144 +
   1.145 +/*
   1.146 + *----------------------------------------------------------------------
   1.147 + *
   1.148 + * TclpSysAlloc --
   1.149 + *
   1.150 + *	Allocate a new block of memory free from the System.
   1.151 + *
   1.152 + * Results:
   1.153 + *	Returns a pointer to a new block of memory.
   1.154 + *
   1.155 + * Side effects:
   1.156 + *	May obtain memory from app or sys space.  Info is added to
   1.157 + *	overhead lists etc.
   1.158 + *
   1.159 + *----------------------------------------------------------------------
   1.160 + */
   1.161 +
   1.162 +VOID *
   1.163 +TclpSysAlloc(
   1.164 +    long size,		/* Size of block to allocate. */
   1.165 +    int isBin)		/* Is this a bin allocation? */
   1.166 +{
   1.167 +    Handle hand = NULL;
   1.168 +    ListEl * newMemoryRecord;
   1.169 +	int isSysMem = 0;
   1.170 +	static int initialized=0;
   1.171 +	
   1.172 +	if (!initialized) {
   1.173 +	long response = 0;
   1.174 +	OSErr err = noErr;
   1.175 +	int useTempMem = 0;
   1.176 +	
   1.177 +	/* Check if we can use temporary memory */
   1.178 +	initialized=1;
   1.179 +	err = Gestalt(gestaltOSAttr, &response);
   1.180 +	if (err == noErr) {
   1.181 +    	useTempMem = response & (1 << gestaltRealTempMemory);
   1.182 +	}
   1.183 +	tclUseMemTracking = !useTempMem || (memoryFlags & MEMORY_DONT_USE_TEMPMEM);
   1.184 +	if(tclUseMemTracking) {
   1.185 +	    tclExtraHdlSize = sizeof(ListEl);
   1.186 +	    /*
   1.187 +	     * We are allocating memory directly from the system
   1.188 +	     * heap. We need to install an exit handle 
   1.189 +	     * to ensure the memory is cleaned up.
   1.190 +	     */
   1.191 +	    TclMacInstallExitToShellPatch(CleanUpExitProc);
   1.192 +	}
   1.193 +	}
   1.194 +
   1.195 +    if (!(memoryFlags & MEMORY_ALL_SYS)) {
   1.196 +
   1.197 +    	/*
   1.198 +    	 * If the guard handle has been purged, throw it away and try
   1.199 +    	 * to allocate it again.
   1.200 +    	 */
   1.201 +
   1.202 +    	if ((toolGuardHandle != NULL) && (*toolGuardHandle == NULL)) {
   1.203 +    	    DisposeHandle(toolGuardHandle);
   1.204 +    	    toolGuardHandle = NULL;
   1.205 +    	}
   1.206 +
   1.207 +    	/*
   1.208 +    	 * If we have never allocated the guard handle, or it was purged
   1.209 +    	 * and thrown away, then try to allocate it again.
   1.210 +    	 */
   1.211 +
   1.212 +    	if (toolGuardHandle == NULL) {
   1.213 +    	    toolGuardHandle = NewHandle(TOOLBOX_SPACE);
   1.214 +    	    if (toolGuardHandle != NULL) {
   1.215 +    	    	HLock(toolGuardHandle);
   1.216 +    	    	HPurge(toolGuardHandle);
   1.217 +    	    }
   1.218 +    	}
   1.219 +
   1.220 +	/*
   1.221 +	 * If we got the handle, lock it and do our allocation.
   1.222 +	 */
   1.223 +
   1.224 +    	if (toolGuardHandle != NULL) {
   1.225 +    	    HLock(toolGuardHandle);
   1.226 +	    hand = NewHandle(size + tclExtraHdlSize);
   1.227 +	    HUnlock(toolGuardHandle);
   1.228 +	}
   1.229 +    }
   1.230 +    if (hand == NULL) {
   1.231 +	/*
   1.232 +	 * Ran out of memory in application space.  Lets try to get
   1.233 +	 * more memory from system.  Otherwise, we return NULL to
   1.234 +	 * denote failure.
   1.235 +	 */
   1.236 +	if(!tclUseMemTracking) {
   1.237 +		/* Use Temporary Memory instead of System Heap when available */
   1.238 +		OSErr err;
   1.239 +		isBin = 1; /* always HLockHi TempMemHandles */
   1.240 +		hand = TempNewHandle(size + tclExtraHdlSize,&err);
   1.241 +		if(err!=noErr) { hand=NULL; }
   1.242 +	} else {
   1.243 +	/* Use system heap when tracking memory */
   1.244 +	isSysMem=1;
   1.245 +	isBin = 0;
   1.246 +	hand = NewHandleSys(size + tclExtraHdlSize);
   1.247 +	}
   1.248 +	}
   1.249 +	if (hand == NULL) {
   1.250 +	    return NULL;
   1.251 +	}
   1.252 +    if (isBin) {
   1.253 +	HLockHi(hand);
   1.254 +    } else {
   1.255 +	HLock(hand);
   1.256 +    }
   1.257 +	if(tclUseMemTracking) {
   1.258 +	/* Only need to do this when tracking memory */
   1.259 +	newMemoryRecord = (ListEl *) *hand;
   1.260 +	newMemoryRecord->memoryHandle = hand;
   1.261 +	newMemoryRecord->prec = NULL;
   1.262 +	if(isSysMem) {
   1.263 +	newMemoryRecord->next = systemMemory;
   1.264 +	systemMemory = newMemoryRecord;
   1.265 +	} else {
   1.266 +	newMemoryRecord->next = appMemory;
   1.267 +	appMemory = newMemoryRecord;
   1.268 +	}
   1.269 +	if(newMemoryRecord->next!=NULL) {
   1.270 +	newMemoryRecord->next->prec=newMemoryRecord;
   1.271 +	}
   1.272 +	}
   1.273 +	
   1.274 +    return (*hand + tclExtraHdlSize);
   1.275 +}
   1.276 +
   1.277 +/*
   1.278 + *----------------------------------------------------------------------
   1.279 + *
   1.280 + * TclpSysFree --
   1.281 + *
   1.282 + *	Free memory that we allocated back to the system.
   1.283 + *
   1.284 + * Results:
   1.285 + *	None.
   1.286 + *
   1.287 + * Side effects:
   1.288 + *	Memory is freed.
   1.289 + *
   1.290 + *----------------------------------------------------------------------
   1.291 + */
   1.292 +
   1.293 +void
   1.294 +TclpSysFree(
   1.295 +    void * ptr)		/* Free this system memory. */
   1.296 +{
   1.297 +	if(tclUseMemTracking) {
   1.298 +    /* Only need to do this when tracking memory */
   1.299 +    ListEl *memRecord;
   1.300 +
   1.301 +    memRecord = (ListEl *) ((Ptr) ptr - tclExtraHdlSize);
   1.302 +    /* Remove current record from linked list */
   1.303 +    if(memRecord->next!=NULL) {
   1.304 +    	memRecord->next->prec=memRecord->prec;
   1.305 +    }
   1.306 +    if(memRecord->prec!=NULL) {
   1.307 +    	memRecord->prec->next=memRecord->next;
   1.308 +    }
   1.309 +    if(memRecord==appMemory) {
   1.310 +    	appMemory=memRecord->next;
   1.311 +    } else if(memRecord==systemMemory) {
   1.312 +    	systemMemory=memRecord->next;
   1.313 +    }
   1.314 +    DisposeHandle(memRecord->memoryHandle);
   1.315 +	} else {
   1.316 +    DisposeHandle(RecoverHandle((Ptr) ptr));
   1.317 +	}
   1.318 +}
   1.319 +
   1.320 +/*
   1.321 + *----------------------------------------------------------------------
   1.322 + *
   1.323 + * CleanUpExitProc --
   1.324 + *
   1.325 + *	This procedure is invoked as an exit handler when ExitToShell
   1.326 + *	is called.  It removes any memory that was allocated directly
   1.327 + *	from the system heap.  This must be called when the application
   1.328 + *	quits or the memory will never be freed.
   1.329 + *
   1.330 + * Results:
   1.331 + *	None.
   1.332 + *
   1.333 + * Side effects:
   1.334 + *	May free memory in the system heap.
   1.335 + *
   1.336 + *----------------------------------------------------------------------
   1.337 + */
   1.338 +
   1.339 +static pascal void
   1.340 +CleanUpExitProc()
   1.341 +{
   1.342 +    ListEl * memRecord;
   1.343 +
   1.344 +    if(tclUseMemTracking) {
   1.345 +    /* Only need to do this when tracking memory */
   1.346 +    while (systemMemory != NULL) {
   1.347 +	memRecord = systemMemory;
   1.348 +	systemMemory = memRecord->next;
   1.349 +	DisposeHandle(memRecord->memoryHandle);
   1.350 +    }
   1.351 +    }
   1.352 +}
   1.353 +
   1.354 +/*
   1.355 + *----------------------------------------------------------------------
   1.356 + *
   1.357 + * FreeAllMemory --
   1.358 + *
   1.359 + *	This procedure frees all memory blocks allocated by the memory
   1.360 + *	sub-system.  Make sure you don't have any code that references
   1.361 + *	any malloced data!
   1.362 + *
   1.363 + * Results:
   1.364 + *	None.
   1.365 + *
   1.366 + * Side effects:
   1.367 + *	Frees all memory allocated by TclpAlloc.
   1.368 + *
   1.369 + *----------------------------------------------------------------------
   1.370 + */
   1.371 +
   1.372 +void
   1.373 +FreeAllMemory()
   1.374 +{
   1.375 +    ListEl * memRecord;
   1.376 +
   1.377 +	if(tclUseMemTracking) {
   1.378 +	/* Only need to do this when tracking memory */
   1.379 +    while (systemMemory != NULL) {
   1.380 +	memRecord = systemMemory;
   1.381 +	systemMemory = memRecord->next;
   1.382 +	DisposeHandle(memRecord->memoryHandle);
   1.383 +    }
   1.384 +    while (appMemory != NULL) {
   1.385 +	memRecord = appMemory;
   1.386 +	appMemory = memRecord->next;
   1.387 +	DisposeHandle(memRecord->memoryHandle);
   1.388 +	}
   1.389 +    }
   1.390 +}
   1.391 +
   1.392 +/*
   1.393 + *----------------------------------------------------------------------
   1.394 + *
   1.395 + * ConfigureMemory --
   1.396 + *
   1.397 + *	This procedure sets certain flags in this file that control
   1.398 + *	how memory is allocated and managed.  This call must be made
   1.399 + *	before any call to TclpAlloc is made.
   1.400 + *
   1.401 + * Results:
   1.402 + *	None.
   1.403 + *
   1.404 + * Side effects:
   1.405 + *	Certain state will be changed.
   1.406 + *
   1.407 + *----------------------------------------------------------------------
   1.408 + */
   1.409 +
   1.410 +void
   1.411 +ConfigureMemory(
   1.412 +    int flags)		/* Flags that control memory alloc scheme. */
   1.413 +{
   1.414 +    memoryFlags = flags;
   1.415 +}