extensions/sqlite/sqlite-source/mem2.c
author David Anderson <dvander@alliedmods.net>
Sun Oct 28 05:48:06 2007 +0000 (2007-10-28)
changeset 1645 27307df4d711
permissions -rw-r--r--
updated to sqlite-3.5.1 now that it's stable
used new shared cache functionality (yay)
dvander@1645
     1
/*
dvander@1645
     2
** 2007 August 15
dvander@1645
     3
**
dvander@1645
     4
** The author disclaims copyright to this source code.  In place of
dvander@1645
     5
** a legal notice, here is a blessing:
dvander@1645
     6
**
dvander@1645
     7
**    May you do good and not evil.
dvander@1645
     8
**    May you find forgiveness for yourself and forgive others.
dvander@1645
     9
**    May you share freely, never taking more than you give.
dvander@1645
    10
**
dvander@1645
    11
*************************************************************************
dvander@1645
    12
** This file contains the C functions that implement a memory
dvander@1645
    13
** allocation subsystem for use by SQLite.  
dvander@1645
    14
**
dvander@1645
    15
** $Id$
dvander@1645
    16
*/
dvander@1645
    17
dvander@1645
    18
/*
dvander@1645
    19
** This version of the memory allocator is used only if the
dvander@1645
    20
** SQLITE_MEMDEBUG macro is defined and SQLITE_OMIT_MEMORY_ALLOCATION
dvander@1645
    21
** is not defined.
dvander@1645
    22
*/
dvander@1645
    23
#if defined(SQLITE_MEMDEBUG) && !defined(SQLITE_OMIT_MEMORY_ALLOCATION)
dvander@1645
    24
dvander@1645
    25
/*
dvander@1645
    26
** We will eventually construct multiple memory allocation subsystems
dvander@1645
    27
** suitable for use in various contexts:
dvander@1645
    28
**
dvander@1645
    29
**    *  Normal multi-threaded builds
dvander@1645
    30
**    *  Normal single-threaded builds
dvander@1645
    31
**    *  Debugging builds
dvander@1645
    32
**
dvander@1645
    33
** This version is suitable for use in debugging builds.
dvander@1645
    34
**
dvander@1645
    35
** Features:
dvander@1645
    36
**
dvander@1645
    37
**    * Every allocate has guards at both ends.
dvander@1645
    38
**    * New allocations are initialized with randomness
dvander@1645
    39
**    * Allocations are overwritten with randomness when freed
dvander@1645
    40
**    * Optional logs of malloc activity generated
dvander@1645
    41
**    * Summary of outstanding allocations with backtraces to the
dvander@1645
    42
**      point of allocation.
dvander@1645
    43
**    * The ability to simulate memory allocation failure
dvander@1645
    44
*/
dvander@1645
    45
#include "sqliteInt.h"
dvander@1645
    46
#include <stdio.h>
dvander@1645
    47
dvander@1645
    48
/*
dvander@1645
    49
** The backtrace functionality is only available with GLIBC
dvander@1645
    50
*/
dvander@1645
    51
#ifdef __GLIBC__
dvander@1645
    52
  extern int backtrace(void**,int);
dvander@1645
    53
  extern void backtrace_symbols_fd(void*const*,int,int);
dvander@1645
    54
#else
dvander@1645
    55
# define backtrace(A,B) 0
dvander@1645
    56
# define backtrace_symbols_fd(A,B,C)
dvander@1645
    57
#endif
dvander@1645
    58
dvander@1645
    59
/*
dvander@1645
    60
** Each memory allocation looks like this:
dvander@1645
    61
**
dvander@1645
    62
**  ------------------------------------------------------------------------
dvander@1645
    63
**  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
dvander@1645
    64
**  ------------------------------------------------------------------------
dvander@1645
    65
**
dvander@1645
    66
** The application code sees only a pointer to the allocation.  We have
dvander@1645
    67
** to back up from the allocation pointer to find the MemBlockHdr.  The
dvander@1645
    68
** MemBlockHdr tells us the size of the allocation and the number of
dvander@1645
    69
** backtrace pointers.  There is also a guard word at the end of the
dvander@1645
    70
** MemBlockHdr.
dvander@1645
    71
*/
dvander@1645
    72
