os/persistentdata/persistentstorage/sql/SQLite/mem5.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
** 2007 October 14
sl@0
     3
**
sl@0
     4
** The author disclaims copyright to this source code.  In place of
sl@0
     5
** a legal notice, here is a blessing:
sl@0
     6
**
sl@0
     7
**    May you do good and not evil.
sl@0
     8
**    May you find forgiveness for yourself and forgive others.
sl@0
     9
**    May you share freely, never taking more than you give.
sl@0
    10
**
sl@0
    11
*************************************************************************
sl@0
    12
** This file contains the C functions that implement a memory
sl@0
    13
** allocation subsystem for use by SQLite. 
sl@0
    14
**
sl@0
    15
** This version of the memory allocation subsystem omits all
sl@0
    16
** use of malloc(). The SQLite user supplies a block of memory
sl@0
    17
** before calling sqlite3_initialize() from which allocations
sl@0
    18
** are made and returned by the xMalloc() and xRealloc() 
sl@0
    19
** implementations. Once sqlite3_initialize() has been called,
sl@0
    20
** the amount of memory available to SQLite is fixed and cannot
sl@0
    21
** be changed.
sl@0
    22
**
sl@0
    23
** This version of the memory allocation subsystem is included
sl@0
    24
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
sl@0
    25
**
sl@0
    26
** $Id: mem5.c,v 1.11 2008/07/16 12:25:32 drh Exp $
sl@0
    27
*/
sl@0
    28
#include "sqliteInt.h"
sl@0
    29
sl@0
    30
/*
sl@0
    31
** This version of the memory allocator is used only when 
sl@0
    32
** SQLITE_POW2_MEMORY_SIZE is defined.
sl@0
    33
*/
sl@0
    34
#ifdef SQLITE_ENABLE_MEMSYS5
sl@0
    35
sl@0
    36
/*
sl@0
    37
** Log2 of the minimum size of an allocation.  For example, if
sl@0
    38
** 4 then all allocations will be rounded up to at least 16 bytes.
sl@0
    39
** If 5 then all allocations will be rounded up to at least 32 bytes.
sl@0
    40
*/
sl@0
    41
#ifndef SQLITE_POW2_LOGMIN
sl@0
    42
# define SQLITE_POW2_LOGMIN 6
sl@0
    43
#endif
sl@0
    44
sl@0
    45
/*
sl@0
    46
** Log2 of the maximum size of an allocation.
sl@0
    47
*/
sl@0
    48
#ifndef SQLITE_POW2_LOGMAX
sl@0
    49
# define SQLITE_POW2_LOGMAX 20
sl@0
    50
#endif
sl@0
    51
#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX)
sl@0
    52
sl@0
    53
/*
sl@0
    54
** Number of distinct allocation sizes.
sl@0
    55
*/
sl@0
    56
#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)
sl@0
    57
sl@0
    58
/*
sl@0
    59
** A minimum allocation is an instance of the following structure.
sl@0
    60
** Larger allocations are an array of these structures where the
sl@0
    61
** size of the array is a power of 2.
sl@0
    62
*/
sl@0
    63
typedef struct Mem5Link Mem5Link;
sl@0
    64
struct Mem5Link {
sl@0
    65
  int next;       /* Index of next free chunk */
sl@0
    66
  int prev;       /* Index of previous free chunk */
sl@0
    67
};
sl@0
    68
sl@0
    69
/*
sl@0
    70
** Maximum size of any allocation is ((1<<LOGMAX)*mem5.nAtom). Since
sl@0
    71
** mem5.nAtom is always at least 8, this is not really a practical
sl@0
    72
** limitation.
sl@0
    73
*/
sl@0
    74
#define LOGMAX 30
sl@0
    75
sl@0
    76
/*
sl@0
    77
** Masks used for mem5.aCtrl[] elements.
sl@0
    78
*/
sl@0
    79
#define CTRL_LOGSIZE  0x1f    /* Log2 Size of this block relative to POW2_MIN */
sl@0
    80
#define CTRL_FREE     0x20    /* True if not checked out */
sl@0
    81
sl@0
    82
/*
sl@0
    83
** All of the static variables used by this module are collected
sl@0
    84
** into a single structure named "mem5".  This is to keep the
sl@0
    85
** static variables organized and to reduce namespace pollution
sl@0
    86
** when this module is combined with other in the amalgamation.
sl@0
    87
*/
sl@0
    88
