diff options
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 93 |
1 files changed, 58 insertions, 35 deletions
diff --git a/src/util.c b/src/util.c index 1670d1966..3f88da85c 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.175 2006/01/18 15:39:26 danielk1977 Exp $ +** $Id: util.c,v 1.176 2006/01/18 16:51:36 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -196,20 +196,27 @@ int sqlite3_memMax; /* TODO Mem usage high-water mark */ int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */ +void *sqlite3_pFirst = 0; /* Pointer to linked list of allocations */ +int sqlite3_nMaxAlloc = 0; /* High water mark of ThreadData.nAlloc */ +int sqlite3_mallocDisallowed = 0; /* assert() in sqlite3Malloc() if set */ +int sqlite3_isFail = 0; /* True if all malloc calls should fail */ +const char *sqlite3_zFile = 0; /* Filename to associate debug info with */ +int sqlite3_iLine = 0; /* Line number for debug info */ + /* ** Check for a simulated memory allocation failure. Return true if ** the failure should be simulated. Return false to proceed as normal. */ static int failMalloc(){ ThreadData *pTsd = sqlite3ThreadData(); - if( pTsd->isFail ){ + if( sqlite3_isFail ){ return 1; } if( sqlite3_iMallocFail>=0 ){ sqlite3_iMallocFail--; if( sqlite3_iMallocFail==0 ){ sqlite3_iMallocFail = sqlite3_iMallocReset; - pTsd->isFail = 1; + sqlite3_isFail = 1; return 1; } } @@ -269,11 +276,11 @@ static void applyGuards(u32 *p) /* Line number */ z = &((char *)z)[TESTALLOC_NGUARD*sizeof(u32)]; /* Guard words */ z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)]; - memcpy(z, &sqlite3ThreadData()->iLine, sizeof(u32)); + memcpy(z, &sqlite3_iLine, sizeof(u32)); /* File name */ z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)]; - strncpy(z, sqlite3ThreadData()->zFile, TESTALLOC_FILESIZE); + strncpy(z, sqlite3_zFile, TESTALLOC_FILESIZE); z[TESTALLOC_FILESIZE - 1] = '\0'; /* User string */ @@ -312,11 +319,11 @@ static void linkAlloc(void *p){ ThreadData *pTsd = sqlite3ThreadData(); void **pp = (void **)p; pp[0] = 0; - pp[1] = pTsd->pFirst; - if( pTsd->pFirst ){ - ((void **)pTsd->pFirst)[0] = p; + pp[1] = sqlite3_pFirst; + if( sqlite3_pFirst ){ + ((void **)sqlite3_pFirst)[0] = p; } - pTsd->pFirst = p; + sqlite3_pFirst = p; } /* @@ -327,12 +334,12 @@ static void unlinkAlloc(void *p) { ThreadData *pTsd = sqlite3ThreadData(); void **pp = (void **)p; - if( p==pTsd->pFirst ){ + if( p==sqlite3_pFirst ){ assert(!pp[0]); assert(!pp[1] || ((void **)(pp[1]))[0]==p); - pTsd->pFirst = pp[1]; - if( pTsd->pFirst ){ - ((void **)pTsd->pFirst)[0] = 0; + sqlite3_pFirst = pp[1]; + if( sqlite3_pFirst ){ + ((void **)sqlite3_pFirst)[0] = 0; } }else{ void **pprev = pp[0]; @@ -359,7 +366,7 @@ static void relinkAlloc(void *p) ((void **)(pp[0]))[1] = p; }else{ ThreadData *pTsd = sqlite3ThreadData(); - pTsd->pFirst = p; + sqlite3_pFirst = p; } if( pp[1] ){ ((void **)(pp[1]))[0] = p; @@ -394,7 +401,7 @@ int sqlite3OutstandingMallocs(Tcl_Interp *interp){ Tcl_Obj *pRes = Tcl_NewObj(); Tcl_IncrRefCount(pRes); - for(p=pTsd->pFirst; p; p=((void **)p)[1]){ + for(p=sqlite3_pFirst; p; p=((void **)p)[1]){ Tcl_Obj *pEntry = Tcl_NewObj(); Tcl_Obj *pStack = Tcl_NewObj(); char *z; @@ -439,9 +446,9 @@ int sqlite3OutstandingMallocs(Tcl_Interp *interp){ static void * OSMALLOC(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT ThreadData *pTsd = sqlite3ThreadData(); - pTsd->nMaxAlloc = MAX(pTsd->nMaxAlloc, pTsd->nAlloc); + sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc); #endif - assert( !sqlite3ThreadData()->mallocDisallowed ); + assert( !sqlite3_mallocDisallowed ); if( !failMalloc() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); @@ -481,9 +488,9 @@ static void OSFREE(void *pFree){ static void * OSREALLOC(void *pRealloc, int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT ThreadData *pTsd = sqlite3ThreadData(); - pTsd->nMaxAlloc = MAX(pTsd->nMaxAlloc, pTsd->nAlloc); + sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc); #endif - assert( !sqlite3ThreadData()->mallocDisallowed ); + assert( !sqlite3_mallocDisallowed ); if( !failMalloc() ){ u32 *p = (u32 *)getOsPointer(pRealloc); checkGuards(p); @@ -496,7 +503,7 @@ static void * OSREALLOC(void *pRealloc, int n){ } static void OSMALLOC_FAILED(){ - sqlite3ThreadData()->isFail = 0; + sqlite3_isFail = 0; } #else @@ -549,7 +556,7 @@ static void handleSoftLimit(int n){ */ void *sqlite3MallocRaw(int n){ void *p = 0; - if( n>0 && !sqlite3ThreadDataReadOnly()->mallocFailed ){ + if( n>0 && !sqlite3MallocFailed() ){ handleSoftLimit(n); while( !(p = OSMALLOC(n)) && sqlite3_release_memory(n) ); if( !p ){ @@ -559,7 +566,7 @@ void *sqlite3MallocRaw(int n){ ** still correct after a malloc() failure. */ handleSoftLimit(n * -1); - sqlite3ThreadData()->mallocFailed = 1; + sqlite3FailedMalloc(); OSMALLOC_FAILED(); } } @@ -572,7 +579,7 @@ void *sqlite3MallocRaw(int n){ ** attempt to free memory by calling sqlite3_release_memory(). */ void *sqlite3Realloc(void *p, int n){ - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ + if( sqlite3MallocFailed() ){ return 0; } @@ -589,7 +596,7 @@ void *sqlite3Realloc(void *p, int n){ ** still correct after a malloc() failure. */ handleSoftLimit(OSSIZEOF(p) - n); - sqlite3ThreadData()->mallocFailed = 1; + sqlite3FailedMalloc(); OSMALLOC_FAILED(); } return np; @@ -1350,26 +1357,42 @@ void sqlite3ReleaseThreadData(){ ** then the connection error-code (the value returned by sqlite3_errcode()) ** is set to SQLITE_NOMEM. */ +static int mallocHasFailed = 0; int sqlite3ApiExit(sqlite3* db, int rc){ - ThreadData *pTd = sqlite3OsThreadSpecificData(0); - if( pTd && pTd->mallocFailed ){ - pTd->mallocFailed = 0; - if( db ){ - sqlite3Error(db, SQLITE_NOMEM, 0); - } - return SQLITE_NOMEM; + if( sqlite3MallocFailed() ){ + mallocHasFailed = 0; + sqlite3OsLeaveMutex(); + sqlite3Error(db, SQLITE_NOMEM, 0); + rc = SQLITE_NOMEM; } return rc; } +/* +** Return true is a malloc has failed in this thread since the last call +** to sqlite3ApiExit(), or false otherwise. +*/ +int sqlite3MallocFailed(){ + return (mallocHasFailed && sqlite3OsInMutex()); +} + +/* +** Set the "malloc has failed" condition to true for this thread. +*/ +void sqlite3FailedMalloc(){ + sqlite3OsEnterMutex(); + assert( mallocHasFailed==0 ); + mallocHasFailed = 1; +} + #ifdef SQLITE_MEMDEBUG /* ** This function sets a flag in the thread-specific-data structure that will ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. */ void sqlite3MallocDisallow(){ - assert( sqlite3ThreadData()->mallocDisallowed>=0 ); - sqlite3ThreadData()->mallocDisallowed++; + assert( sqlite3_mallocDisallowed>=0 ); + sqlite3_mallocDisallowed++; } /* @@ -1377,7 +1400,7 @@ void sqlite3MallocDisallow(){ ** by sqlite3MallocDisallow(). */ void sqlite3MallocAllow(){ - assert( sqlite3ThreadData()->mallocDisallowed>0 ); - sqlite3ThreadData()->mallocDisallowed--; + assert( sqlite3_mallocDisallowed>0 ); + sqlite3_mallocDisallowed--; } #endif |