struct MemBlockHdr {
dvander@1645
    73
  struct MemBlockHdr *pNext, *pPrev;  /* Linked list of all unfreed memory */
dvander@1645
    74
  int iSize;                          /* Size of this allocation */
dvander@1645
    75
  char nBacktrace;                    /* Number of backtraces on this alloc */
dvander@1645
    76
  char nBacktraceSlots;               /* Available backtrace slots */
dvander@1645
    77
  short nTitle;                       /* Bytes of title; includes '\0' */
dvander@1645
    78
  int iForeGuard;                     /* Guard word for sanity */
dvander@1645
    79
};
dvander@1645
    80
dvander@1645
    81
/*
dvander@1645
    82
** Guard words
dvander@1645
    83
*/
dvander@1645
    84
#define FOREGUARD 0x80F5E153
dvander@1645
    85
#define REARGUARD 0xE4676B53
dvander@1645
    86
dvander@1645
    87
/*
dvander@1645
    88
** All of the static variables used by this module are collected
dvander@1645
    89
** into a single structure named "mem".  This is to keep the
dvander@1645
    90
** static variables organized and to reduce namespace pollution
dvander@1645
    91
** when this module is combined with other in the amalgamation.
dvander@1645
    92
*/
dvander@1645
    93
static struct {
dvander@1645
    94
  /*
dvander@1645
    95
  ** The alarm callback and its arguments.  The mem.mutex lock will
dvander@1645
    96
  ** be held while the callback is running.  Recursive calls into
dvander@1645
    97
  ** the memory subsystem are allowed, but no new callbacks will be
dvander@1645
    98
  ** issued.  The alarmBusy variable is set to prevent recursive
dvander@1645
    99
  ** callbacks.
dvander@1645
   100
  */
dvander@1645
   101
  sqlite3_int64 alarmThreshold;
dvander@1645
   102
  void (*alarmCallback)(void*, sqlite3_int64, int);
dvander@1645
   103
  void *alarmArg;
dvander@1645
   104
  int alarmBusy;
dvander@1645
   105
  
dvander@1645
   106
  /*
dvander@1645
   107
  ** Mutex to control access to the memory allocation subsystem.
dvander@1645
   108
  */
dvander@1645
   109
  sqlite3_mutex *mutex;
dvander@1645
   110
  
dvander@1645
   111
  /*
dvander@1645
   112
  ** Current allocation and high-water mark.
dvander@1645
   113
  */
dvander@1645
   114
  sqlite3_int64 nowUsed;
dvander@1645
   115
  sqlite3_int64 mxUsed;
dvander@1645
   116
  
dvander@1645
   117
  /*
dvander@1645
   118
  ** Head and tail of a linked list of all outstanding allocations
dvander@1645
   119
  */
dvander@1645
   120
  struct MemBlockHdr *pFirst;
dvander@1645
   121
  struct MemBlockHdr *pLast;
dvander@1645
   122
  
dvander@1645
   123
  /*
dvander@1645
   124
  ** The number of levels of backtrace to save in new allocations.
dvander@1645
   125
  */
dvander@1645
   126
  int nBacktrace;
dvander@1645
   127
dvander@1645
   128
  /*
dvander@1645
   129
  ** Title text to insert in front of each block
dvander@1645
   130
  */
dvander@1645
   131
  int nTitle;        /* Bytes of zTitle to save.  Includes '\0' and padding */
dvander@1645
   132
  char zTitle[100];  /* The title text */
dvander@1645
   133
dvander@1645
   134
  /*
dvander@1645
   135
  ** These values are used to simulate malloc failures.  When
dvander@1645
   136
  ** iFail is 1, simulate a malloc failures and reset the value
dvander@1645
   137
  ** to iReset.
dvander@1645
   138
  */
dvander@1645
   139
  int iFail;    /* Decrement and fail malloc when this is 1 */
dvander@1645
   140
  int iReset;   /* When malloc fails set iiFail to this value */
dvander@1645
   141
  int iFailCnt;         /* Number of failures */
dvander@1645
   142
  int iBenignFailCnt;   /* Number of benign failures */
dvander@1645
   143
  int iNextIsBenign;    /* True if the next call to malloc may fail benignly */
dvander@1645
   144
  int iIsBenign;        /* All malloc calls may fail benignly */
dvander@1645
   145
dvander@1645
   146
  /* 
dvander@1645
   147
  ** sqlite3MallocDisallow() increments the following counter.
dvander@1645
   148
  ** sqlite3MallocAllow() decrements it.
dvander@1645
   149
  */
dvander@1645
   150
  int disallow; /* Do not allow memory allocation */
dvander@1645
   151
  
dvander@1645
   152
  
dvander@1645
   153
} mem;
dvander@1645
   154