static struct {
sl@0
    89
  /*
sl@0
    90
  ** The alarm callback and its arguments.  The mem5.mutex lock will
sl@0
    91
  ** be held while the callback is running.  Recursive calls into
sl@0
    92
  ** the memory subsystem are allowed, but no new callbacks will be
sl@0
    93
  ** issued.  The alarmBusy variable is set to prevent recursive
sl@0
    94
  ** callbacks.
sl@0
    95
  */
sl@0
    96
  sqlite3_int64 alarmThreshold;
sl@0
    97
  void (*alarmCallback)(void*, sqlite3_int64,int);
sl@0
    98
  void *alarmArg;
sl@0
    99
  int alarmBusy;
sl@0
   100
  
sl@0
   101
  /*
sl@0
   102
  ** Mutex to control access to the memory allocation subsystem.
sl@0
   103
  */
sl@0
   104
  sqlite3_mutex *mutex;
sl@0
   105
sl@0
   106
  /*
sl@0
   107
  ** Performance statistics
sl@0
   108
  */
sl@0
   109
  u64 nAlloc;         /* Total number of calls to malloc */
sl@0
   110
  u64 totalAlloc;     /* Total of all malloc calls - includes internal frag */
sl@0
   111
  u64 totalExcess;    /* Total internal fragmentation */
sl@0
   112
  u32 currentOut;     /* Current checkout, including internal fragmentation */
sl@0
   113
  u32 currentCount;   /* Current number of distinct checkouts */
sl@0
   114
  u32 maxOut;         /* Maximum instantaneous currentOut */
sl@0
   115
  u32 maxCount;       /* Maximum instantaneous currentCount */
sl@0
   116
  u32 maxRequest;     /* Largest allocation (exclusive of internal frag) */
sl@0
   117
  
sl@0
   118
  /*
sl@0
   119
  ** Lists of free blocks of various sizes.
sl@0
   120
  */
sl@0
   121
  int aiFreelist[LOGMAX+1];
sl@0
   122
sl@0
   123
  /*
sl@0
   124
  ** Space for tracking which blocks are checked out and the size
sl@0
   125
  ** of each block.  One byte per block.
sl@0
   126
  */
sl@0
   127
  u8 *aCtrl;
sl@0
   128
sl@0
   129
  /*
sl@0
   130
  ** Memory available for allocation
sl@0
   131
  */
sl@0
   132
  int nAtom;       /* Smallest possible allocation in bytes */
sl@0
   133
  int nBlock;      /* Number of nAtom sized blocks in zPool */
sl@0
   134
  u8 *zPool;
sl@0
   135
} mem5;
sl@0
   136
sl@0
   137
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom]))
sl@0
   138
sl@0
   139
/*
sl@0
   140
** Unlink the chunk at mem5.aPool[i] from list it is currently
sl@0
   141
** on.  It should be found on mem5.aiFreelist[iLogsize].
sl@0
   142
*/
sl@0
   143
static void memsys5Unlink(int i, int iLogsize){
sl@0
   144
  int next, prev;
sl@0
   145
  assert( i>=0 && i<mem5.nBlock );
sl@0
   146
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
sl@0
   147
  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
sl@0
   148
sl@0
   149
  next = MEM5LINK(i)->next;
sl@0
   150
  prev = MEM5LINK(i)->prev;
sl@0
   151
  if( prev<0 ){
sl@0
   152
    mem5.aiFreelist[iLogsize] = next;
sl@0
   153
  }else{
sl@0
   154
    MEM5LINK(prev)->next = next;
sl@0
   155
  }
sl@0
   156
  if( next>=0 ){
sl@0
   157
    MEM5LINK(next)->prev = prev;
sl@0
   158
  }
sl@0
   159
}
sl@0
   160
sl@0
   161
/*
sl@0
   162
** Link the chunk at mem5.aPool[i] so that is on the iLogsize
sl@0
   163
** free list.
sl@0
   164
*/
sl@0
   165
