xref: /sqlite-3.40.0/src/mem1.c (revision 8a29dfde)
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