15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2007 October 14
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains the C functions that implement a memory
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** allocation subsystem for use by SQLite.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This version of the memory allocation subsystem omits all
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** use of malloc(). The SQLite user supplies a block of memory
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** before calling sqlite3_initialize() from which allocations
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are made and returned by the xMalloc() and xRealloc()
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** implementations. Once sqlite3_initialize() has been called,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the amount of memory available to SQLite is fixed and cannot
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be changed.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This version of the memory allocation subsystem is included
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This version of the memory allocator is only built into the library
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** mean that the library will use a memory-pool by default, just that
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it is available. The mempool allocator is activated by calling
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_config().
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_ENABLE_MEMSYS3
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Maximum size (in Mem3Blocks) of a "small" chunk.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MX_SMALL 10
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Number of freelist hash slots
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define N_HASH  61
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A memory allocation (also called a "chunk") consists of two or
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** more blocks where each block is 8 bytes.  The first 8 bytes are
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a header that is not returned to the user.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A chunk is two or more blocks that is either checked out or
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** free.  The first block has format u.hdr.  u.hdr.size4x is 4 times the
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** size of the allocation in blocks if the allocation is free.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The u.hdr.size4x&1 bit is true if the chunk is checked out and
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** false if the chunk is on the freelist.  The u.hdr.size4x&2 bit
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is true if the previous chunk is checked out and false if the
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** previous chunk is free.  The u.hdr.prevSize field is the size of
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the previous chunk in blocks if the previous chunk is on the
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** freelist. If the previous chunk is checked out, then
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** u.hdr.prevSize can be part of the data for that chunk and should
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** not be read or written.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** We often identify a chunk by its index in mem3.aPool[].  When
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this is done, the chunk index refers to the second block of
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the chunk.  In this way, the first chunk has an index of 1.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A chunk index of 0 means "no such chunk" and is the equivalent
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of a NULL pointer.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The second block of free chunks is of the form u.list.  The
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** two fields form a double-linked list of chunks of related sizes.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Pointers to the head of the list are stored in mem3.aiSmall[]
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for smaller chunks and mem3.aiHash[] for larger chunks.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The second block of a chunk is user data if the chunk is checked
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** out.  If a chunk is checked out, the user data may extend into
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the u.hdr.prevSize value of the following chunk.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct Mem3Block Mem3Block;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Mem3Block {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u32 prevSize;   /* Size of previous chunk in Mem3Block elements */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u32 size4x;     /* 4x the size of current chunk in Mem3Block elements */
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } hdr;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u32 next;       /* Index in mem3.aPool[] of next free chunk */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u32 prev;       /* Index in mem3.aPool[] of previous free chunk */
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } list;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All of the static variables used by this module are collected
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** into a single structure named "mem3".  This is to keep the
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** static variables organized and to reduce namespace pollution
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** when this module is combined with other in the amalgamation.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SQLITE_WSD struct Mem3Global {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Memory available for allocation. nPool is the size of the array
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** (in Mem3Blocks) pointed to by aPool less 2.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 nPool;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mem3Block *aPool;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** True if we are evaluating an out-of-memory callback.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int alarmBusy;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Mutex to control access to the memory allocation subsystem.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex *mutex;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** The minimum amount of free space that we have seen.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 mnMaster;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** iMaster is the index of the master chunk.  Most new allocations
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** occur off of this chunk.  szMaster is the size (in Mem3Blocks)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** of the current master.  iMaster is 0 if there is not master chunk.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** The master chunk is not in either the aiHash[] or aiSmall[].
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 iMaster;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 szMaster;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Array of lists of free blocks according to the block size
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** for smaller chunks, or a hash on the block size for larger
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** chunks.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 aiSmall[MX_SMALL-1];   /* For sizes 2 through MX_SMALL, inclusive */
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 aiHash[N_HASH];        /* For sizes MX_SMALL+1 and larger */
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} mem3 = { 97535575 };
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define mem3 GLOBAL(struct Mem3Global, mem3)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unlink the chunk at mem3.aPool[i] from list it is currently
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on.  *pRoot is the list that i is a member of.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 next = mem3.aPool[i].u.list.next;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 prev = mem3.aPool[i].u.list.prev;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( prev==0 ){
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pRoot = next;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[prev].u.list.next = next;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( next ){
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[next].u.list.prev = prev;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i].u.list.next = 0;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i].u.list.prev = 0;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unlink the chunk at index i from
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** whatever list is currently a member of.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3Unlink(u32 i){
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 size, hash;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( i>=1 );
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size = mem3.aPool[i-1].u.hdr.size4x/4;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( size>=2 );
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( size <= MX_SMALL ){
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash = size % N_HASH;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Link the chunk at mem3.aPool[i] so that is on the list rooted
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** at *pRoot.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3LinkIntoList(u32 i, u32 *pRoot){
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i].u.list.next = *pRoot;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i].u.list.prev = 0;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( *pRoot ){
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[*pRoot].u.list.prev = i;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pRoot = i;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Link the chunk at index i into either the appropriate
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** small chunk list, or into the large chunk hash table.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3Link(u32 i){
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 size, hash;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( i>=1 );
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size = mem3.aPool[i-1].u.hdr.size4x/4;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( size>=2 );
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( size <= MX_SMALL ){
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash = size % N_HASH;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memsys3LinkIntoList(i, &mem3.aiHash[hash]);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will already be held (obtained by code in malloc.c) if
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3GlobalConfig.bMemStat is true.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3Enter(void){
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(mem3.mutex);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3Leave(void){
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(mem3.mutex);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Called when we are unable to satisfy an allocation of nBytes.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3OutOfMemory(int nByte){
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !mem3.alarmBusy ){
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.alarmBusy = 1;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( sqlite3_mutex_held(mem3.mutex) );
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_mutex_leave(mem3.mutex);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_release_memory(nByte);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_mutex_enter(mem3.mutex);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.alarmBusy = 0;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Chunk i is a free chunk that has been unlinked.  Adjust its
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** size parameters for check-out and return a pointer to the
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** user portion of the chunk.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *memsys3Checkout(u32 i, u32 nBlock){
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 x;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( i>=1 );
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  x = mem3.aPool[i-1].u.hdr.size4x;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &mem3.aPool[i];
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Carve a piece off of the end of the mem3.iMaster free chunk.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a pointer to the new allocation.  Or, if the master chunk
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is not large enough, return 0.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *memsys3FromMaster(u32 nBlock){
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( mem3.szMaster>=nBlock );
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nBlock>=mem3.szMaster-1 ){
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Use the entire master */
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.iMaster = 0;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.szMaster = 0;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.mnMaster = 0;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return p;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Split the master block.  Return the tail. */
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u32 newi, x;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    newi = mem3.iMaster + mem3.szMaster - nBlock;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( newi > mem3.iMaster+1 );
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.szMaster -= nBlock;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( mem3.szMaster < mem3.mnMaster ){
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.mnMaster = mem3.szMaster;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (void*)&mem3.aPool[newi];
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** *pRoot is the head of a list of free chunks of the same size
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or same size hash.  In other words, *pRoot is an entry in either
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** mem3.aiSmall[] or mem3.aiHash[].
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine examines all entries on the given list and tries
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to coalesce each entries with adjacent free chunks.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If it sees a chunk that is larger than mem3.iMaster, it replaces
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the current mem3.iMaster with the new larger chunk.  In order for
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this mem3.iMaster replacement to work, the master chunk must be
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** linked into the hash tables.  That is not the normal state of
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** affairs, of course.  The calling routine must link the master
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** chunk before invoking this routine, then must unlink the (possibly
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** changed) master chunk once this routine has finished.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3Merge(u32 *pRoot){
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 iNext, prev, size, i, x;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=*pRoot; i>0; i=iNext){
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iNext = mem3.aPool[i].u.list.next;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = mem3.aPool[i-1].u.hdr.size4x;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( (size&1)==0 );
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (size&2)==0 ){
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3UnlinkFromList(i, pRoot);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( i > mem3.aPool[i-1].u.hdr.prevSize );
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prev = i - mem3.aPool[i-1].u.hdr.prevSize;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( prev==iNext ){
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iNext = mem3.aPool[prev].u.list.next;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Unlink(prev);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size = i + size/4 - prev;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x = mem3.aPool[prev-1].u.hdr.size4x & 2;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.aPool[prev+size-1].u.hdr.prevSize = size;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Link(prev);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = prev;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size /= 4;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( size>mem3.szMaster ){
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.iMaster = i;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.szMaster = size;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a block of memory of at least nBytes in size.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return NULL if unable.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function assumes that the necessary mutexes, if any, are
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** already held by the caller. Hence "Unsafe".
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *memsys3MallocUnsafe(int nByte){
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 i;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 nBlock;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 toFree;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sizeof(Mem3Block)==8 );
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nByte<=12 ){
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nBlock = 2;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nBlock = (nByte + 11)/8;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( nBlock>=2 );
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* STEP 1:
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Look for an entry of the correct size in either the small
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** chunk table or in the large chunk hash table.  This is
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** successful most of the time (about 9 times out of 10).
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nBlock <= MX_SMALL ){
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = mem3.aiSmall[nBlock-2];
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( i>0 ){
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return memsys3Checkout(i, nBlock);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int hash = nBlock % N_HASH;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return memsys3Checkout(i, nBlock);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* STEP 2:
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Try to satisfy the allocation by carving a piece off of the end
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** of the master chunk.  This step usually works if step 1 fails.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( mem3.szMaster>=nBlock ){
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return memsys3FromMaster(nBlock);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* STEP 3:
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Loop through the entire memory pool.  Coalesce adjacent free
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** chunks.  Recompute the master chunk as the largest free chunk.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Then try again to satisfy the allocation by carving a piece off
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** of the end of the master chunk.  This step happens very
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** rarely (we hope!)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memsys3OutOfMemory(toFree);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( mem3.iMaster ){
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Link(mem3.iMaster);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.iMaster = 0;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.szMaster = 0;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<N_HASH; i++){
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Merge(&mem3.aiHash[i]);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<MX_SMALL-1; i++){
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Merge(&mem3.aiSmall[i]);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( mem3.szMaster ){
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Unlink(mem3.iMaster);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( mem3.szMaster>=nBlock ){
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return memsys3FromMaster(nBlock);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If none of the above worked, then we fail. */
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Free an outstanding memory allocation.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function assumes that the necessary mutexes, if any, are
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** already held by the caller. Hence "Unsafe".
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void memsys3FreeUnsafe(void *pOld){
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mem3Block *p = (Mem3Block*)pOld;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 size, x;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(mem3.mutex) );
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = p - mem3.aPool;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size = mem3.aPool[i-1].u.hdr.size4x/4;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( i+size<=mem3.nPool+1 );
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i-1].u.hdr.size4x &= ~1;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i+size-1].u.hdr.prevSize = size;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Link(i);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Try to expand the master using the newly freed chunk */
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( mem3.iMaster ){
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.iMaster -= size;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.szMaster += size;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Unlink(mem3.iMaster);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memsys3Unlink(mem3.iMaster+mem3.szMaster);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the size of an outstanding allocation, in bytes.  The
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** size returned omits the 8-byte header overhead.  This only
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** works for chunks that are currently checked out.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int memsys3Size(void *p){
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mem3Block *pBlock;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ) return 0;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pBlock = (Mem3Block*)p;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Round up a request size to the next valid allocation size.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int memsys3Roundup(int n){
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( n<=12 ){
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 12;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ((n+11)&~7) - 4;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Allocate nBytes of memory.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *memsys3Malloc(int nBytes){
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 *p;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( nBytes>0 );          /* malloc.c filters out 0 byte requests */
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Enter();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = memsys3MallocUnsafe(nBytes);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Leave();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (void*)p;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Free memory.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void memsys3Free(void *pPrior){
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pPrior );
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Enter();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3FreeUnsafe(pPrior);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Leave();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Change the size of an existing memory allocation
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *memsys3Realloc(void *pPrior, int nBytes){
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nOld;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *p;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pPrior==0 ){
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sqlite3_malloc(nBytes);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nBytes<=0 ){
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pPrior);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nOld = memsys3Size(pPrior);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nBytes<=nOld && nBytes>=nOld-128 ){
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pPrior;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Enter();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = memsys3MallocUnsafe(nBytes);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p ){
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( nOld<nBytes ){
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(p, pPrior, nOld);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(p, pPrior, nBytes);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memsys3FreeUnsafe(pPrior);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Leave();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initialize this module.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int memsys3Init(void *NotUsed){
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !sqlite3GlobalConfig.pHeap ){
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Store a pointer to the memory block in global structure mem3. */
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sizeof(Mem3Block)==8 );
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Initialize the master block. */
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.szMaster = mem3.nPool;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.mnMaster = mem3.szMaster;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.iMaster = 1;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Deinitialize this module.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void memsys3Shutdown(void *NotUsed){
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem3.mutex = 0;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the file indicated and write a log of all unfreed memory
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** allocations into that log.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void sqlite3Memsys3Dump(const char *zFilename){
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE *out;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 i, j;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 size;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zFilename==0 || zFilename[0]==0 ){
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = stdout;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = fopen(zFilename, "w");
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( out==0 ){
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      zFilename);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memsys3Enter();
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(out, "CHUNKS:\n");
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=1; i<=mem3.nPool; i+=size/4){
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = mem3.aPool[i-1].u.hdr.size4x;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( size/4<=1 ){
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, "%p size error\n", &mem3.aPool[i]);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( 0 );
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( 0 );
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( 0 );
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( size&1 ){
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  i==mem3.iMaster ? " **master**" : "");
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<MX_SMALL-1; i++){
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( mem3.aiSmall[i]==0 ) continue;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(out, "small(%2d):", i);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, " %p(%d)", &mem3.aPool[j],
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(out, "\n");
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<N_HASH; i++){
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( mem3.aiHash[i]==0 ) continue;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(out, "hash(%2d):", i);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(out, " %p(%d)", &mem3.aPool[j],
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(out, "\n");
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(out, "master=%d\n", mem3.iMaster);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(mem3.mutex);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( out==stdout ){
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fflush(stdout);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fclose(out);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(zFilename);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine is the only routine in this file with external
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** linkage.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the low-level memory allocation function pointers in
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3GlobalConfig.m with pointers to the routines in this file. The
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** arguments specify the block of memory to manage.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine is only called by sqlite3_config(), and therefore
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is not required to be threadsafe (it is not).
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const sqlite3_mem_methods mempoolMethods = {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Malloc,
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Free,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Realloc,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Size,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Roundup,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Init,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     memsys3Shutdown,
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &mempoolMethods;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_ENABLE_MEMSYS3 */
688