From: drh Date: Mon, 6 Feb 2006 21:22:30 +0000 (+0000) Subject: Keep correct track of the amount of outstanding memory even when the X-Git-Tag: version-3.3.4~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=444059718786cece96a9d47ac486f05001535670;p=thirdparty%2Fsqlite.git Keep correct track of the amount of outstanding memory even when the system memory allocator returns a different number of bytes than requested. Ticket #1660. (CVS 3057) FossilOrigin-Name: 6f5eb74fd93a78ccdc2ddee0936ad4c5b2813720 --- diff --git a/manifest b/manifest index a727208cda..753e03905b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sper-thread\sbytes\sallocated\scounter\swith\sthe\snumber\sof\sbytes\sactually\sallocated,\snot\sthe\snumber\srequested.\sTicket\s#1660.\s(CVS\s3056) -D 2006-02-06T13:59:43 +C Keep\scorrect\strack\sof\sthe\samount\sof\soutstanding\smemory\seven\swhen\sthe\nsystem\smemory\sallocator\sreturns\sa\sdifferent\snumber\sof\sbytes\sthan\nrequested.\s\sTicket\s#1660.\s(CVS\s3057) +D 2006-02-06T21:22:31 F Makefile.in 5d8dff443383918b700e495de42ec65bc1c8865b F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -87,7 +87,7 @@ F src/tokenize.c 9ae9a59238eb97fbc61baea280563b91100518fb F src/trigger.c 4d3644cbd16959b568c95ae73493402be8021b08 F src/update.c 14be4ba2f438919b4217085c02feff569e6cf1f2 F src/utf.c 1199766bbb0157931a83aa6eede6b6381177be64 -F src/util.c 36ce845aa173c7347251e7462d61f937b78c88fb +F src/util.c 405f46fef062b476826d2c171ec21def29563b75 F src/vacuum.c 3865673cc66acd0717ecd517f6b8fdb2a5e7924b F src/vdbe.c 29c68f39ce8cba44814b0e1f3d909ef961eb28a7 F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 @@ -350,7 +350,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P f5341529d0cdbd63ce4c33606858158b6093969a -R 74794a57a00f0992fd89f2fde95755fd -U danielk1977 -Z eb9ce12217e4d8db003d2eaae05f7ed8 +P 3f0a0ff1973079956506daaba9b21912fc76982b +R 223918435068480aa41a0976a6bec9c9 +U drh +Z 06a3dbaa3b53376bd535876b78dfb2ea diff --git a/manifest.uuid b/manifest.uuid index 24a7d460ab..f2af9b08f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3f0a0ff1973079956506daaba9b21912fc76982b \ No newline at end of file +6f5eb74fd93a78ccdc2ddee0936ad4c5b2813720 \ No newline at end of file diff --git a/src/util.c b/src/util.c index 569a447218..0f2bc94aa3 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.183 2006/02/06 13:59:43 danielk1977 Exp $ +** $Id: util.c,v 1.184 2006/02/06 21:22:31 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -142,13 +142,6 @@ int sqlite3_release_memory(int n){ #define TESTALLOC_USERSIZE 64 const char *sqlite3_malloc_id = 0; -/* -** Always allocate blocks to be a multiple of the following size in bytes. -** For example, if TESTALLOC_QUANTA is 8 and a block of 21 bytes is -** requested, return a pointer to a block of 24 bytes. -*/ -#define TESTALLOC_QUANTA 8 - /* ** Blocks used by the test layer have the following format: ** @@ -406,6 +399,7 @@ int sqlite3OutstandingMallocs(Tcl_Interp *interp){ Tcl_Obj *pRes = Tcl_NewObj(); Tcl_IncrRefCount(pRes); + for(p=sqlite3_pFirst; p; p=((void **)p)[1]){ Tcl_Obj *pEntry = Tcl_NewObj(); Tcl_Obj *pStack = Tcl_NewObj(); @@ -454,7 +448,6 @@ static void * OSMALLOC(int n){ MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); #endif assert( !sqlite3_mallocDisallowed ); - n += (TESTALLOC_QUANTA - (n % TESTALLOC_QUANTA)) % TESTALLOC_QUANTA; if( !sqlite3TestMallocFail() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); @@ -496,14 +489,10 @@ static void * OSREALLOC(void *pRealloc, int n){ sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); #endif - n += (TESTALLOC_QUANTA - (n % TESTALLOC_QUANTA)) % TESTALLOC_QUANTA; assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ - u32 *p = 0; - if( pRealloc ){ - u32 *p = (u32 *)getOsPointer(pRealloc); - checkGuards(p); - } + u32 *p = (u32 *)getOsPointer(pRealloc); + checkGuards(p); p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD); applyGuards(p); relinkAlloc(p); @@ -532,34 +521,56 @@ static void OSMALLOC_FAILED(){ **--------------------------------------------------------------------------*/ /* -** The handleSoftLimit() function is called before each call to -** sqlite3OsMalloc() or xRealloc(). The parameter 'n' is the number of -** extra bytes about to be allocated (for Realloc() this means the size of the -** new allocation less the size of the old allocation). If the extra allocation -** means that the total memory allocated to SQLite in this thread would exceed -** the limit set by sqlite3_soft_heap_limit(), then sqlite3_release_memory() is -** called to try to avoid this. No indication of whether or not this is -** successful is returned to the caller. +** This routine is called when we are about to allocate n additional bytes +** of memory. If the new allocation will put is over the soft allocation +** limit, then invoke sqlite3_release_memory() to try to release some +** memory before continuing with the allocation. +** +** This routine also makes sure that the thread-specific-data (TSD) has +** be allocated. If it has not and can not be allocated, then return +** false. The updateMemoryUsedCount() routine below will deallocate +** the TSD if it ought to be. +** +** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is +** a no-op +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +static int enforceSoftLimit(int n){ + ThreadData *pTsd = sqlite3ThreadData(); + if( pTsd==0 ){ + return 0; + } + assert( pTsd->nAlloc>=0 ); + if( n>0 && pTsd->nSoftHeapLimit>0 ){ + while( pTsd->nAlloc+n>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ); + } + return 1; +} +#else +# define enforceSoftLimit(X) 1 +#endif + +/* +** Update the count of total outstanding memory that is held in +** thread-specific-data (TSD). If after this update the TSD is +** no longer being used, then deallocate it. ** ** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is ** a no-op */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -static int handleSoftLimit(int n){ +static void updateMemoryUsedCount(int n){ ThreadData *pTsd = sqlite3ThreadData(); if( pTsd ){ pTsd->nAlloc += n; assert( pTsd->nAlloc>=0 ); - if( n>0 && pTsd->nSoftHeapLimit>0 ){ - while( pTsd->nAlloc>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ); - }else if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){ + if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){ sqlite3ReleaseThreadData(); } } - return (pTsd ? 0 : 1); } #else -#define handleSoftLimit(x) 0 +#define updateMemoryUsedCount(x) /* no-op */ #endif /* @@ -569,12 +580,13 @@ static int handleSoftLimit(int n){ */ void *sqlite3MallocRaw(int n){ void *p = 0; - if( n>0 && !sqlite3MallocFailed() ){ + if( n>0 && !sqlite3MallocFailed() && enforceSoftLimit(n) ){ while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ); - if( !p || handleSoftLimit(OSSIZEOF(p)) ){ - OSFREE(p); + if( !p ){ sqlite3FailedMalloc(); OSMALLOC_FAILED(); + }else{ + updateMemoryUsedCount(OSSIZEOF(p)); } } return p; @@ -586,19 +598,28 @@ void *sqlite3MallocRaw(int n){ ** attempt to free memory by calling sqlite3_release_memory(). */ void *sqlite3Realloc(void *p, int n){ - void *np = 0; - if( !sqlite3MallocFailed() ){ -#ifndef SQLITE_ENABLE_MEMORY_MANAGEMENT - int oldsize = OSSIZEOF(p); + if( sqlite3MallocFailed() ){ + return 0; + } + + if( !p ){ + return sqlite3Malloc(n); + }else{ + void *np = 0; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int origSize = OSSIZEOF(p); #endif - while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ); - if( !np || handleSoftLimit(OSSIZEOF(np) - oldsize) ){ - OSFREE(np); - sqlite3FailedMalloc(); - OSMALLOC_FAILED(); + if( enforceSoftLimit(n - origSize) ){ + while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ); + if( !np ){ + sqlite3FailedMalloc(); + OSMALLOC_FAILED(); + }else{ + updateMemoryUsedCount(OSSIZEOF(np) - origSize); + } } + return np; } - return np; } /* @@ -606,8 +627,8 @@ void *sqlite3Realloc(void *p, int n){ ** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc(). */ void sqlite3FreeX(void *p){ - (void)handleSoftLimit(0 - OSSIZEOF(p)); if( p ){ + updateMemoryUsedCount(0 - OSSIZEOF(p)); OSFREE(p); } }