dvander@1645
   155
dvander@1645
   156
/*
dvander@1645
   157
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
dvander@1645
   158
*/
dvander@1645
   159
static void enterMem(void){
dvander@1645
   160
  if( mem.mutex==0 ){
dvander@1645
   161
    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
dvander@1645
   162
  }
dvander@1645
   163
  sqlite3_mutex_enter(mem.mutex);
dvander@1645
   164
}
dvander@1645
   165
dvander@1645
   166
/*
dvander@1645
   167
** Return the amount of memory currently checked out.
dvander@1645
   168
*/
dvander@1645
   169
sqlite3_int64 sqlite3_memory_used(void){
dvander@1645
   170
  sqlite3_int64 n;
dvander@1645
   171
  enterMem();
dvander@1645
   172
  n = mem.nowUsed;
dvander@1645
   173
  sqlite3_mutex_leave(mem.mutex);  
dvander@1645
   174
  return n;
dvander@1645
   175
}
dvander@1645
   176
dvander@1645
   177
/*
dvander@1645
   178
** Return the maximum amount of memory that has ever been
dvander@1645
   179
** checked out since either the beginning of this process
dvander@1645
   180
** or since the most recent reset.
dvander@1645
   181
*/
dvander@1645
   182
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
dvander@1645
   183
  sqlite3_int64 n;
dvander@1645
   184
  enterMem();
dvander@1645
   185
  n = mem.mxUsed;
dvander@1645
   186
  if( resetFlag ){
dvander@1645
   187
    mem.mxUsed = mem.nowUsed;
dvander@1645
   188
  }
dvander@1645
   189
  sqlite3_mutex_leave(mem.mutex);  
dvander@1645
   190
  return n;
dvander@1645
   191
}
dvander@1645
   192
dvander@1645
   193
/*
dvander@1645
   194
** Change the alarm callback
dvander@1645
   195
*/
dvander@1645
   196
int sqlite3_memory_alarm(
dvander@1645
   197
  void(*xCallback)(void *pArg, sqlite3_int64 used, int N),
dvander@1645
   198
  void *pArg,
dvander@1645
   199
  sqlite3_int64 iThreshold
dvander@1645
   200
){
dvander@1645
   201
  enterMem();
dvander@1645
   202
  mem.alarmCallback = xCallback;
dvander@1645
   203
  mem.alarmArg = pArg;
dvander@1645
   204
  mem.alarmThreshold = iThreshold;
dvander@1645
   205
  sqlite3_mutex_leave(mem.mutex);
dvander@1645
   206
  return SQLITE_OK;
dvander@1645
   207
}
dvander@1645
   208
dvander@1645
   209
/*
dvander@1645
   210
** Trigger the alarm 
dvander@1645
   211
*/
dvander@1645
   212
static void sqlite3MemsysAlarm(int nByte){
dvander@1645
   213
  void (*xCallback)(void*,sqlite3_int64,int);
dvander@1645
   214
  sqlite3_int64 nowUsed;
dvander@1645
   215
  void *pArg;
dvander@1645
   216
  if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
dvander@1645
   217
  mem.alarmBusy = 1;
dvander@1645
   218
  xCallback = mem.alarmCallback;
dvander@1645
   219
  nowUsed = mem.nowUsed;
dvander@1645
   220
  pArg = mem.alarmArg;
dvander@1645
   221
  sqlite3_mutex_leave(mem.mutex);
dvander@1645
   222
  xCallback(pArg, nowUsed, nByte);
dvander@1645
   223
  sqlite3_mutex_enter(mem.mutex);
dvander@1645
   224
  mem.alarmBusy = 0;
dvander@1645
   225
}
dvander@1645
   226
dvander@1645
   227
/*
dvander@1645
   228
** Given an allocation, find the MemBlockHdr for that allocation.
dvander@1645
   229
**
dvander@1645
   230
** This routine checks the guards at either end of the allocation and
dvander@1645
   231
** if they are incorrect it asserts.
dvander@1645
   232
*/
dvander@1645
   233
static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
dvander@1645
   234
  struct MemBlockHdr *p;
dvander@1645
   235
  int *pInt;
dvander@1645
   236
dvander@1645
   237
  p = (struct MemBlockHdr*)pAllocation;
dvander@1645
   238
  p--;
dvander@1645
   239
  assert( p->iForeGuard==FOREGUARD );
dvander@1645
   240
  assert( (p->iSize & 3)==0 );
dvander@1645
   241
  pInt = (int*)pAllocation;
dvander@1645
   242
  assert( pInt[p->iSize/sizeof(int)]==REARGUARD );
dvander@1645
   243
  return p;
dvander@1645
   244
}
dvander@1645
   245
dvander@1645
   246
/*
dvander@1645
   247
** This routine is called once the first time a simulated memory
dvander@1645
   248
** failure occurs.  The sole purpose of this routine is to provide
dvander@1645
   249
** a convenient place to set a debugger breakpoint when debugging
dvander@1645
   250
** errors related to malloc() failures.
dvander@1645
   251
*/
dvander@1645
   252
static void sqlite3MemsysFailed(void){
dvander@1645
   253
  mem.iFailCnt = 0;
dvander@1645
   254
  mem.iBenignFailCnt = 0;
dvander@1645
   255
}
dvander@1645
   256
dvander@1645
   257
/*
dvander@1645
   258
** Allocate nByte bytes of memory.
dvander@1645
   259
*/
dvander@1645
   260
void *sqlite3_malloc(int nByte){
dvander@1645
   261
  struct MemBlockHdr *pHdr;
dvander@1645
   262
  void **pBt;
dvander@1645
   263
  char *z;
dvander@1645
   264
  int *pInt;
dvander@1645
   265
  void *p = 0;
dvander@1645
   266
  int totalSize;
dvander@1645
   267
dvander@1645
   268
  if( nByte>0 ){
dvander@1645
   269
    enterMem();
dvander@1645
   270
    assert( mem.disallow==0 );
dvander@1645
   271
    if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){
dvander@1645
   272
      sqlite3MemsysAlarm(nByte);
dvander@1645
   273
    }
dvander@1645
   274
    nByte = (nByte+3)&~3;
dvander@1645
   275
    totalSize = nByte + sizeof(*pHdr) + sizeof(int) +
dvander@1645
   276
                 mem.nBacktrace*sizeof(void*) + mem.nTitle;
dvander@1645
   277
    if( mem.iFail>0 ){
dvander@1645
   278
      if( mem.iFail==1 ){
dvander@1645
   279
        p = 0;
dvander@1645
   280
        mem.iFail = mem.iReset;
dvander@1645
   281
        if( mem.iFailCnt==0 ){
dvander@1645
   282
          sqlite3MemsysFailed();  /* A place to set a breakpoint */
dvander@1645
   283
        }
dvander@1645
   284
        mem.iFailCnt++;
dvander@1645
   285
        if( mem.iNextIsBenign || mem.iIsBenign ){
dvander@1645
   286
          mem.iBenignFailCnt++;
dvander@1645
   287
        }
dvander@1645
   288
      }else{
dvander@1645
   289
        p = malloc(totalSize);
dvander@1645
   290
        mem.iFail--;
dvander@1645
   291
      }
dvander@1645
   292
    }else{
dvander@1645
   293
      p = malloc(totalSize);
dvander@1645
   294
      if( p==0 ){
dvander@1645
   295
        sqlite3MemsysAlarm(nByte);
dvander@1645
   296
        p = malloc(totalSize);
dvander@1645
   297
      }
dvander@1645
   298
    }
dvander@1645
   299
    if( p ){
dvander@1645
   300
      z = p;
dvander@1645
   301
      pBt = (void**)&z[mem.nTitle];
dvander@1645
   302
      pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
dvander@1645
   303
      pHdr->pNext = 0;
dvander@1645
   304
      pHdr->pPrev = mem.pLast;
dvander@1645
   305
      if( mem.pLast ){
dvander@1645
   306
        mem.pLast->pNext = pHdr;
dvander@1645
   307
      }else{
dvander@1645
   308
        mem.pFirst = pHdr;
dvander@1645
   309
      }
dvander@1645
   310
      mem.pLast = pHdr;
dvander@1645
   311
      pHdr->iForeGuard = FOREGUARD;
dvander@1645
   312
      pHdr->nBacktraceSlots = mem.nBacktrace;
dvander@1645
   313
      pHdr->nTitle = mem.nTitle;
dvander@1645
   314
      if( mem.nBacktrace ){
dvander@1645
   315
        void *aAddr[40];
dvander@1645
   316
        pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
dvander@1645
   317
        memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
dvander@1645
   318
      }else{
dvander@1645
   319
        pHdr->nBacktrace = 0;
dvander@1645
   320
      }
dvander@1645
   321
      if( mem.nTitle ){
dvander@1645
   322
        memcpy(z, mem.zTitle, mem.nTitle);
dvander@1645
   323
      }
dvander@1645
   324
      pHdr->iSize = nByte;
dvander@1645
   325
      pInt = (int*)&pHdr[1];
dvander@1645
   326
      pInt[nByte/sizeof(int)] = REARGUARD;
dvander@1645
   327
      memset(pInt, 0x65, nByte);
dvander@1645
   328
      mem.nowUsed += nByte;
dvander@1645
   329
      if( mem.nowUsed>mem.mxUsed ){
dvander@1645
   330
        mem.mxUsed = mem.nowUsed;
dvander@1645
   331
      }
dvander@1645
   332
      p = (void*)pInt;
dvander@1645
   333
    }
dvander@1645
   334
    sqlite3_mutex_leave(mem.mutex);
dvander@1645
   335
  }