static void memsys5Link(int i, int iLogsize){
sl@0
   166
  int x;
sl@0
   167
  assert( sqlite3_mutex_held(mem5.mutex) );
sl@0
   168
  assert( i>=0 && i<mem5.nBlock );
sl@0
   169
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
sl@0
   170
  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
sl@0
   171
sl@0
   172
  x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
sl@0
   173
  MEM5LINK(i)->prev = -1;
sl@0
   174
  if( x>=0 ){
sl@0
   175
    assert( x<mem5.nBlock );
sl@0
   176
    MEM5LINK(x)->prev = i;
sl@0
   177
  }
sl@0
   178
  mem5.aiFreelist[iLogsize] = i;
sl@0
   179
}
sl@0
   180
sl@0
   181
/*
sl@0
   182
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
sl@0
   183
** will already be held (obtained by code in malloc.c) if
sl@0
   184
** sqlite3Config.bMemStat is true.
sl@0
   185
*/
sl@0
   186
static void memsys5Enter(void){
sl@0
   187
  if( sqlite3Config.bMemstat==0 && mem5.mutex==0 ){
sl@0
   188
    mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
sl@0
   189
  }
sl@0
   190
  sqlite3_mutex_enter(mem5.mutex);
sl@0
   191
}
sl@0
   192
static void memsys5Leave(void){
sl@0
   193
  sqlite3_mutex_leave(mem5.mutex);
sl@0
   194
}
sl@0
   195
sl@0
   196
/*
sl@0
   197
** Return the size of an outstanding allocation, in bytes.  The
sl@0
   198
** size returned omits the 8-byte header overhead.  This only
sl@0
   199
** works for chunks that are currently checked out.
sl@0
   200
*/
sl@0
   201
static int memsys5Size(void *p){
sl@0
   202
  int iSize = 0;
sl@0
   203
  if( p ){
sl@0
   204
    int i = ((u8 *)p-mem5.zPool)/mem5.nAtom;
sl@0
   205
    assert( i>=0 && i<mem5.nBlock );
sl@0
   206
    iSize = mem5.nAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
sl@0
   207
  }
sl@0
   208
  return iSize;
sl@0
   209
}
sl@0
   210
sl@0
   211
/*
sl@0
   212
** Find the first entry on the freelist iLogsize.  Unlink that
sl@0
   213
** entry and return its index. 
sl@0
   214
*/
sl@0
   215
static int memsys5UnlinkFirst(int iLogsize){
sl@0
   216
  int i;
sl@0
   217
  int iFirst;
sl@0
   218
sl@0
   219
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
sl@0
   220
  i = iFirst = mem5.aiFreelist[iLogsize];
sl@0
   221
  assert( iFirst>=0 );
sl@0
   222
  while( i>0 ){
sl@0
   223
    if( i<iFirst ) iFirst = i;
sl@0
   224
    i = MEM5LINK(i)->next;
sl@0
   225
  }
sl@0
   226
  memsys5Unlink(iFirst, iLogsize);
sl@0
   227
  return iFirst;
sl@0
   228
}
sl@0
   229
sl@0
   230
/*
sl@0
   231
** Return a block of memory of at least nBytes in size.
sl@0
   232
** Return NULL if unable.
sl@0
   233
*/
sl@0
   234
