1 /* 2 ** 2007 August 14 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** This file contains the C functions that implement a memory 13 ** allocation subsystem for use by SQLite. 14 ** 15 ** $Id: mem1.c,v 1.13 2007/11/05 17:54:17 drh Exp $ 16 */ 17 18 /* 19 ** This version of the memory allocator is the default. It is 20 ** used when no other memory allocator is specified using compile-time 21 ** macros. 22 */ 23 #if !defined(SQLITE_MEMDEBUG) && !defined(SQLITE_MEMORY_SIZE) 24 25 /* 26 ** We will eventually construct multiple memory allocation subsystems 27 ** suitable for use in various contexts: 28 ** 29 ** * Normal multi-threaded builds 30 ** * Normal single-threaded builds 31 ** * Debugging builds 32 ** 33 ** This initial version is suitable for use in normal multi-threaded 34 ** builds. We envision that alternative versions will be stored in 35 ** separate source files. #ifdefs will be used to select the code from 36 ** one of the various memN.c source files for use in any given build. 37 */ 38 #include "sqliteInt.h" 39 40 /* 41 ** All of the static variables used by this module are collected 42 ** into a single structure named "mem". This is to keep the 43 ** static variables organized and to reduce namespace pollution 44 ** when this module is combined with other in the amalgamation. 45 */ 46 static struct { 47 /* 48 ** The alarm callback and its arguments. The mem.mutex lock will 49 ** be held while the callback is running. Recursive calls into 50 ** the memory subsystem are allowed, but no new callbacks will be 51 ** issued. The alarmBusy variable is set to prevent recursive 52 ** callbacks. 53 */ 54 sqlite3_int64 alarmThreshold; 55 void (*alarmCallback)(void*, sqlite3_int64,int); 56 void *alarmArg; 57 int alarmBusy; 58 59 /* 60 ** Mutex to control access to the memory allocation subsystem. 61 */ 62 sqlite3_mutex *mutex; 63 64 /* 65 ** Current allocation and high-water mark. 66 */ 67 sqlite3_int64 nowUsed; 68 sqlite3_int64 mxUsed; 69 70 71 } mem; 72 73 /* 74 ** Enter the mutex mem.mutex. Allocate it if it is not already allocated. 75 */ 76 static void enterMem(void){ 77 if( mem.mutex==0 ){ 78 mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); 79 } 80 sqlite3_mutex_enter(mem.mutex); 81 } 82 83 /* 84 ** Return the amount of memory currently checked out. 85 */ 86 sqlite3_int64 sqlite3_memory_used(void){ 87 sqlite3_int64 n; 88 enterMem(); 89 n = mem.nowUsed; 90 sqlite3_mutex_leave(mem.mutex); 91 return n; 92 } 93 94 /* 95 ** Return the maximum amount of memory that has ever been 96 ** checked out since either the beginning of this process 97 ** or since the most recent reset. 98 */ 99 sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ 100 sqlite3_int64 n; 101 enterMem(); 102 n = mem.mxUsed; 103 if( resetFlag ){ 104 mem.mxUsed = mem.nowUsed; 105 } 106 sqlite3_mutex_leave(mem.mutex); 107 return n; 108 } 109 110 /* 111 ** Change the alarm callback 112 */ 113 int sqlite3_memory_alarm( 114 void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 115 void *pArg, 116 sqlite3_int64 iThreshold 117 ){ 118 enterMem(); 119 mem.alarmCallback = xCallback; 120 mem.alarmArg = pArg; 121 mem.alarmThreshold = iThreshold; 122 sqlite3_mutex_leave(mem.mutex); 123 return SQLITE_OK; 124 } 125 126 /* 127 ** Trigger the alarm 128 */ 129 static void sqlite3MemsysAlarm(int nByte){ 130 void (*xCallback)(void*,sqlite3_int64,int); 131 sqlite3_int64 nowUsed; 132 void *pArg; 133 if( mem.alarmCallback==0 || mem.alarmBusy ) return; 134 mem.alarmBusy = 1; 135 xCallback = mem.alarmCallback; 136 nowUsed = mem.nowUsed; 137 pArg = mem.alarmArg; 138 sqlite3_mutex_leave(mem.mutex); 139 xCallback(pArg, nowUsed, nByte); 140 sqlite3_mutex_enter(mem.mutex); 141 mem.alarmBusy = 0; 142 } 143 144 /* 145 ** Allocate nBytes of memory 146 */ 147 void *sqlite3_malloc(int nBytes){ 148 sqlite3_int64 *p = 0; 149 if( nBytes>0 ){ 150 enterMem(); 151 if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ 152 sqlite3MemsysAlarm(nBytes); 153 } 154 p = malloc(nBytes+8); 155 if( p==0 ){ 156 sqlite3MemsysAlarm(nBytes); 157 p = malloc(nBytes+8); 158 } 159 if( p ){ 160 p[0] = nBytes; 161 p++; 162 mem.nowUsed += nBytes; 163 if( mem.nowUsed>mem.mxUsed ){ 164 mem.mxUsed = mem.nowUsed; 165 } 166 } 167 sqlite3_mutex_leave(mem.mutex); 168 } 169 return (void*)p; 170 } 171 172 /* 173 ** Free memory. 174 */ 175 void sqlite3_free(void *pPrior){ 176 sqlite3_int64 *p; 177 int nByte; 178 if( pPrior==0 ){ 179 return; 180 } 181 assert( mem.mutex!=0 ); 182 p = pPrior; 183 p--; 184 nByte = (int)*p; 185 sqlite3_mutex_enter(mem.mutex); 186 mem.nowUsed -= nByte; 187 free(p); 188 sqlite3_mutex_leave(mem.mutex); 189 } 190 191 /* 192 ** Change the size of an existing memory allocation 193 */ 194 void *sqlite3_realloc(void *pPrior, int nBytes){ 195 int nOld; 196 sqlite3_int64 *p; 197 if( pPrior==0 ){ 198 return sqlite3_malloc(nBytes); 199 } 200 if( nBytes<=0 ){ 201 sqlite3_free(pPrior); 202 return 0; 203 } 204 p = pPrior; 205 p--; 206 nOld = (int)p[0]; 207 assert( mem.mutex!=0 ); 208 sqlite3_mutex_enter(mem.mutex); 209 if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){ 210 sqlite3MemsysAlarm(nBytes-nOld); 211 } 212 p = realloc(p, nBytes+8); 213 if( p==0 ){ 214 sqlite3MemsysAlarm(nBytes); 215 p = pPrior; 216 p--; 217 p = realloc(p, nBytes+8); 218 } 219 if( p ){ 220 p[0] = nBytes; 221 p++; 222 mem.nowUsed += nBytes-nOld; 223 if( mem.nowUsed>mem.mxUsed ){ 224 mem.mxUsed = mem.nowUsed; 225 } 226 } 227 sqlite3_mutex_leave(mem.mutex); 228 return (void*)p; 229 } 230 231 #endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */ 232