dvander@1645
   336
  mem.iNextIsBenign = 0;
dvander@1645
   337
  return p; 
dvander@1645
   338
}
dvander@1645
   339
dvander@1645
   340
/*
dvander@1645
   341
** Free memory.
dvander@1645
   342
*/
dvander@1645
   343
void sqlite3_free(void *pPrior){
dvander@1645
   344
  struct MemBlockHdr *pHdr;
dvander@1645
   345
  void **pBt;
dvander@1645
   346
  char *z;
dvander@1645
   347
  if( pPrior==0 ){
dvander@1645
   348
    return;
dvander@1645
   349
  }
dvander@1645
   350
  assert( mem.mutex!=0 );
dvander@1645
   351
  pHdr = sqlite3MemsysGetHeader(pPrior);
dvander@1645
   352
  pBt = (void**)pHdr;
dvander@1645
   353
  pBt -= pHdr->nBacktraceSlots;
dvander@1645
   354
  sqlite3_mutex_enter(mem.mutex);
dvander@1645
   355
  mem.nowUsed -= pHdr->iSize;
dvander@1645
   356
  if( pHdr->pPrev ){
dvander@1645
   357
    assert( pHdr->pPrev->pNext==pHdr );
dvander@1645
   358
    pHdr->pPrev->pNext = pHdr->pNext;
dvander@1645
   359
  }else{
dvander@1645
   360
    assert( mem.pFirst==pHdr );
dvander@1645
   361
    mem.pFirst = pHdr->pNext;
dvander@1645
   362
  }
dvander@1645
   363
  if( pHdr->pNext ){
dvander@1645
   364
    assert( pHdr->pNext->pPrev==pHdr );
dvander@1645
   365
    pHdr->pNext->pPrev = pHdr->pPrev;
dvander@1645
   366
  }else{
dvander@1645
   367
    assert( mem.pLast==pHdr );
dvander@1645
   368
    mem.pLast = pHdr->pPrev;
dvander@1645
   369
  }
dvander@1645
   370
  z = (char*)pBt;
dvander@1645
   371
  z -= pHdr->nTitle;
dvander@1645
   372
  memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
dvander@1645
   373
                  pHdr->iSize + sizeof(int) + pHdr->nTitle);
dvander@1645
   374
  free(z);
dvander@1645
   375
  sqlite3_mutex_leave(mem.mutex);  
dvander@1645
   376
}
dvander@1645
   377
dvander@1645
   378
/*
dvander@1645
   379
** Change the size of an existing memory allocation.
dvander@1645
   380
**
dvander@1645
   381
** For this debugging implementation, we *always* make a copy of the
dvander@1645
   382
** allocation into a new place in memory.  In this way, if the 
dvander@1645
   383
** higher level code is using pointer to the old allocation, it is 
dvander@1645
   384
** much more likely to break and we are much more liking to find
dvander@1645
   385
** the error.
dvander@1645
   386
*/
dvander@1645
   387
