1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sqlite/sqlite-source/mem1.c Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,229 @@
1.4 +/*
1.5 +** 2007 August 14
1.6 +**
1.7 +** The author disclaims copyright to this source code. In place of
1.8 +** a legal notice, here is a blessing:
1.9 +**
1.10 +** May you do good and not evil.
1.11 +** May you find forgiveness for yourself and forgive others.
1.12 +** May you share freely, never taking more than you give.
1.13 +**
1.14 +*************************************************************************
1.15 +** This file contains the C functions that implement a memory
1.16 +** allocation subsystem for use by SQLite.
1.17 +**
1.18 +** $Id$
1.19 +*/
1.20 +
1.21 +/*
1.22 +** This version of the memory allocator is the default. It is
1.23 +** used when no other memory allocator is specified using compile-time
1.24 +** macros.
1.25 +*/
1.26 +#if !defined(SQLITE_MEMDEBUG) && !defined(SQLITE_OMIT_MEMORY_ALLOCATION)
1.27 +
1.28 +/*
1.29 +** We will eventually construct multiple memory allocation subsystems
1.30 +** suitable for use in various contexts:
1.31 +**
1.32 +** * Normal multi-threaded builds
1.33 +** * Normal single-threaded builds
1.34 +** * Debugging builds
1.35 +**
1.36 +** This initial version is suitable for use in normal multi-threaded
1.37 +** builds. We envision that alternative versions will be stored in
1.38 +** separate source files. #ifdefs will be used to select the code from
1.39 +** one of the various memN.c source files for use in any given build.
1.40 +*/
1.41 +#include "sqliteInt.h"
1.42 +
1.43 +/*
1.44 +** All of the static variables used by this module are collected
1.45 +** into a single structure named "mem". This is to keep the
1.46 +** static variables organized and to reduce namespace pollution
1.47 +** when this module is combined with other in the amalgamation.
1.48 +*/
1.49 +static struct {
1.50 + /*
1.51 + ** The alarm callback and its arguments. The mem.mutex lock will
1.52 + ** be held while the callback is running. Recursive calls into
1.53 + ** the memory subsystem are allowed, but no new callbacks will be
1.54 + ** issued. The alarmBusy variable is set to prevent recursive
1.55 + ** callbacks.
1.56 + */
1.57 + sqlite3_int64 alarmThreshold;
1.58 + void (*alarmCallback)(void*, sqlite3_int64,int);
1.59 + void *alarmArg;
1.60 + int alarmBusy;
1.61 +
1.62 + /*
1.63 + ** Mutex to control access to the memory allocation subsystem.
1.64 + */
1.65 + sqlite3_mutex *mutex;
1.66 +
1.67 + /*
1.68 + ** Current allocation and high-water mark.
1.69 + */
1.70 + sqlite3_int64 nowUsed;
1.71 + sqlite3_int64 mxUsed;
1.72 +
1.73 +
1.74 +} mem;
1.75 +
1.76 +/*
1.77 +** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
1.78 +*/
1.79 +static void enterMem(void){
1.80 + if( mem.mutex==0 ){
1.81 + mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
1.82 + }
1.83 + sqlite3_mutex_enter(mem.mutex);
1.84 +}
1.85 +
1.86 +/*
1.87 +** Return the amount of memory currently checked out.
1.88 +*/
1.89 +sqlite3_int64 sqlite3_memory_used(void){
1.90 + sqlite3_int64 n;
1.91 + enterMem();
1.92 + n = mem.nowUsed;
1.93 + sqlite3_mutex_leave(mem.mutex);
1.94 + return n;
1.95 +}
1.96 +
1.97 +/*
1.98 +** Return the maximum amount of memory that has ever been
1.99 +** checked out since either the beginning of this process
1.100 +** or since the most recent reset.
1.101 +*/
1.102 +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
1.103 + sqlite3_int64 n;
1.104 + enterMem();
1.105 + n = mem.mxUsed;
1.106 + if( resetFlag ){
1.107 + mem.mxUsed = mem.nowUsed;
1.108 + }
1.109 + sqlite3_mutex_leave(mem.mutex);
1.110 + return n;
1.111 +}
1.112 +
1.113 +/*
1.114 +** Change the alarm callback
1.115 +*/
1.116 +int sqlite3_memory_alarm(
1.117 + void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
1.118 + void *pArg,
1.119 + sqlite3_int64 iThreshold
1.120 +){
1.121 + enterMem();
1.122 + mem.alarmCallback = xCallback;
1.123 + mem.alarmArg = pArg;
1.124 + mem.alarmThreshold = iThreshold;
1.125 + sqlite3_mutex_leave(mem.mutex);
1.126 + return SQLITE_OK;
1.127 +}
1.128 +
1.129 +/*
1.130 +** Trigger the alarm
1.131 +*/
1.132 +static void sqlite3MemsysAlarm(int nByte){
1.133 + void (*xCallback)(void*,sqlite3_int64,int);
1.134 + sqlite3_int64 nowUsed;
1.135 + void *pArg;
1.136 + if( mem.alarmCallback==0 || mem.alarmBusy ) return;
1.137 + mem.alarmBusy = 1;
1.138 + xCallback = mem.alarmCallback;
1.139 + nowUsed = mem.nowUsed;
1.140 + pArg = mem.alarmArg;
1.141 + sqlite3_mutex_leave(mem.mutex);
1.142 + xCallback(pArg, nowUsed, nByte);
1.143 + sqlite3_mutex_enter(mem.mutex);
1.144 + mem.alarmBusy = 0;
1.145 +}
1.146 +
1.147 +/*
1.148 +** Allocate nBytes of memory
1.149 +*/
1.150 +void *sqlite3_malloc(int nBytes){
1.151 + sqlite3_int64 *p = 0;
1.152 + if( nBytes>0 ){
1.153 + enterMem();
1.154 + if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
1.155 + sqlite3MemsysAlarm(nBytes);
1.156 + }
1.157 + p = malloc(nBytes+8);
1.158 + if( p==0 ){
1.159 + sqlite3MemsysAlarm(nBytes);
1.160 + p = malloc(nBytes+8);
1.161 + }
1.162 + if( p ){
1.163 + p[0] = nBytes;
1.164 + p++;
1.165 + mem.nowUsed += nBytes;
1.166 + if( mem.nowUsed>mem.mxUsed ){
1.167 + mem.mxUsed = mem.nowUsed;
1.168 + }
1.169 + }
1.170 + sqlite3_mutex_leave(mem.mutex);
1.171 + }
1.172 + return (void*)p;
1.173 +}
1.174 +
1.175 +/*
1.176 +** Free memory.
1.177 +*/
1.178 +void sqlite3_free(void *pPrior){
1.179 + sqlite3_int64 *p;
1.180 + int nByte;
1.181 + if( pPrior==0 ){
1.182 + return;
1.183 + }
1.184 + assert( mem.mutex!=0 );
1.185 + p = pPrior;
1.186 + p--;
1.187 + nByte = (int)*p;
1.188 + sqlite3_mutex_enter(mem.mutex);
1.189 + mem.nowUsed -= nByte;
1.190 + free(p);
1.191 + sqlite3_mutex_leave(mem.mutex);
1.192 +}
1.193 +
1.194 +/*
1.195 +** Change the size of an existing memory allocation
1.196 +*/
1.197 +void *sqlite3_realloc(void *pPrior, int nBytes){
1.198 + int nOld;
1.199 + sqlite3_int64 *p;
1.200 + if( pPrior==0 ){
1.201 + return sqlite3_malloc(nBytes);
1.202 + }
1.203 + if( nBytes<=0 ){
1.204 + sqlite3_free(pPrior);
1.205 + return 0;
1.206 + }
1.207 + p = pPrior;
1.208 + p--;
1.209 + nOld = (int)p[0];
1.210 + assert( mem.mutex!=0 );
1.211 + sqlite3_mutex_enter(mem.mutex);
1.212 + if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
1.213 + sqlite3MemsysAlarm(nBytes-nOld);
1.214 + }
1.215 + p = realloc(p, nBytes+8);
1.216 + if( p==0 ){
1.217 + sqlite3MemsysAlarm(nBytes);
1.218 + p = realloc(p, nBytes+8);
1.219 + }
1.220 + if( p ){
1.221 + p[0] = nBytes;
1.222 + p++;
1.223 + mem.nowUsed += nBytes-nOld;
1.224 + if( mem.nowUsed>mem.mxUsed ){
1.225 + mem.mxUsed = mem.nowUsed;
1.226 + }
1.227 + }
1.228 + sqlite3_mutex_leave(mem.mutex);
1.229 + return (void*)p;
1.230 +}
1.231 +
1.232 +#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */