| 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 |