diff -r 5f8e5adbbed9 -r 29cda98b007e engine/sqlite/src/mem1.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/sqlite/src/mem1.cpp Thu Feb 25 14:29:19 2010 +0000 @@ -0,0 +1,232 @@ +/* +** 2007 August 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** $Id: mem1.cpp 1282 2008-11-13 09:31:33Z LarsPson $ +*/ + +/* +** This version of the memory allocator is the default. It is +** used when no other memory allocator is specified using compile-time +** macros. +*/ +#if !defined(SQLITE_MEMDEBUG) && !defined(SQLITE_MEMORY_SIZE) \ + && !defined(SQLITE_MMAP_HEAP_SIZE) + +/* +** We will eventually construct multiple memory allocation subsystems +** suitable for use in various contexts: +** +** * Normal multi-threaded builds +** * Normal single-threaded builds +** * Debugging builds +** +** This initial version is suitable for use in normal multi-threaded +** builds. We envision that alternative versions will be stored in +** separate source files. #ifdefs will be used to select the code from +** one of the various memN.c source files for use in any given build. +*/ +#include "sqliteInt.h" + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** The alarm callback and its arguments. The mem.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. The alarmBusy variable is set to prevent recursive + ** callbacks. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Current allocation and high-water mark. + */ + sqlite3_int64 nowUsed; + sqlite3_int64 mxUsed; + + +} mem; + +/* +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. +*/ +static void enterMem(void){ + if( mem.mutex==0 ){ + mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem.mutex); +} + +/* +** Return the amount of memory currently checked out. +*/ +EXPORT_C sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + enterMem(); + n = mem.nowUsed; + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +EXPORT_C sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; + enterMem(); + n = mem.mxUsed; + if( resetFlag ){ + mem.mxUsed = mem.nowUsed; + } + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Change the alarm callback +*/ +EXPORT_C int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + enterMem(); + mem.alarmCallback = xCallback; + mem.alarmArg = pArg; + mem.alarmThreshold = iThreshold; + sqlite3_mutex_leave(mem.mutex); + return SQLITE_OK; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MemsysAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem.alarmCallback==0 || mem.alarmBusy ) return; + mem.alarmBusy = 1; + xCallback = mem.alarmCallback; + nowUsed = mem.nowUsed; + pArg = mem.alarmArg; + sqlite3_mutex_leave(mem.mutex); + xCallback(pArg, nowUsed, nByte); + sqlite3_mutex_enter(mem.mutex); + mem.alarmBusy = 0; +} + +/* +** Allocate nBytes of memory +*/ +EXPORT_C void *sqlite3_malloc(int nBytes){ + sqlite3_int64 *p = 0; + if( nBytes>0 ){ + enterMem(); + if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes); + } + p = (sqlite3_int64*)malloc(nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = (sqlite3_int64*)malloc(nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + sqlite3_mutex_leave(mem.mutex); + } + return (void*)p; +} + +/* +** Free memory. +*/ +EXPORT_C void sqlite3_free(void *pPrior){ + sqlite3_int64 *p; + int nByte; + if( pPrior==0 ){ + return; + } + assert( mem.mutex!=0 ); + p = (sqlite3_int64*)pPrior; + p--; + nByte = (int)*p; + sqlite3_mutex_enter(mem.mutex); + mem.nowUsed -= nByte; + free(p); + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Change the size of an existing memory allocation +*/ +EXPORT_C void *sqlite3_realloc(void *pPrior, int nBytes){ + int nOld; + sqlite3_int64 *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + p = (sqlite3_int64*)pPrior; + p--; + nOld = (int)p[0]; + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes-nOld); + } + p = (sqlite3_int64*)realloc(p, nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = (sqlite3_int64*)pPrior; + p--; + p = (sqlite3_int64*)realloc(p, nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes-nOld; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + sqlite3_mutex_leave(mem.mutex); + return (void*)p; +} + +#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */