1 /* 2 ** 2007 October 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 ** This version of the memory allocation subsystem omits all 16 ** use of malloc(). All dynamically allocatable memory is 17 ** contained in a static array, mem.aPool[]. The size of this 18 ** fixed memory pool is SQLITE_MEMORY_SIZE bytes. 19 ** 20 ** This version of the memory allocation subsystem is used if 21 ** and only if SQLITE_MEMORY_SIZE is defined. 22 ** 23 ** $Id: mem3.c,v 1.13 2008/06/13 18:24:27 drh Exp $ 24 */ 25 #include "sqliteInt.h" 26 27 /* 28 ** This version of the memory allocator is used only when 29 ** SQLITE_MEMORY_SIZE is defined. 30 */ 31 #ifdef SQLITE_MEMORY_SIZE 32 33 /* 34 ** Maximum size (in Mem3Blocks) of a "small" chunk. 35 */ 36 #define MX_SMALL 10 37 38 39 /* 40 ** Number of freelist hash slots 41 */ 42 #define N_HASH 61 43 44 /* 45 ** A memory allocation (also called a "chunk") consists of two or 46 ** more blocks where each block is 8 bytes. The first 8 bytes are 47 ** a header that is not returned to the user. 48 ** 49 ** A chunk is two or more blocks that is either checked out or 50 ** free. The first block has format u.hdr. u.hdr.size4x is 4 times the 51 ** size of the allocation in blocks if the allocation is free. 52 ** The u.hdr.size4x&1 bit is true if the chunk is checked out and 53 ** false if the chunk is on the freelist. The u.hdr.size4x&2 bit 54 ** is true if the previous chunk is checked out and false if the 55 ** previous chunk is free. The u.hdr.prevSize field is the size of 56 ** the previous chunk in blocks if the previous chunk is on the 57 ** freelist. If the previous chunk is checked out, then 58 ** u.hdr.prevSize can be part of the data for that chunk and should 59 ** not be read or written. 60 ** 61 ** We often identify a chunk by its index in mem.aPool[]. When 62 ** this is done, the chunk index refers to the second block of 63 ** the chunk. In this way, the first chunk has an index of 1. 64 ** A chunk index of 0 means "no such chunk" and is the equivalent 65 ** of a NULL pointer. 66 ** 67 ** The second block of free chunks is of the form u.list. The 68 ** two fields form a double-linked list of chunks of related sizes. 69 ** Pointers to the head of the list are stored in mem.aiSmall[] 70 ** for smaller chunks and mem.aiHash[] for larger chunks. 71 ** 72 ** The second block of a chunk is user data if the chunk is checked 73 ** out. If a chunk is checked out, the user data may extend into 74 ** the u.hdr.prevSize value of the following chunk. 75 */ 76 typedef struct Mem3Block Mem3Block; 77 struct Mem3Block { 78 union { 79 struct { 80 u32 prevSize; /* Size of previous chunk in Mem3Block elements */ 81 u32 size4x; /* 4x the size of current chunk in Mem3Block elements */ 82 } hdr; 83 struct { 84 u32 next; /* Index in mem.aPool[] of next free chunk */ 85 u32 prev; /* Index in mem.aPool[] of previous free chunk */ 86 } list; 87 } u; 88 }; 89 90 /* 91 ** All of the static variables used by this module are collected 92 ** into a single structure named "mem". This is to keep the 93 ** static variables organized and to reduce namespace pollution 94 ** when this module is combined with other in the amalgamation. 95 */ 96 static struct { 97 /* 98 ** True if we are evaluating an out-of-memory callback. 99 */ 100 int alarmBusy; 101 102 /* 103 ** Mutex to control access to the memory allocation subsystem. 104 */ 105 sqlite3_mutex *mutex; 106 107 /* 108 ** The minimum amount of free space that we have seen. 109 */ 110 u32 mnMaster; 111 112 /* 113 ** iMaster is the index of the master chunk. Most new allocations 114 ** occur off of this chunk. szMaster is the size (in Mem3Blocks) 115 ** of the current master. iMaster is 0 if there is not master chunk. 116 ** The master chunk is not in either the aiHash[] or aiSmall[]. 117 */ 118 u32 iMaster; 119 u32 szMaster; 120 121 /* 122 ** Array of lists of free blocks according to the block size 123 ** for smaller chunks, or a hash on the block size for larger 124 ** chunks. 125 */ 126 u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */ 127 u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */ 128 129 /* 130 ** Memory available for allocation 131 */ 132 Mem3Block aPool[SQLITE_MEMORY_SIZE/sizeof(Mem3Block)+2]; 133 } mem; 134 135 /* 136 ** Unlink the chunk at mem.aPool[i] from list it is currently 137 ** on. *pRoot is the list that i is a member of. 138 */ 139 static void memsys3UnlinkFromList(u32 i, u32 *pRoot){ 140 u32 next = mem.aPool[i].u.list.next; 141 u32 prev = mem.aPool[i].u.list.prev; 142 assert( sqlite3_mutex_held(mem.mutex) ); 143 if( prev==0 ){ 144 *pRoot = next; 145 }else{ 146 mem.aPool[prev].u.list.next = next; 147 } 148 if( next ){ 149 mem.aPool[next].u.list.prev = prev; 150 } 151 mem.aPool[i].u.list.next = 0; 152 mem.aPool[i].u.list.prev = 0; 153 } 154 155 /* 156 ** Unlink the chunk at index i from 157 ** whatever list is currently a member of. 158 */ 159 static void memsys3Unlink(u32 i){ 160 u32 size, hash; 161 assert( sqlite3_mutex_held(mem.mutex) ); 162 assert( (mem.aPool[i-1].u.hdr.size4x & 1)==0 ); 163 assert( i>=1 ); 164 size = mem.aPool[i-1].u.hdr.size4x/4; 165 assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); 166 assert( size>=2 ); 167 if( size <= MX_SMALL ){ 168 memsys3UnlinkFromList(i, &mem.aiSmall[size-2]); 169 }else{ 170 hash = size % N_HASH; 171 memsys3UnlinkFromList(i, &mem.aiHash[hash]); 172 } 173 } 174 175 /* 176 ** Link the chunk at mem.aPool[i] so that is on the list rooted 177 ** at *pRoot. 178 */ 179 static void memsys3LinkIntoList(u32 i, u32 *pRoot){ 180 assert( sqlite3_mutex_held(mem.mutex) ); 181 mem.aPool[i].u.list.next = *pRoot; 182 mem.aPool[i].u.list.prev = 0; 183 if( *pRoot ){ 184 mem.aPool[*pRoot].u.list.prev = i; 185 } 186 *pRoot = i; 187 } 188 189 /* 190 ** Link the chunk at index i into either the appropriate 191 ** small chunk list, or into the large chunk hash table. 192 */ 193 static void memsys3Link(u32 i){ 194 u32 size, hash; 195 assert( sqlite3_mutex_held(mem.mutex) ); 196 assert( i>=1 ); 197 assert( (mem.aPool[i-1].u.hdr.size4x & 1)==0 ); 198 size = mem.aPool[i-1].u.hdr.size4x/4; 199 assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); 200 assert( size>=2 ); 201 if( size <= MX_SMALL ){ 202 memsys3LinkIntoList(i, &mem.aiSmall[size-2]); 203 }else{ 204 hash = size % N_HASH; 205 memsys3LinkIntoList(i, &mem.aiHash[hash]); 206 } 207 } 208 209 /* 210 ** Enter the mutex mem.mutex. Allocate it if it is not already allocated. 211 ** 212 ** Also: Initialize the memory allocation subsystem the first time 213 ** this routine is called. 214 */ 215 static void memsys3Enter(void){ 216 if( mem.mutex==0 ){ 217 mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); 218 mem.aPool[0].u.hdr.size4x = SQLITE_MEMORY_SIZE/2 + 2; 219 mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8; 220 mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.size4x = 1; 221 mem.iMaster = 1; 222 mem.szMaster = SQLITE_MEMORY_SIZE/8; 223 mem.mnMaster = mem.szMaster; 224 } 225 sqlite3_mutex_enter(mem.mutex); 226 } 227 228 /* 229 ** Return the amount of memory currently checked out. 230 */ 231 sqlite3_int64 sqlite3_memory_used(void){ 232 sqlite3_int64 n; 233 memsys3Enter(); 234 n = SQLITE_MEMORY_SIZE - mem.szMaster*8; 235 sqlite3_mutex_leave(mem.mutex); 236 return n; 237 } 238 239 /* 240 ** Return the maximum amount of memory that has ever been 241 ** checked out since either the beginning of this process 242 ** or since the most recent reset. 243 */ 244 sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ 245 sqlite3_int64 n; 246 memsys3Enter(); 247 n = SQLITE_MEMORY_SIZE - mem.mnMaster*8; 248 if( resetFlag ){ 249 mem.mnMaster = mem.szMaster; 250 } 251 sqlite3_mutex_leave(mem.mutex); 252 return n; 253 } 254 255 /* 256 ** Change the alarm callback. 257 ** 258 ** This is a no-op for the static memory allocator. The purpose 259 ** of the memory alarm is to support sqlite3_soft_heap_limit(). 260 ** But with this memory allocator, the soft_heap_limit is really 261 ** a hard limit that is fixed at SQLITE_MEMORY_SIZE. 262 */ 263 int sqlite3_memory_alarm( 264 void(*xCallback)(void *pArg, sqlite3_int64 used,int N), 265 void *pArg, 266 sqlite3_int64 iThreshold 267 ){ 268 return SQLITE_OK; 269 } 270 271 /* 272 ** Called when we are unable to satisfy an allocation of nBytes. 273 */ 274 static void memsys3OutOfMemory(int nByte){ 275 if( !mem.alarmBusy ){ 276 mem.alarmBusy = 1; 277 assert( sqlite3_mutex_held(mem.mutex) ); 278 sqlite3_mutex_leave(mem.mutex); 279 sqlite3_release_memory(nByte); 280 sqlite3_mutex_enter(mem.mutex); 281 mem.alarmBusy = 0; 282 } 283 } 284 285 /* 286 ** Return the size of an outstanding allocation, in bytes. The 287 ** size returned omits the 8-byte header overhead. This only 288 ** works for chunks that are currently checked out. 289 */ 290 int sqlite3MallocSize(void *p){ 291 int iSize = 0; 292 if( p ){ 293 Mem3Block *pBlock = (Mem3Block*)p; 294 assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); 295 iSize = (pBlock[-1].u.hdr.size4x&~3)*2 - 4; 296 } 297 return iSize; 298 } 299 300 /* 301 ** Initialize the memmory allocation subsystem. 302 */ 303 int sqlite3MallocInit(void){ 304 return SQLITE_OK; 305 } 306 307 /* 308 ** Chunk i is a free chunk that has been unlinked. Adjust its 309 ** size parameters for check-out and return a pointer to the 310 ** user portion of the chunk. 311 */ 312 static void *memsys3Checkout(u32 i, int nBlock){ 313 u32 x; 314 assert( sqlite3_mutex_held(mem.mutex) ); 315 assert( i>=1 ); 316 assert( mem.aPool[i-1].u.hdr.size4x/4==nBlock ); 317 assert( mem.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); 318 x = mem.aPool[i-1].u.hdr.size4x; 319 mem.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2); 320 mem.aPool[i+nBlock-1].u.hdr.prevSize = nBlock; 321 mem.aPool[i+nBlock-1].u.hdr.size4x |= 2; 322 return &mem.aPool[i]; 323 } 324 325 /* 326 ** Carve a piece off of the end of the mem.iMaster free chunk. 327 ** Return a pointer to the new allocation. Or, if the master chunk 328 ** is not large enough, return 0. 329 */ 330 static void *memsys3FromMaster(int nBlock){ 331 assert( sqlite3_mutex_held(mem.mutex) ); 332 assert( mem.szMaster>=nBlock ); 333 if( nBlock>=mem.szMaster-1 ){ 334 /* Use the entire master */ 335 void *p = memsys3Checkout(mem.iMaster, mem.szMaster); 336 mem.iMaster = 0; 337 mem.szMaster = 0; 338 mem.mnMaster = 0; 339 return p; 340 }else{ 341 /* Split the master block. Return the tail. */ 342 u32 newi, x; 343 newi = mem.iMaster + mem.szMaster - nBlock; 344 assert( newi > mem.iMaster+1 ); 345 mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = nBlock; 346 mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x |= 2; 347 mem.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; 348 mem.szMaster -= nBlock; 349 mem.aPool[newi-1].u.hdr.prevSize = mem.szMaster; 350 x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; 351 mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; 352 if( mem.szMaster < mem.mnMaster ){ 353 mem.mnMaster = mem.szMaster; 354 } 355 return (void*)&mem.aPool[newi]; 356 } 357 } 358 359 /* 360 ** *pRoot is the head of a list of free chunks of the same size 361 ** or same size hash. In other words, *pRoot is an entry in either 362 ** mem.aiSmall[] or mem.aiHash[]. 363 ** 364 ** This routine examines all entries on the given list and tries 365 ** to coalesce each entries with adjacent free chunks. 366 ** 367 ** If it sees a chunk that is larger than mem.iMaster, it replaces 368 ** the current mem.iMaster with the new larger chunk. In order for 369 ** this mem.iMaster replacement to work, the master chunk must be 370 ** linked into the hash tables. That is not the normal state of 371 ** affairs, of course. The calling routine must link the master 372 ** chunk before invoking this routine, then must unlink the (possibly 373 ** changed) master chunk once this routine has finished. 374 */ 375 static void memsys3Merge(u32 *pRoot){ 376 u32 iNext, prev, size, i, x; 377 378 assert( sqlite3_mutex_held(mem.mutex) ); 379 for(i=*pRoot; i>0; i=iNext){ 380 iNext = mem.aPool[i].u.list.next; 381 size = mem.aPool[i-1].u.hdr.size4x; 382 assert( (size&1)==0 ); 383 if( (size&2)==0 ){ 384 memsys3UnlinkFromList(i, pRoot); 385 assert( i > mem.aPool[i-1].u.hdr.prevSize ); 386 prev = i - mem.aPool[i-1].u.hdr.prevSize; 387 if( prev==iNext ){ 388 iNext = mem.aPool[prev].u.list.next; 389 } 390 memsys3Unlink(prev); 391 size = i + size/4 - prev; 392 x = mem.aPool[prev-1].u.hdr.size4x & 2; 393 mem.aPool[prev-1].u.hdr.size4x = size*4 | x; 394 mem.aPool[prev+size-1].u.hdr.prevSize = size; 395 memsys3Link(prev); 396 i = prev; 397 }else{ 398 size /= 4; 399 } 400 if( size>mem.szMaster ){ 401 mem.iMaster = i; 402 mem.szMaster = size; 403 } 404 } 405 } 406 407 /* 408 ** Return a block of memory of at least nBytes in size. 409 ** Return NULL if unable. 410 */ 411 static void *memsys3Malloc(int nByte){ 412 u32 i; 413 int nBlock; 414 int toFree; 415 416 assert( sqlite3_mutex_held(mem.mutex) ); 417 assert( sizeof(Mem3Block)==8 ); 418 if( nByte<=12 ){ 419 nBlock = 2; 420 }else{ 421 nBlock = (nByte + 11)/8; 422 } 423 assert( nBlock >= 2 ); 424 425 /* STEP 1: 426 ** Look for an entry of the correct size in either the small 427 ** chunk table or in the large chunk hash table. This is 428 ** successful most of the time (about 9 times out of 10). 429 */ 430 if( nBlock <= MX_SMALL ){ 431 i = mem.aiSmall[nBlock-2]; 432 if( i>0 ){ 433 memsys3UnlinkFromList(i, &mem.aiSmall[nBlock-2]); 434 return memsys3Checkout(i, nBlock); 435 } 436 }else{ 437 int hash = nBlock % N_HASH; 438 for(i=mem.aiHash[hash]; i>0; i=mem.aPool[i].u.list.next){ 439 if( mem.aPool[i-1].u.hdr.size4x/4==nBlock ){ 440 memsys3UnlinkFromList(i, &mem.aiHash[hash]); 441 return memsys3Checkout(i, nBlock); 442 } 443 } 444 } 445 446 /* STEP 2: 447 ** Try to satisfy the allocation by carving a piece off of the end 448 ** of the master chunk. This step usually works if step 1 fails. 449 */ 450 if( mem.szMaster>=nBlock ){ 451 return memsys3FromMaster(nBlock); 452 } 453 454 455 /* STEP 3: 456 ** Loop through the entire memory pool. Coalesce adjacent free 457 ** chunks. Recompute the master chunk as the largest free chunk. 458 ** Then try again to satisfy the allocation by carving a piece off 459 ** of the end of the master chunk. This step happens very 460 ** rarely (we hope!) 461 */ 462 for(toFree=nBlock*16; toFree<SQLITE_MEMORY_SIZE*2; toFree *= 2){ 463 memsys3OutOfMemory(toFree); 464 if( mem.iMaster ){ 465 memsys3Link(mem.iMaster); 466 mem.iMaster = 0; 467 mem.szMaster = 0; 468 } 469 for(i=0; i<N_HASH; i++){ 470 memsys3Merge(&mem.aiHash[i]); 471 } 472 for(i=0; i<MX_SMALL-1; i++){ 473 memsys3Merge(&mem.aiSmall[i]); 474 } 475 if( mem.szMaster ){ 476 memsys3Unlink(mem.iMaster); 477 if( mem.szMaster>=nBlock ){ 478 return memsys3FromMaster(nBlock); 479 } 480 } 481 } 482 483 /* If none of the above worked, then we fail. */ 484 return 0; 485 } 486 487 /* 488 ** Free an outstanding memory allocation. 489 */ 490 void memsys3Free(void *pOld){ 491 Mem3Block *p = (Mem3Block*)pOld; 492 int i; 493 u32 size, x; 494 assert( sqlite3_mutex_held(mem.mutex) ); 495 assert( p>mem.aPool && p<&mem.aPool[SQLITE_MEMORY_SIZE/8] ); 496 i = p - mem.aPool; 497 assert( (mem.aPool[i-1].u.hdr.size4x&1)==1 ); 498 size = mem.aPool[i-1].u.hdr.size4x/4; 499 assert( i+size<=SQLITE_MEMORY_SIZE/8+1 ); 500 mem.aPool[i-1].u.hdr.size4x &= ~1; 501 mem.aPool[i+size-1].u.hdr.prevSize = size; 502 mem.aPool[i+size-1].u.hdr.size4x &= ~2; 503 memsys3Link(i); 504 505 /* Try to expand the master using the newly freed chunk */ 506 if( mem.iMaster ){ 507 while( (mem.aPool[mem.iMaster-1].u.hdr.size4x&2)==0 ){ 508 size = mem.aPool[mem.iMaster-1].u.hdr.prevSize; 509 mem.iMaster -= size; 510 mem.szMaster += size; 511 memsys3Unlink(mem.iMaster); 512 x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; 513 mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; 514 mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; 515 } 516 x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; 517 while( (mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x&1)==0 ){ 518 memsys3Unlink(mem.iMaster+mem.szMaster); 519 mem.szMaster += mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x/4; 520 mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; 521 mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; 522 } 523 } 524 } 525 526 /* 527 ** Allocate nBytes of memory 528 */ 529 void *sqlite3_malloc(int nBytes){ 530 sqlite3_int64 *p = 0; 531 if( nBytes>0 ){ 532 memsys3Enter(); 533 p = memsys3Malloc(nBytes); 534 sqlite3_mutex_leave(mem.mutex); 535 } 536 return (void*)p; 537 } 538 539 /* 540 ** Free memory. 541 */ 542 void sqlite3_free(void *pPrior){ 543 if( pPrior==0 ){ 544 return; 545 } 546 assert( mem.mutex!=0 ); 547 sqlite3_mutex_enter(mem.mutex); 548 memsys3Free(pPrior); 549 sqlite3_mutex_leave(mem.mutex); 550 } 551 552 /* 553 ** Change the size of an existing memory allocation 554 */ 555 void *sqlite3_realloc(void *pPrior, int nBytes){ 556 int nOld; 557 void *p; 558 if( pPrior==0 ){ 559 return sqlite3_malloc(nBytes); 560 } 561 if( nBytes<=0 ){ 562 sqlite3_free(pPrior); 563 return 0; 564 } 565 assert( mem.mutex!=0 ); 566 nOld = sqlite3MallocSize(pPrior); 567 if( nBytes<=nOld && nBytes>=nOld-128 ){ 568 return pPrior; 569 } 570 sqlite3_mutex_enter(mem.mutex); 571 p = memsys3Malloc(nBytes); 572 if( p ){ 573 if( nOld<nBytes ){ 574 memcpy(p, pPrior, nOld); 575 }else{ 576 memcpy(p, pPrior, nBytes); 577 } 578 memsys3Free(pPrior); 579 } 580 sqlite3_mutex_leave(mem.mutex); 581 return p; 582 } 583 584 /* 585 ** Open the file indicated and write a log of all unfreed memory 586 ** allocations into that log. 587 */ 588 void sqlite3MemdebugDump(const char *zFilename){ 589 #ifdef SQLITE_DEBUG 590 FILE *out; 591 int i, j; 592 u32 size; 593 if( zFilename==0 || zFilename[0]==0 ){ 594 out = stdout; 595 }else{ 596 out = fopen(zFilename, "w"); 597 if( out==0 ){ 598 fprintf(stderr, "** Unable to output memory debug output log: %s **\n", 599 zFilename); 600 return; 601 } 602 } 603 memsys3Enter(); 604 fprintf(out, "CHUNKS:\n"); 605 for(i=1; i<=SQLITE_MEMORY_SIZE/8; i+=size/4){ 606 size = mem.aPool[i-1].u.hdr.size4x; 607 if( size/4<=1 ){ 608 fprintf(out, "%p size error\n", &mem.aPool[i]); 609 assert( 0 ); 610 break; 611 } 612 if( (size&1)==0 && mem.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){ 613 fprintf(out, "%p tail size does not match\n", &mem.aPool[i]); 614 assert( 0 ); 615 break; 616 } 617 if( ((mem.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){ 618 fprintf(out, "%p tail checkout bit is incorrect\n", &mem.aPool[i]); 619 assert( 0 ); 620 break; 621 } 622 if( size&1 ){ 623 fprintf(out, "%p %6d bytes checked out\n", &mem.aPool[i], (size/4)*8-8); 624 }else{ 625 fprintf(out, "%p %6d bytes free%s\n", &mem.aPool[i], (size/4)*8-8, 626 i==mem.iMaster ? " **master**" : ""); 627 } 628 } 629 for(i=0; i<MX_SMALL-1; i++){ 630 if( mem.aiSmall[i]==0 ) continue; 631 fprintf(out, "small(%2d):", i); 632 for(j = mem.aiSmall[i]; j>0; j=mem.aPool[j].u.list.next){ 633 fprintf(out, " %p(%d)", &mem.aPool[j], 634 (mem.aPool[j-1].u.hdr.size4x/4)*8-8); 635 } 636 fprintf(out, "\n"); 637 } 638 for(i=0; i<N_HASH; i++){ 639 if( mem.aiHash[i]==0 ) continue; 640 fprintf(out, "hash(%2d):", i); 641 for(j = mem.aiHash[i]; j>0; j=mem.aPool[j].u.list.next){ 642 fprintf(out, " %p(%d)", &mem.aPool[j], 643 (mem.aPool[j-1].u.hdr.size4x/4)*8-8); 644 } 645 fprintf(out, "\n"); 646 } 647 fprintf(out, "master=%d\n", mem.iMaster); 648 fprintf(out, "nowUsed=%d\n", SQLITE_MEMORY_SIZE - mem.szMaster*8); 649 fprintf(out, "mxUsed=%d\n", SQLITE_MEMORY_SIZE - mem.mnMaster*8); 650 sqlite3_mutex_leave(mem.mutex); 651 if( out==stdout ){ 652 fflush(stdout); 653 }else{ 654 fclose(out); 655 } 656 #endif 657 } 658 659 660 #endif /* !SQLITE_MEMORY_SIZE */ 661