static void *memsys5MallocUnsafe(int nByte){
sl@0
   235
  int i;           /* Index of a mem5.aPool[] slot */
sl@0
   236
  int iBin;        /* Index into mem5.aiFreelist[] */
sl@0
   237
  int iFullSz;     /* Size of allocation rounded up to power of 2 */
sl@0
   238
  int iLogsize;    /* Log2 of iFullSz/POW2_MIN */
sl@0
   239
sl@0
   240
  /* Keep track of the maximum allocation request.  Even unfulfilled
sl@0
   241
  ** requests are counted */
sl@0
   242
  if( nByte>mem5.maxRequest ){
sl@0
   243
    mem5.maxRequest = nByte;
sl@0
   244
  }
sl@0
   245
sl@0
   246
  /* Round nByte up to the next valid power of two */
sl@0
   247
  if( nByte>POW2_MAX ) return 0;
sl@0
   248
  for(iFullSz=mem5.nAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
sl@0
   249
sl@0
   250
  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
sl@0
   251
  ** block.  If not, then split a block of the next larger power of
sl@0
   252
  ** two in order to create a new free block of size iLogsize.
sl@0
   253
  */
sl@0
   254
  for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
sl@0
   255
  if( iBin>LOGMAX ) return 0;
sl@0
   256
  i = memsys5UnlinkFirst(iBin);
sl@0
   257
  while( iBin>iLogsize ){
sl@0
   258
    int newSize;
sl@0
   259
sl@0
   260
    iBin--;
sl@0
   261
    newSize = 1 << iBin;
sl@0
   262
    mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
sl@0
   263
    memsys5Link(i+newSize, iBin);
sl@0
   264
  }
sl@0
   265
  mem5.aCtrl[i] = iLogsize;
sl@0
   266
sl@0
   267
  /* Update allocator performance statistics. */
sl@0
   268
  mem5.nAlloc++;
sl@0
   269
  mem5.totalAlloc += iFullSz;
sl@0
   270
  mem5.totalExcess += iFullSz - nByte;
sl@0
   271
  mem5.currentCount++;
sl@0
   272
  mem5.currentOut += iFullSz;
sl@0
   273
  if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
sl@0
   274
  if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
sl@0
   275
sl@0
   276
  /* Return a pointer to the allocated memory. */
sl@0
   277
  return (void*)&mem5.zPool[i*mem5.nAtom];
sl@0
   278
}
sl@0
   279
sl@0
   280
/*
sl@0
   281
** Free an outstanding memory allocation.
sl@0
   282
*/
sl@0
   283
static void memsys5FreeUnsafe(void *pOld){
sl@0
   284
  u32 size, iLogsize;
sl@0
   285
  int iBlock;             
sl@0
   286
sl@0
   287
  /* Set iBlock to the index of the block pointed to by pOld in 
sl@0
   288
  ** the array of mem5.nAtom byte blocks pointed to by mem5.zPool.
sl@0
   289
  */
sl@0
   290
  iBlock = ((u8 *)pOld-mem5.zPool)/mem5.nAtom;
sl@0
   291
sl@0
   292
  /* Check that the pointer pOld points to a valid, non-free block. */
sl@0
   293
  assert( iBlock>=0 && iBlock<mem5.nBlock );
sl@0
   294
  assert( ((u8 *)pOld-mem5.zPool)%mem5.nAtom==0 );
sl@0
   295
  assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
sl@0
   296
sl@0
   297
  iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
sl@0
   298
  size = 1<<iLogsize;
sl@0
   299
  assert( iBlock+size-1<mem5.nBlock );
sl@0
   300
sl@0
   301
  mem5.aCtrl[iBlock] |= CTRL_FREE;
sl@0
   302
  mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
sl@0
   303
  assert( mem5.currentCount>0 );
sl@0
   304
  assert( mem5.currentOut>=0 );
sl@0
   305
  mem5.currentCount--;
sl@0
   306
  mem5.currentOut -= size*mem5.nAtom;
sl@0
   307
  assert( mem5.currentOut>0 || mem5.currentCount==0 );
sl@0
   308
  assert( mem5.currentCount>0 || mem5.currentOut==0 );
sl@0
   309
sl@0
   310
  mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
sl@0
   311
  while( iLogsize<LOGMAX ){
sl@0
   312
    int iBuddy;
sl@0
   313
    if( (iBlock>>iLogsize) & 1 ){
sl@0
   314
      iBuddy = iBlock - size;
sl@0
   315
    }else{
sl@0
   316
      iBuddy = iBlock + size;
sl@0
   317
    }
sl@0
   318
    assert( iBuddy>=0 );
sl@0
   319
    if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
sl@0
   320
    if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
sl@0
   321
    memsys5Unlink(iBuddy, iLogsize);
sl@0
   322
    iLogsize++;
sl@0
   323
    if( iBuddy<iBlock ){
sl@0
   324
      mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
sl@0
   325
      mem5.aCtrl[iBlock] = 0;
sl@0
   326
      iBlock = iBuddy;
sl@0
   327
    }else{
sl@0
   328
      mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
sl@0
   329
      mem5.aCtrl[iBuddy] = 0;
sl@0
   330
    }
sl@0
   331
    size *= 2;
sl@0
   332
  }
sl@0
   333
  memsys5Link(iBlock, iLogsize);
sl@0
   334
}
sl@0
   335
sl@0
   336
/*
sl@0
   337
** Allocate nBytes of memory
sl@0
   338
*/
sl@0
   339
static void *memsys5Malloc(int nBytes){
sl@0
   340
  sqlite3_int64 *p = 0;
sl@0
   341
  if( nBytes>0 ){
sl@0
   342
    memsys5Enter();
sl@0
   343
    p = memsys5MallocUnsafe(nBytes);
sl@0
   344
    memsys5Leave();
sl@0
   345
  }
sl@0
   346
  return (void*)p; 
sl@0
   347
}
sl@0
   348
sl@0
   349
/*
sl@0
   350
** Free memory.
sl@0
   351
*/
sl@0
   352
static void memsys5Free(void *pPrior){
sl@0
   353
  if( pPrior==0 ){
sl@0
   354
assert(0);
sl@0
   355
    return;
sl@0
   356
  }
sl@0
   357
  memsys5Enter();
sl@0
   358
  memsys5FreeUnsafe(pPrior);
sl@0
   359
  memsys5Leave();  
sl@0
   360
}
sl@0
   361
sl@0
   362
/*
sl@0
   363
** Change the size of an existing memory allocation
sl@0
   364
*/
sl@0
   365
static void *memsys5Realloc(void *pPrior, int nBytes){
sl@0
   366
  int nOld;
sl@0
   367
  void *p;
sl@0
   368
  if( pPrior==0 ){
sl@0
   369
    return memsys5Malloc(nBytes);
sl@0
   370
  }
sl@0
   371
  if( nBytes<=0 ){
sl@0
   372
    memsys5Free(pPrior);
sl@0
   373
    return 0;
sl@0
   374
  }
sl@0
   375
  nOld = memsys5Size(pPrior);
sl@0
   376
  if( nBytes<=nOld ){
sl@0
   377
    return pPrior;
sl@0
   378
  }
sl@0
   379
  memsys5Enter();
sl@0
   380
  p = memsys5MallocUnsafe(nBytes);
sl@0
   381
  if( p ){
sl@0
   382
    memcpy(p, pPrior, nOld);
sl@0
   383
    memsys5FreeUnsafe(pPrior);
sl@0
   384
  }
sl@0
   385
  memsys5Leave();
sl@0
   386
  return p;
sl@0
   387
}
sl@0
   388
sl@0
   389
/*
sl@0
   390
** Round up a request size to the next valid allocation size.
sl@0
   391
*/
sl@0
   392
static int memsys5Roundup(int n){
sl@0
   393
  int iFullSz;
sl@0
   394
  for(iFullSz=mem5.nAtom; iFullSz<n; iFullSz *= 2);
sl@0
   395
  return iFullSz;
sl@0
   396
}
sl@0
   397
sl@0
   398
static int memsys5Log(int iValue){
sl@0
   399
  int iLog;
sl@0
   400
  for(iLog=0; (1<<iLog)<iValue; iLog++);
sl@0
   401
  return iLog;
sl@0
   402
}
sl@0
   403
sl@0
   404
/*
sl@0
   405
** Initialize this module.
sl@0
   406
*/
sl@0
   407
static int memsys5Init(void *NotUsed){
sl@0
   408
  int ii;
sl@0
   409
  int nByte = sqlite3Config.nHeap;
sl@0
   410
  u8 *zByte = (u8 *)sqlite3Config.pHeap;
sl@0
   411
  int nMinLog;                 /* Log of minimum allocation size in bytes*/
sl@0
   412
  int iOffset;
sl@0
   413
sl@0
   414
  if( !zByte ){
sl@0
   415
    return SQLITE_ERROR;
sl@0
   416
  }
sl@0
   417
sl@0
   418
  nMinLog = memsys5Log(sqlite3Config.mnReq);
sl@0
   419
  mem5.nAtom = (1<<nMinLog);
sl@0
   420
  while( sizeof(Mem5Link)>mem5.nAtom ){
sl@0
   421
    mem5.nAtom = mem5.nAtom << 1;
sl@0
   422
  }
sl@0
   423
sl@0
   424
  mem5.nBlock = (nByte / (mem5.nAtom+sizeof(u8)));
sl@0
   425
  mem5.zPool = zByte;
sl@0
   426
  mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.nAtom];
sl@0
   427
sl@0
   428
  for(ii=0; ii<=LOGMAX; ii++){
sl@0
   429
    mem5.aiFreelist[ii] = -1;
sl@0
   430
  }
sl@0
   431
sl@0
   432
  iOffset = 0;
sl@0
   433
  for(ii=LOGMAX; ii>=0; ii--){
sl@0
   434
    int nAlloc = (1<<ii);
sl@0
   435
    if( (iOffset+nAlloc)<=mem5.nBlock ){
sl@0
   436
      mem5.aCtrl[iOffset] = ii | CTRL_FREE;
sl@0
   437
      memsys5Link(iOffset, ii);
sl@0
   438
      iOffset += nAlloc;
sl@0
   439
    }
sl@0
   440
    assert((iOffset+nAlloc)>mem5.nBlock);
sl@0
   441
  }
sl@0
   442
sl@0
   443
  return SQLITE_OK;
sl@0
   444
}
sl@0
   445
