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
This commit is contained in:
@@ -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
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3f0a0ff1973079956506daaba9b21912fc76982b
|
||||
6f5eb74fd93a78ccdc2ddee0936ad4c5b2813720
|
||||
+66
-45
@@ -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);
|
||||
#endif
|
||||
while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) );
|
||||
if( !np || handleSoftLimit(OSSIZEOF(np) - oldsize) ){
|
||||
OSFREE(np);
|
||||
sqlite3FailedMalloc();
|
||||
OSMALLOC_FAILED();
|
||||
}
|
||||
if( sqlite3MallocFailed() ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !p ){
|
||||
return sqlite3Malloc(n);
|
||||
}else{
|
||||
void *np = 0;
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
int origSize = OSSIZEOF(p);
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user