OLD | NEW |
1 /* | 1 /* |
2 ** 2007 October 14 | 2 ** 2007 October 14 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** This file contains the C functions that implement a memory | 12 ** This file contains the C functions that implement a memory |
13 ** allocation subsystem for use by SQLite. | 13 ** allocation subsystem for use by SQLite. |
14 ** | 14 ** |
15 ** This version of the memory allocation subsystem omits all | 15 ** This version of the memory allocation subsystem omits all |
16 ** use of malloc(). The application gives SQLite a block of memory | 16 ** use of malloc(). The application gives SQLite a block of memory |
17 ** before calling sqlite3_initialize() from which allocations | 17 ** before calling sqlite3_initialize() from which allocations |
18 ** are made and returned by the xMalloc() and xRealloc() | 18 ** are made and returned by the xMalloc() and xRealloc() |
19 ** implementations. Once sqlite3_initialize() has been called, | 19 ** implementations. Once sqlite3_initialize() has been called, |
20 ** the amount of memory available to SQLite is fixed and cannot | 20 ** the amount of memory available to SQLite is fixed and cannot |
21 ** be changed. | 21 ** be changed. |
22 ** | 22 ** |
23 ** This version of the memory allocation subsystem is included | 23 ** This version of the memory allocation subsystem is included |
24 ** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. | 24 ** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. |
25 ** | 25 ** |
26 ** This memory allocator uses the following algorithm: | 26 ** This memory allocator uses the following algorithm: |
27 ** | 27 ** |
28 ** 1. All memory allocations sizes are rounded up to a power of 2. | 28 ** 1. All memory allocation sizes are rounded up to a power of 2. |
29 ** | 29 ** |
30 ** 2. If two adjacent free blocks are the halves of a larger block, | 30 ** 2. If two adjacent free blocks are the halves of a larger block, |
31 ** then the two blocks are coalesced into the single larger block. | 31 ** then the two blocks are coalesced into the single larger block. |
32 ** | 32 ** |
33 ** 3. New memory is allocated from the first available free block. | 33 ** 3. New memory is allocated from the first available free block. |
34 ** | 34 ** |
35 ** This algorithm is described in: J. M. Robson. "Bounds for Some Functions | 35 ** This algorithm is described in: J. M. Robson. "Bounds for Some Functions |
36 ** Concerning Dynamic Storage Allocation". Journal of the Association for | 36 ** Concerning Dynamic Storage Allocation". Journal of the Association for |
37 ** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. | 37 ** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. |
38 ** | 38 ** |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 u64 totalExcess; /* Total internal fragmentation */ | 110 u64 totalExcess; /* Total internal fragmentation */ |
111 u32 currentOut; /* Current checkout, including internal fragmentation */ | 111 u32 currentOut; /* Current checkout, including internal fragmentation */ |
112 u32 currentCount; /* Current number of distinct checkouts */ | 112 u32 currentCount; /* Current number of distinct checkouts */ |
113 u32 maxOut; /* Maximum instantaneous currentOut */ | 113 u32 maxOut; /* Maximum instantaneous currentOut */ |
114 u32 maxCount; /* Maximum instantaneous currentCount */ | 114 u32 maxCount; /* Maximum instantaneous currentCount */ |
115 u32 maxRequest; /* Largest allocation (exclusive of internal frag) */ | 115 u32 maxRequest; /* Largest allocation (exclusive of internal frag) */ |
116 | 116 |
117 /* | 117 /* |
118 ** Lists of free blocks. aiFreelist[0] is a list of free blocks of | 118 ** Lists of free blocks. aiFreelist[0] is a list of free blocks of |
119 ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2. | 119 ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2. |
120 ** and so forth. | 120 ** aiFreelist[2] holds free blocks of size szAtom*4. And so forth. |
121 */ | 121 */ |
122 int aiFreelist[LOGMAX+1]; | 122 int aiFreelist[LOGMAX+1]; |
123 | 123 |
124 /* | 124 /* |
125 ** Space for tracking which blocks are checked out and the size | 125 ** Space for tracking which blocks are checked out and the size |
126 ** of each block. One byte per block. | 126 ** of each block. One byte per block. |
127 */ | 127 */ |
128 u8 *aCtrl; | 128 u8 *aCtrl; |
129 | 129 |
130 } mem5; | 130 } mem5; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize]; | 176 x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize]; |
177 MEM5LINK(i)->prev = -1; | 177 MEM5LINK(i)->prev = -1; |
178 if( x>=0 ){ | 178 if( x>=0 ){ |
179 assert( x<mem5.nBlock ); | 179 assert( x<mem5.nBlock ); |
180 MEM5LINK(x)->prev = i; | 180 MEM5LINK(x)->prev = i; |
181 } | 181 } |
182 mem5.aiFreelist[iLogsize] = i; | 182 mem5.aiFreelist[iLogsize] = i; |
183 } | 183 } |
184 | 184 |
185 /* | 185 /* |
186 ** If the STATIC_MEM mutex is not already held, obtain it now. The mutex | 186 ** Obtain or release the mutex needed to access global data structures. |
187 ** will already be held (obtained by code in malloc.c) if | |
188 ** sqlite3GlobalConfig.bMemStat is true. | |
189 */ | 187 */ |
190 static void memsys5Enter(void){ | 188 static void memsys5Enter(void){ |
191 sqlite3_mutex_enter(mem5.mutex); | 189 sqlite3_mutex_enter(mem5.mutex); |
192 } | 190 } |
193 static void memsys5Leave(void){ | 191 static void memsys5Leave(void){ |
194 sqlite3_mutex_leave(mem5.mutex); | 192 sqlite3_mutex_leave(mem5.mutex); |
195 } | 193 } |
196 | 194 |
197 /* | 195 /* |
198 ** Return the size of an outstanding allocation, in bytes. The | 196 ** Return the size of an outstanding allocation, in bytes. |
199 ** size returned omits the 8-byte header overhead. This only | 197 ** This only works for chunks that are currently checked out. |
200 ** works for chunks that are currently checked out. | |
201 */ | 198 */ |
202 static int memsys5Size(void *p){ | 199 static int memsys5Size(void *p){ |
203 int iSize = 0; | 200 int iSize, i; |
204 if( p ){ | 201 assert( p!=0 ); |
205 int i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom); | 202 i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom); |
206 assert( i>=0 && i<mem5.nBlock ); | 203 assert( i>=0 && i<mem5.nBlock ); |
207 iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE)); | 204 iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE)); |
208 } | |
209 return iSize; | 205 return iSize; |
210 } | 206 } |
211 | 207 |
212 /* | 208 /* |
213 ** Return a block of memory of at least nBytes in size. | 209 ** Return a block of memory of at least nBytes in size. |
214 ** Return NULL if unable. Return NULL if nBytes==0. | 210 ** Return NULL if unable. Return NULL if nBytes==0. |
215 ** | 211 ** |
216 ** The caller guarantees that nByte is positive. | 212 ** The caller guarantees that nByte is positive. |
217 ** | 213 ** |
218 ** The caller has obtained a mutex prior to invoking this | 214 ** The caller has obtained a mutex prior to invoking this |
219 ** routine so there is never any chance that two or more | 215 ** routine so there is never any chance that two or more |
220 ** threads can be in this routine at the same time. | 216 ** threads can be in this routine at the same time. |
221 */ | 217 */ |
222 static void *memsys5MallocUnsafe(int nByte){ | 218 static void *memsys5MallocUnsafe(int nByte){ |
223 int i; /* Index of a mem5.aPool[] slot */ | 219 int i; /* Index of a mem5.aPool[] slot */ |
224 int iBin; /* Index into mem5.aiFreelist[] */ | 220 int iBin; /* Index into mem5.aiFreelist[] */ |
225 int iFullSz; /* Size of allocation rounded up to power of 2 */ | 221 int iFullSz; /* Size of allocation rounded up to power of 2 */ |
226 int iLogsize; /* Log2 of iFullSz/POW2_MIN */ | 222 int iLogsize; /* Log2 of iFullSz/POW2_MIN */ |
227 | 223 |
228 /* nByte must be a positive */ | 224 /* nByte must be a positive */ |
229 assert( nByte>0 ); | 225 assert( nByte>0 ); |
230 | 226 |
231 /* Keep track of the maximum allocation request. Even unfulfilled | 227 /* Keep track of the maximum allocation request. Even unfulfilled |
232 ** requests are counted */ | 228 ** requests are counted */ |
233 if( (u32)nByte>mem5.maxRequest ){ | 229 if( (u32)nByte>mem5.maxRequest ){ |
| 230 /* Abort if the requested allocation size is larger than the largest |
| 231 ** power of two that we can represent using 32-bit signed integers. */ |
| 232 if( nByte > 0x40000000 ) return 0; |
234 mem5.maxRequest = nByte; | 233 mem5.maxRequest = nByte; |
235 } | 234 } |
236 | 235 |
237 /* Abort if the requested allocation size is larger than the largest | |
238 ** power of two that we can represent using 32-bit signed integers. | |
239 */ | |
240 if( nByte > 0x40000000 ){ | |
241 return 0; | |
242 } | |
243 | |
244 /* Round nByte up to the next valid power of two */ | 236 /* Round nByte up to the next valid power of two */ |
245 for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){
} | 237 for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){} |
246 | 238 |
247 /* Make sure mem5.aiFreelist[iLogsize] contains at least one free | 239 /* Make sure mem5.aiFreelist[iLogsize] contains at least one free |
248 ** block. If not, then split a block of the next larger power of | 240 ** block. If not, then split a block of the next larger power of |
249 ** two in order to create a new free block of size iLogsize. | 241 ** two in order to create a new free block of size iLogsize. |
250 */ | 242 */ |
251 for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){} | 243 for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){} |
252 if( iBin>LOGMAX ){ | 244 if( iBin>LOGMAX ){ |
253 testcase( sqlite3GlobalConfig.xLog!=0 ); | 245 testcase( sqlite3GlobalConfig.xLog!=0 ); |
254 sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); | 246 sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); |
255 return 0; | 247 return 0; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 assert( pPrior!=0 ); | 384 assert( pPrior!=0 ); |
393 assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */ | 385 assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */ |
394 assert( nBytes>=0 ); | 386 assert( nBytes>=0 ); |
395 if( nBytes==0 ){ | 387 if( nBytes==0 ){ |
396 return 0; | 388 return 0; |
397 } | 389 } |
398 nOld = memsys5Size(pPrior); | 390 nOld = memsys5Size(pPrior); |
399 if( nBytes<=nOld ){ | 391 if( nBytes<=nOld ){ |
400 return pPrior; | 392 return pPrior; |
401 } | 393 } |
402 memsys5Enter(); | 394 p = memsys5Malloc(nBytes); |
403 p = memsys5MallocUnsafe(nBytes); | |
404 if( p ){ | 395 if( p ){ |
405 memcpy(p, pPrior, nOld); | 396 memcpy(p, pPrior, nOld); |
406 memsys5FreeUnsafe(pPrior); | 397 memsys5Free(pPrior); |
407 } | 398 } |
408 memsys5Leave(); | |
409 return p; | 399 return p; |
410 } | 400 } |
411 | 401 |
412 /* | 402 /* |
413 ** Round up a request size to the next valid allocation size. If | 403 ** Round up a request size to the next valid allocation size. If |
414 ** the allocation is too large to be handled by this allocation system, | 404 ** the allocation is too large to be handled by this allocation system, |
415 ** return 0. | 405 ** return 0. |
416 ** | 406 ** |
417 ** All allocations must be a power of two and must be expressed by a | 407 ** All allocations must be a power of two and must be expressed by a |
418 ** 32-bit signed integer. Hence the largest allocation is 0x40000000 | 408 ** 32-bit signed integer. Hence the largest allocation is 0x40000000 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 memsys5Size, | 557 memsys5Size, |
568 memsys5Roundup, | 558 memsys5Roundup, |
569 memsys5Init, | 559 memsys5Init, |
570 memsys5Shutdown, | 560 memsys5Shutdown, |
571 0 | 561 0 |
572 }; | 562 }; |
573 return &memsys5Methods; | 563 return &memsys5Methods; |
574 } | 564 } |
575 | 565 |
576 #endif /* SQLITE_ENABLE_MEMSYS5 */ | 566 #endif /* SQLITE_ENABLE_MEMSYS5 */ |
OLD | NEW |