summaryrefslogtreecommitdiffstats
path: root/mac
diff options
context:
space:
mode:
authordas <das@noemail.net>2001-05-17 13:30:01 (GMT)
committerdas <das@noemail.net>2001-05-17 13:30:01 (GMT)
commitda370f27864403589365c5083b908e1ccfea3254 (patch)
tree2932408b466ddb854268ad116bea7ab9b41ed78e /mac
parent9b2fc8ce7bd849f2a33ee0a0cdd1894ce0bbcb58 (diff)
downloadtcl-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.c174
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);
+ }
}
}