sl@0
   446
/*
sl@0
   447
** Deinitialize this module.
sl@0
   448
*/
sl@0
   449
static void memsys5Shutdown(void *NotUsed){
sl@0
   450
  return;
sl@0
   451
}
sl@0
   452
sl@0
   453
/*
sl@0
   454
** Open the file indicated and write a log of all unfreed memory 
sl@0
   455
** allocations into that log.
sl@0
   456
*/
sl@0
   457
void sqlite3Memsys5Dump(const char *zFilename){
sl@0
   458
#ifdef SQLITE_DEBUG
sl@0
   459
  FILE *out;
sl@0
   460
  int i, j, n;
sl@0
   461
  int nMinLog;
sl@0
   462
sl@0
   463
  if( zFilename==0 || zFilename[0]==0 ){
sl@0
   464
    out = stdout;
sl@0
   465
  }else{
sl@0
   466
    out = fopen(zFilename, "w");
sl@0
   467
    if( out==0 ){
sl@0
   468
      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
sl@0
   469
                      zFilename);
sl@0
   470
      return;
sl@0
   471
    }
sl@0
   472
  }
sl@0
   473
  memsys5Enter();
sl@0
   474
  nMinLog = memsys5Log(mem5.nAtom);
sl@0
   475
  for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
sl@0
   476
    for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