void *sqlite3_realloc(void *pPrior, int nByte){
dvander@1645
   388
  struct MemBlockHdr *pOldHdr;
dvander@1645
   389
  void *pNew;
dvander@1645
   390
  if( pPrior==0 ){
dvander@1645
   391
    return sqlite3_malloc(nByte);
dvander@1645
   392
  }
dvander@1645
   393
  if( nByte<=0 ){
dvander@1645
   394
    sqlite3_free(pPrior);
dvander@1645
   395
    return 0;
dvander@1645
   396
  }
dvander@1645
   397
  assert( mem.disallow==0 );
dvander@1645
   398
  pOldHdr = sqlite3MemsysGetHeader(pPrior);
dvander@1645
   399
  pNew = sqlite3_malloc(nByte);
dvander@1645
   400
  if( pNew ){
dvander@1645
   401
    memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
dvander@1645
   402
    if( nByte>pOldHdr->iSize ){
dvander@1645
   403
      memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
dvander@1645
   404
    }
dvander@1645
   405
    sqlite3_free(pPrior);
dvander@1645
   406
  }
dvander@1645
   407
  return pNew;
dvander@1645
   408
}
dvander@1645
   409
dvander@1645
   410
/*
dvander@1645
   411
** Set the number of backtrace levels kept for each allocation.
dvander@1645
   412
** A value of zero turns of backtracing.  The number is always rounded
dvander@1645
   413
** up to a multiple of 2.
dvander@1645
   414
*/
dvander@1645
   415
void sqlite3_memdebug_backtrace(int depth){
dvander@1645
   416
  if( depth<0 ){ depth = 0; }
dvander@1645
   417
  if( depth>20 ){ depth = 20; }
dvander@1645
   418
  depth = (depth+1)&0xfe;
dvander@1645
   419
  mem.nBacktrace = depth;
dvander@1645
   420
}
dvander@1645
   421
dvander@1645
   422
/*
dvander@1645
   423
** Set the title string for subsequent allocations.
dvander@1645
   424
*/
dvander@1645
   425
void sqlite3_memdebug_settitle(const char *zTitle){
dvander@1645
   426
  int n = strlen(zTitle) + 1;
dvander@1645
   427
  enterMem();
dvander@1645
   428
  if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
dvander@1645
   429
  memcpy(mem.zTitle, zTitle, n);
dvander@1645
   430
  mem.zTitle[n] = 0;
dvander@1645
   431
  mem.nTitle = (n+3)&~3;
dvander@1645
   432
  sqlite3_mutex_leave(mem.mutex);
dvander@1645
   433
}
dvander@1645
   434
dvander@1645
   435
/*
dvander@1645
   436
** Open the file indicated and write a log of all unfreed memory 
dvander@1645
   437
** allocations into that log.
dvander@1645
   438
*/
dvander@1645
   439
void sqlite3_memdebug_dump(const char *zFilename){
dvander@1645
   440
  FILE *out;
dvander@1645
   441
  struct MemBlockHdr *pHdr;
dvander@1645
   442
  void **pBt;
dvander@1645
   443
  out = fopen(zFilename, "w");
dvander@1645
   444
  if( out==0 ){
dvander@1645
   445
    fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
dvander@1645
   446
                    zFilename);
dvander@1645
   447
    return;
dvander@1645
   448
  }
dvander@1645
   449
  for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
dvander@1645
   450
    char *z = (char*)pHdr;
dvander@1645
   451
    z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
dvander@1645
   452
    fprintf(out, "**** %d bytes at %p from %s ****\n", 
dvander@1645
   453
            pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
dvander@1645
   454
    if( pHdr->nBacktrace ){
dvander@1645
   455
      fflush(out);
dvander@1645
   456
      pBt = (void**)pHdr;
dvander@1645
   457
      pBt -= pHdr->nBacktraceSlots;
dvander@1645
   458
      backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
dvander@1645
   459
      fprintf(out, "\n");
dvander@1645
   460
    }
dvander@1645
   461
  }
dvander@1645
   462
  fclose(out);
dvander@1645
   463
}
dvander@1645
   464
dvander@1645
   465
