os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacAlloc.c
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 +}