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.17 2008/03/18 00:07:11 drh Exp $ 16 */ 17 #include "sqliteInt.h" 18 19 /* 20 ** This version of the memory allocator is the default. It is 21 ** used when no other memory allocator is specified using compile-time 22 ** macros. 23 */ 24 #ifdef SQLITE_SYSTEM_MALLOC 25 26 /* 27 ** All of the static variables used by this module are collected 28 ** into a single structure named "mem". This is to keep the 29 ** static variables organized and to reduce namespace pollution 30 ** when this module is combined with other in the amalgamation. 31 */ 32 static struct { 33 /* 34 ** The alarm callback and its arguments. The mem.mutex lock will 35 ** be held while the callback is running. Recursive calls into 36 ** the memory subsystem are allowed, but no new callbacks will be 37 ** issued. The alarmBusy variable is set to prevent recursive 38 ** callbacks. 39 */ 40 sqlite3_int64 alarmThreshold; 41 void (*alarmCallback)(void*, sqlite3_int64,int); 42 void *alarmArg; 43 int alarmBusy; 44 45 /* 46 ** Mutex to control access to the memory allocation subsystem. 47 */ 48 sqlite3_mutex *mutex; 49 50 /* 51 ** Current allocation and high-water mark. 52 */ 53 sqlite3_int64 nowUsed; 54 sqlite3_int64 mxUsed; 55 56 57 } mem; 58 59 /* 60 ** Enter the mutex mem.mutex. Allocate it if it is not already allocated. 61 */ 62 static void enterMem(void){ 63 if( mem.mutex==0 ){ 64 mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); 65 } 66 sqlite3_mutex_enter(mem.mutex); 67 } 68 69 /* 70 ** Return the amount of memory currently checked out. 71 */ 72 sqlite3_int64 sqlite3_memory_used(void){ 73 sqlite3_int64 n; 74 enterMem(); 75 n = mem.nowUsed; 76 sqlite3_mutex_leave(mem.mutex); 77 return n; 78 } 79 80 /* 81 ** Return the maximum amount of memory that has ever been 82 ** checked out since either the beginning of this process 83 ** or since the most recent reset. 84 */ 85 sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ 86 sqlite3_int64 n; 87 enterMem(); 88 n = mem.mxUsed; 89 if( resetFlag ){ 90 mem.mxUsed = mem.nowUsed; 91 } 92 sqlite3_mutex_leave(mem.mutex); 93 return n; 94 } 95 96 /* 97 ** Change the alarm callback 98 */ 99 int sqlite3_memory_alarm( 100 void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 101 void *pArg, 102 sqlite3_int64 iThreshold 103 ){ 104 enterMem(); 105 mem.alarmCallback = xCallback; 106 mem.alarmArg = pArg; 107 mem.alarmThreshold = iThreshold; 108 sqlite3_mutex_leave(mem.mutex); 109 return SQLITE_OK; 110 } 111 112 /* 113 ** Trigger the alarm 114 */ 115 static void sqlite3MemsysAlarm(int nByte){ 116 void (*xCallback)(void*,sqlite3_int64,int); 117 sqlite3_int64 nowUsed; 118 void *pArg; 119 if( mem.alarmCallback==0 || mem.alarmBusy ) return; 120 mem.alarmBusy = 1; 121 xCallback = mem.alarmCallback; 122 nowUsed = mem.nowUsed; 123 pArg = mem.alarmArg; 124 sqlite3_mutex_leave(mem.mutex); 125 xCallback(pArg, nowUsed, nByte); 126 sqlite3_mutex_enter(mem.mutex); 127 mem.alarmBusy = 0; 128 } 129 130 /* 131 ** Allocate nBytes of memory 132 */ 133 void *sqlite3_malloc(int nBytes){ 134 sqlite3_int64 *p = 0; 135 if( nBytes>0 ){ 136 enterMem(); 137 if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ 138 sqlite3MemsysAlarm(nBytes); 139 } 140 if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){ 141 p = 0; 142 }else{ 143 p = malloc(nBytes+8); 144 if( p==0 ){ 145 sqlite3MemsysAlarm(nBytes); 146 p = malloc(nBytes+8); 147 } 148 } 149 if( p ){ 150 p[0] = nBytes; 151 p++; 152 mem.nowUsed += nBytes; 153 if( mem.nowUsed>mem.mxUsed ){ 154 mem.mxUsed = mem.nowUsed; 155 } 156 } 157 sqlite3_mutex_leave(mem.mutex); 158 } 159 return (void*)p; 160 } 161 162 /* 163 ** Free memory. 164 */ 165 void sqlite3_free(void *pPrior){ 166 sqlite3_int64 *p; 167 int nByte; 168 if( pPrior==0 ){ 169 return; 170 } 171 assert( mem.mutex!=0 ); 172 p = pPrior; 173 p--; 174 nByte = (int)*p; 175 sqlite3_mutex_enter(mem.mutex); 176 mem.nowUsed -= nByte; 177 free(p); 178 sqlite3_mutex_leave(mem.mutex); 179 } 180 181 /* 182 ** Return the number of bytes allocated at p. 183 */ 184 int sqlite3MallocSize(void *p){ 185 sqlite3_int64 *pInt; 186 if( !p ) return 0; 187 pInt = p; 188 return pInt[-1]; 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 if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){ 213 p = 0; 214 }else{ 215 p = realloc(p, nBytes+8); 216 if( p==0 ){ 217 sqlite3MemsysAlarm(nBytes); 218 p = pPrior; 219 p--; 220 p = realloc(p, nBytes+8); 221 } 222 } 223 if( p ){ 224 p[0] = nBytes; 225 p++; 226 mem.nowUsed += nBytes-nOld; 227 if( mem.nowUsed>mem.mxUsed ){ 228 mem.mxUsed = mem.nowUsed; 229 } 230 } 231 sqlite3_mutex_leave(mem.mutex); 232 return (void*)p; 233 } 234 235 #endif /* SQLITE_SYSTEM_MALLOC */ 236