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