sl@0
   477
    fprintf(out, "freelist items of size %d: %d\n", mem5.nAtom << i, n);
sl@0
   478
  }
sl@0
   479
  fprintf(out, "mem5.nAlloc       = %llu\n", mem5.nAlloc);
sl@0
   480
  fprintf(out, "mem5.totalAlloc   = %llu\n", mem5.totalAlloc);
sl@0
   481
  fprintf(out, "mem5.totalExcess  = %llu\n", mem5.totalExcess);
sl@0
   482
  fprintf(out, "mem5.currentOut   = %u\n", mem5.currentOut);
sl@0
   483
  fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
sl@0
   484
  fprintf(out, "mem5.maxOut       = %u\n", mem5.maxOut);
sl@0
   485
  fprintf(out, "mem5.maxCount     = %u\n", mem5.maxCount);
sl@0
   486
  fprintf(out, "mem5.maxRequest   = %u\n", mem5.maxRequest);
sl@0
   487
  memsys5Leave();
sl@0
   488
  if( out==stdout ){
sl@0
   489
    fflush(stdout);
sl@0
   490
  }else{
sl@0
   491
    fclose(out);
sl@0
   492
  }
sl@0
   493
#endif
sl@0
   494
}
sl@0
   495
sl@0
   496
/*
sl@0
   497
** This routine is the only routine in this file with external 
sl@0
   498
** linkage. It returns a pointer to a static sqlite3_mem_methods
sl@0
   499
** struct populated with the memsys5 methods.
sl@0
   500
*/
sl@0
   501
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
sl@0
   502
  static const sqlite3_mem_methods memsys5Methods = {
sl@0
   503
     memsys5Malloc,
sl@0
   504
     memsys5Free,
sl@0
   505
     memsys5Realloc,
sl@0
   506
     memsys5Size,
sl@0
   507
     memsys5Roundup,
sl@0
   508
     memsys5Init,
sl@0
   509
     memsys5Shutdown,
sl@0
   510
     0
sl@0
   511
  };
sl@0
   512
  return &memsys5Methods;
sl@0
   513
}
sl@0
   514
sl@0
   515
#endif /* SQLITE_ENABLE_MEMSYS5 */