/*
dvander@1645
   466
** This routine is used to simulate malloc failures.
dvander@1645
   467
**
dvander@1645
   468
** After calling this routine, there will be iFail successful
dvander@1645
   469
** memory allocations and then a failure.  If iRepeat is 1
dvander@1645
   470
** all subsequent memory allocations will fail.  If iRepeat is
dvander@1645
   471
** 0, only a single allocation will fail.  If iRepeat is negative
dvander@1645
   472
** then the previous setting for iRepeat is unchanged.
dvander@1645
   473
**
dvander@1645
   474
** Each call to this routine overrides the previous.  To disable
dvander@1645
   475
** the simulated allocation failure mechanism, set iFail to -1.
dvander@1645
   476
**
dvander@1645
   477
** This routine returns the number of simulated failures that have
dvander@1645
   478
** occurred since the previous call.
dvander@1645
   479
*/
dvander@1645
   480
int sqlite3_memdebug_fail(int iFail, int iRepeat, int *piBenign){
dvander@1645
   481
  int n = mem.iFailCnt;
dvander@1645
   482
  if( piBenign ){
dvander@1645
   483
    *piBenign = mem.iBenignFailCnt;
dvander@1645
   484
  }
dvander@1645
   485
  mem.iFail = iFail+1;
dvander@1645
   486
  if( iRepeat>=0 ){
dvander@1645
   487
    mem.iReset = iRepeat;
dvander@1645
   488
  }
dvander@1645
   489
  mem.iFailCnt = 0;
dvander@1645
   490
  mem.iBenignFailCnt = 0;
dvander@1645
   491
  return n;
dvander@1645
   492
}
dvander@1645
   493
dvander@1645
   494
int sqlite3_memdebug_pending(){
dvander@1645
   495
  return (mem.iFail-1);
dvander@1645
   496
}
dvander@1645
   497
dvander@1645
   498
/*
dvander@1645
   499
** The following three functions are used to indicate to the test 
dvander@1645
   500
** infrastructure which malloc() calls may fail benignly without
dvander@1645
   501
** affecting functionality. This can happen when resizing hash tables 
dvander@1645
   502
** (failing to resize a hash-table is a performance hit, but not an 
dvander@1645
   503
** error) or sometimes during a rollback operation.
dvander@1645
   504
**
dvander@1645
   505
** If the argument is true, sqlite3MallocBenignFailure() indicates that the
dvander@1645
   506
** next call to allocate memory may fail benignly.
dvander@1645
   507
**
dvander@1645
   508
** If sqlite3MallocEnterBenignBlock() is called with a non-zero argument,
dvander@1645
   509
** then all memory allocations requested before the next call to
dvander@1645
   510
** sqlite3MallocLeaveBenignBlock() may fail benignly.
dvander@1645
   511
*/
dvander@1645
   512
void sqlite3MallocBenignFailure(int isBenign){
dvander@1645
   513
  if( isBenign ){
dvander@1645
   514
    mem.iNextIsBenign = 1;
dvander@1645
   515
  }
dvander@1645
   516
}
dvander@1645
   517
void sqlite3MallocEnterBenignBlock(int isBenign){
dvander@1645
   518
  if( isBenign ){
dvander@1645
   519
    mem.iIsBenign = 1;
dvander@1645
   520
  }
dvander@1645
   521
}
dvander@1645
   522
void sqlite3MallocLeaveBenignBlock(){
dvander@1645
   523
  mem.iIsBenign = 0;
dvander@1645
   524
}
dvander@1645
   525
dvander@1645
   526
/*
dvander@1645
   527
** The following two routines are used to assert that no memory
dvander@1645
   528
** allocations occur between one call and the next.  The use of
dvander@1645
   529
** these routines does not change the computed results in any way.
dvander@1645
   530
** These routines are like asserts.
dvander@1645
   531
*/
dvander@1645
   532
void sqlite3MallocDisallow(void){
dvander@1645
   533
  assert( mem.mutex!=0 );
dvander@1645
   534
  sqlite3_mutex_enter(mem.mutex);
dvander@1645
   535
  mem.disallow++;
dvander@1645
   536
  sqlite3_mutex_leave(mem.mutex);
dvander@1645
   537
}
dvander@1645
   538
void sqlite3MallocAllow(void){
dvander@1645
   539
  assert( mem.mutex );
dvander@1645
   540
  sqlite3_mutex_enter(mem.mutex);
dvander@1645
   541
  assert( mem.disallow>0 );
dvander@1645
   542
  mem.disallow--;
dvander@1645
   543
  sqlite3_mutex_leave(mem.mutex);
dvander@1645
   544
}
dvander@1645
   545
dvander@1645
   546
#endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */