diff options
author | drh <drh@noemail.net> | 2007-08-15 13:04:54 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2007-08-15 13:04:54 +0000 |
commit | 90f6a5beff55f81faa7135189c65cbd8a569e63c (patch) | |
tree | 900595d8e00a7a44978f9686322a3ed50a73dcbc /src/mem1.c | |
parent | d84f946be8340e2c9c7d86475665ae1610608e0e (diff) | |
download | sqlite-90f6a5beff55f81faa7135189c65cbd8a569e63c.tar.gz sqlite-90f6a5beff55f81faa7135189c65cbd8a569e63c.zip |
Add initial implementations of mutex and memory subsystem modules. (CVS 4226)
FossilOrigin-Name: c0fa3769790af199a4c8715c80bb8ff900730520
Diffstat (limited to 'src/mem1.c')
-rw-r--r-- | src/mem1.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/mem1.c b/src/mem1.c new file mode 100644 index 000000000..ba4c8e950 --- /dev/null +++ b/src/mem1.c @@ -0,0 +1,204 @@ +/* +** 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.c,v 1.1 2007/08/15 13:04:54 drh Exp $ +*/ + +/* +** 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" + + +/* +** Mutex to control access to the memory allocation subsystem. +*/ +static sqlite3_mutex *memMutex = 0; + +/* +** Current allocation and high-water mark. +*/ +static sqlite3_uint64 nowUsed = 0; +static sqlite3_uint64 mxUsed = 0; + +/* +** The alarm callback and its arguments. The memMutex 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. +*/ +static void (*alarmCallback)(void*, sqlite3_uint64, unsigned) = 0; +static void *alarmArg = 0; +static sqlite3_uint64 alarmThreshold = (((sqlite3_uint64)1)<<63); +static int alarmBusy = 0; + + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_uint64 sqlite3_memory_used(void){ + sqlite3_uint64 n; + if( memMutex==0 ){ + memMutex = sqlite3_mutex_alloc(1); + } + sqlite3_mutex_enter(memMutex, 1); + n = nowUsed; + sqlite3_mutex_leave(memMutex); + 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. +*/ +sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_uint64 n; + if( memMutex==0 ){ + memMutex = sqlite3_mutex_alloc(1); + } + sqlite3_mutex_enter(memMutex, 1); + n = mxUsed; + if( resetFlag ){ + mxUsed = nowUsed; + } + sqlite3_mutex_leave(memMutex); + return n; +} + +/* +** Change the alarm callback +*/ +int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_uint64 used, unsigned int N), + void *pArg, + sqlite3_uint64 iThreshold +){ + if( memMutex==0 ){ + memMutex = sqlite3_mutex_alloc(1); + } + sqlite3_mutex_enter(memMutex, 1); + alarmCallback = xCallback; + alarmArg = pArg; + alarmThreshold = iThreshold; + sqlite3_mutex_leave(memMutex); + return SQLITE_OK; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MemsysAlarm(unsigned nByte){ + if( alarmCallback==0 || alarmBusy ) return; + alarmBusy = 1; + alarmCallback(alarmArg, nowUsed, nByte); + alarmBusy = 0; +} + +/* +** Allocate nBytes of memory +*/ +void *sqlite3_malloc(unsigned int nBytes){ + sqlite3_uint64 *p; + if( memMutex==0 ){ + memMutex = sqlite3_mutex_alloc(1); + } + sqlite3_mutex_enter(memMutex, 1); + if( nowUsed+nBytes>=alarmThreshold ){ + sqlite3MemsysAlarm(nBytes); + } + p = malloc(nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = malloc(nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + nowUsed += nBytes; + if( nowUsed>mxUsed ){ + mxUsed = nowUsed; + } + } + sqlite3_mutex_leave(memMutex); + return (void*)p; +} + +/* +** Free memory. +*/ +void sqlite3_free(void *pPrior){ + sqlite3_uint64 *p; + unsigned nByte; + if( pPrior==0 ){ + return; + } + assert( memMutex!=0 ); + p = pPrior; + p--; + nByte = (unsigned int)*p; + sqlite3_mutex_enter(memMutex, 1); + nowUsed -= nByte; + free(p); + sqlite3_mutex_leave(memMutex); +} + +/* +** Change the size of an existing memory allocation +*/ +void *sqlite3_realloc(void *pPrior, unsigned int nBytes){ + unsigned nOld; + sqlite3_uint64 *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes==0 ){ + sqlite3_free(pPrior); + return; + } + p = pPrior; + p--; + nOld = (unsigned int)p[0]; + assert( memMutex!=0 ); + sqlite3_mutex_enter(memMutex, 1); + if( nowUsed+nBytes-nOld>=alarmThreshold ){ + sqlite3MemsysAlarm(nBytes-nOld); + } + p = realloc(p, nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = realloc(p, nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + nowUsed += nBytes-nOld; + if( nowUsed>mxUsed ){ + mxUsed = nowUsed; + } + } + sqlite3_mutex_leave(memMutex); + return (void*)p; +} |