diff options
author | das <das@noemail.net> | 2001-05-17 13:30:01 (GMT) |
---|---|---|
committer | das <das@noemail.net> | 2001-05-17 13:30:01 (GMT) |
commit | da370f27864403589365c5083b908e1ccfea3254 (patch) | |
tree | 2932408b466ddb854268ad116bea7ab9b41ed78e /mac | |
parent | 9b2fc8ce7bd849f2a33ee0a0cdd1894ce0bbcb58 (diff) | |
download | tcl-da370f27864403589365c5083b908e1ccfea3254.zip tcl-da370f27864403589365c5083b908e1ccfea3254.tar.gz tcl-da370f27864403589365c5083b908e1ccfea3254.tar.bz2 |
2001-05-04 Daniel Steffen <das@users.sourceforge.net>
** Mac 8.3.3 binary release
* mac/tclMacAlloc.c: modernized TclpSysAlloc() to use temporary
memory instead of system heap memory when available (MacOS
>= 7.5 and possibly earlier, use of system heap has been
discouraged for a long time and has many disadvantages, e.g. memory
isn't paged out, and errors can very easily bring the system down);
fixed crashing bug in TclpSysRealloc() and CleanUpExitProc() where
memory was being accessed after having been deallocated; fixed
memory leak in (de)allocation code (for every block ever allocated
with TclpSysAlloc, a Ptr was leaked), if temporary memory is
available, don't track allocated memory, instead use
RecoverHandle() to get Handle from Ptr, otherwise use doubly linked
list to correctly track memory and free all allocated memory; added
new option for ConfigureMemory: MEMORY_DONT_USE_TEMPMEM, disables
use of temporary memory even when it would be available, only
necessary when writing e.g. a driver (using tcl??); increased
fraction of application heap reserved for OS routines to 512K
FossilOrigin-Name: 1b4e7a6a18130133eaf2170096b65a276bc48c01
Diffstat (limited to 'mac')
-rw-r--r-- | mac/tclMacAlloc.c | 174 |
1 files changed, 119 insertions, 55 deletions
diff --git a/mac/tclMacAlloc.c b/mac/tclMacAlloc.c index c5daa8b..1d5086e 100644 --- a/mac/tclMacAlloc.c +++ b/mac/tclMacAlloc.c @@ -14,12 +14,13 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacAlloc.c,v 1.4 1999/05/11 07:11:51 jingham Exp $ + * RCS: @(#) $Id: tclMacAlloc.c,v 1.4.12.1 2001/05/17 13:30:02 das Exp $ */ #include "tclInt.h" #include "tclMacInt.h" #include <Memory.h> +#include <Gestalt.h> #include <stdlib.h> #include <string.h> @@ -30,12 +31,13 @@ */ #define MEMORY_ALL_SYS 1 /* All memory should come from the system heap. */ +#define MEMORY_DONT_USE_TEMPMEM 2 /* Don't use temporary memory but system memory. */ /* * Amount of space to leave in the application heap for the Toolbox to work. */ -#define TOOLBOX_SPACE (32 * 1024) +#define TOOLBOX_SPACE (512 * 1024) static int memoryFlags = 0; static Handle toolGuardHandle = NULL; @@ -49,6 +51,15 @@ static Handle toolGuardHandle = NULL; * the way out. If we can't, we go to the * system heap directly. */ +static int tclUseMemTracking = 0; /* Are we tracking memory allocations? + * On recent versions of the MacOS this + * is no longer necessary, as we can use + * temporary memory which is freed by the + * OS after a quit or crash. */ + +static size_t tclExtraHdlSize = 0; /* Size of extra memory allocated at the start + * of each block when using memory tracking + * ( == 0 otherwise) */ /* * The following typedef and variable are used to keep track of memory @@ -59,10 +70,11 @@ static Handle toolGuardHandle = NULL; typedef struct listEl { Handle memoryHandle; struct listEl * next; + struct listEl * prec; } ListEl; -ListEl * systemMemory = NULL; -ListEl * appMemory = NULL; +static ListEl * systemMemory = NULL; +static ListEl * appMemory = NULL; /* * Prototypes for functions used only in this file. @@ -99,13 +111,28 @@ TclpSysRealloc( Handle hand; void *newPtr; int maxsize; + OSErr err; - hand = * (Handle *) ((Ptr) oldPtr - sizeof(Handle)); + if (tclUseMemTracking) { + hand = ((ListEl *) ((Ptr) oldPtr - tclExtraHdlSize))->memoryHandle; + } else { + hand = RecoverHandle((Ptr) oldPtr); + } maxsize = GetHandleSize(hand) - sizeof(Handle); if (maxsize < size) { + HUnlock(hand); + SetHandleSize(hand,size + tclExtraHdlSize); + err = MemError(); + HLock(hand); + if(err==noErr){ + newPtr=(*hand + tclExtraHdlSize); + } else { newPtr = TclpSysAlloc(size, 1); - memcpy(newPtr, oldPtr, maxsize); + if(newPtr!=NULL) { + memmove(newPtr, oldPtr, maxsize); TclpSysFree(oldPtr); + } + } } else { newPtr = oldPtr; } @@ -136,6 +163,31 @@ TclpSysAlloc( { Handle hand = NULL; ListEl * newMemoryRecord; + int isSysMem = 0; + static int initialized=0; + + if (!initialized) { + long response = 0; + OSErr err = noErr; + int useTempMem = 0; + + /* Check if we can use temporary memory */ + initialized=1; + err = Gestalt(gestaltOSAttr, &response); + if (err == noErr) { + useTempMem = response & (1 << gestaltRealTempMemory); + } + tclUseMemTracking = !useTempMem || (memoryFlags & MEMORY_DONT_USE_TEMPMEM); + if(tclUseMemTracking) { + tclExtraHdlSize = sizeof(ListEl); + /* + * We are allocating memory directly from the system + * heap. We need to install an exit handle + * to ensure the memory is cleaned up. + */ + TclMacInstallExitToShellPatch(CleanUpExitProc); + } + } if (!(memoryFlags & MEMORY_ALL_SYS)) { @@ -157,6 +209,7 @@ TclpSysAlloc( if (toolGuardHandle == NULL) { toolGuardHandle = NewHandle(TOOLBOX_SPACE); if (toolGuardHandle != NULL) { + HLock(toolGuardHandle); HPurge(toolGuardHandle); } } @@ -167,55 +220,55 @@ TclpSysAlloc( if (toolGuardHandle != NULL) { HLock(toolGuardHandle); - hand = NewHandle(size + sizeof(Handle)); + hand = NewHandle(size + tclExtraHdlSize); HUnlock(toolGuardHandle); } } - if (hand != NULL) { - newMemoryRecord = (ListEl *) NewPtr(sizeof(ListEl)); - if (newMemoryRecord == NULL) { - DisposeHandle(hand); - return NULL; - } - newMemoryRecord->memoryHandle = hand; - newMemoryRecord->next = appMemory; - appMemory = newMemoryRecord; - } else { + if (hand == NULL) { /* * Ran out of memory in application space. Lets try to get * more memory from system. Otherwise, we return NULL to * denote failure. */ + if(!tclUseMemTracking) { + /* Use Temporary Memory instead of System Heap when available */ + OSErr err; + isBin = 1; /* always HLockHi TempMemHandles */ + hand = TempNewHandle(size + tclExtraHdlSize,&err); + if(err!=noErr) { hand=NULL; } + } else { + /* Use system heap when tracking memory */ + isSysMem=1; isBin = 0; - hand = NewHandleSys(size + sizeof(Handle)); - if (hand == NULL) { - return NULL; + hand = NewHandleSys(size + tclExtraHdlSize); } - if (systemMemory == NULL) { - /* - * This is the first time we've attempted to allocate memory - * directly from the system heap. We need to now install the - * exit handle to ensure the memory is cleaned up. - */ - TclMacInstallExitToShellPatch(CleanUpExitProc); } - newMemoryRecord = (ListEl *) NewPtrSys(sizeof(ListEl)); - if (newMemoryRecord == NULL) { - DisposeHandle(hand); + if (hand == NULL) { return NULL; } - newMemoryRecord->memoryHandle = hand; - newMemoryRecord->next = systemMemory; - systemMemory = newMemoryRecord; - } if (isBin) { HLockHi(hand); } else { HLock(hand); } - (** (Handle **) hand) = hand; - - return (*hand + sizeof(Handle)); + if(tclUseMemTracking) { + /* Only need to do this when tracking memory */ + newMemoryRecord = (ListEl *) *hand; + newMemoryRecord->memoryHandle = hand; + newMemoryRecord->prec = NULL; + if(isSysMem) { + newMemoryRecord->next = systemMemory; + systemMemory = newMemoryRecord; + } else { + newMemoryRecord->next = appMemory; + appMemory = newMemoryRecord; + } + if(newMemoryRecord->next!=NULL) { + newMemoryRecord->next->prec=newMemoryRecord; + } + } + + return (*hand + tclExtraHdlSize); } /* @@ -238,13 +291,27 @@ void TclpSysFree( void * ptr) /* Free this system memory. */ { - Handle hand; - OSErr err; + if(tclUseMemTracking) { + /* Only need to do this when tracking memory */ + ListEl *memRecord; - hand = * (Handle *) ((Ptr) ptr - sizeof(Handle)); - DisposeHandle(hand); - *hand = NULL; - err = MemError(); + memRecord = (ListEl *) ((Ptr) ptr - tclExtraHdlSize); + /* Remove current record from linked list */ + if(memRecord->next!=NULL) { + memRecord->next->prec=memRecord->prec; + } + if(memRecord->prec!=NULL) { + memRecord->prec->next=memRecord->next; + } + if(memRecord==appMemory) { + appMemory=memRecord->next; + } else if(memRecord==systemMemory) { + systemMemory=memRecord->next; + } + DisposeHandle(memRecord->memoryHandle); + } else { + DisposeHandle(RecoverHandle((Ptr) ptr)); + } } /* @@ -271,13 +338,13 @@ CleanUpExitProc() { ListEl * memRecord; + if(tclUseMemTracking) { + /* Only need to do this when tracking memory */ while (systemMemory != NULL) { memRecord = systemMemory; systemMemory = memRecord->next; - if (*(memRecord->memoryHandle) != NULL) { - DisposeHandle(memRecord->memoryHandle); - } - DisposePtr((void *) memRecord); + DisposeHandle(memRecord->memoryHandle); + } } } @@ -304,21 +371,18 @@ FreeAllMemory() { ListEl * memRecord; + if(tclUseMemTracking) { + /* Only need to do this when tracking memory */ while (systemMemory != NULL) { memRecord = systemMemory; systemMemory = memRecord->next; - if (*(memRecord->memoryHandle) != NULL) { - DisposeHandle(memRecord->memoryHandle); - } - DisposePtr((void *) memRecord); + DisposeHandle(memRecord->memoryHandle); } while (appMemory != NULL) { memRecord = appMemory; appMemory = memRecord->next; - if (*(memRecord->memoryHandle) != NULL) { - DisposeHandle(memRecord->memoryHandle); - } - DisposePtr((void *) memRecord); + DisposeHandle(memRecord->memoryHandle); + } } } |