extensions/sqlite/sqlite-source/mem1.c
author Matt Woodrow <pred@alliedmods.net>
Wed Apr 16 05:41:34 2008 +0000 (2008-04-16)
changeset 2005 92033efef85f
parent 1952 b7aa2b626807
permissions -rw-r--r--
Added amb1609 - Persistant option to TF2_SetPlayerClass
ds@1952
     1
/*
ds@1952
     2
** 2007 August 14
ds@1952
     3
**
ds@1952
     4
** The author disclaims copyright to this source code.  In place of
ds@1952
     5
** a legal notice, here is a blessing:
ds@1952
     6
**
ds@1952
     7
**    May you do good and not evil.
ds@1952
     8
**    May you find forgiveness for yourself and forgive others.
ds@1952
     9
**    May you share freely, never taking more than you give.
ds@1952
    10
**
ds@1952
    11
*************************************************************************
ds@1952
    12
** This file contains the C functions that implement a memory
ds@1952
    13
** allocation subsystem for use by SQLite.  
ds@1952
    14
**
ds@1952
    15
** $Id$
ds@1952
    16
*/
ds@1952
    17
ds@1952
    18
/*
ds@1952
    19
** This version of the memory allocator is the default.  It is
ds@1952
    20
** used when no other memory allocator is specified using compile-time
ds@1952
    21
** macros.
ds@1952
    22
*/
ds@1952
    23
#if !defined(SQLITE_MEMDEBUG) && !defined(SQLITE_OMIT_MEMORY_ALLOCATION)
ds@1952
    24
ds@1952
    25
/*
ds@1952
    26
** We will eventually construct multiple memory allocation subsystems
ds@1952
    27
** suitable for use in various contexts:
ds@1952
    28
**
ds@1952
    29
**    *  Normal multi-threaded builds
ds@1952
    30
**    *  Normal single-threaded builds
ds@1952
    31
**    *  Debugging builds
ds@1952
    32
**
ds@1952
    33
** This initial version is suitable for use in normal multi-threaded
ds@1952
    34
** builds.  We envision that alternative versions will be stored in
ds@1952
    35
** separate source files.  #ifdefs will be used to select the code from
ds@1952
    36
** one of the various memN.c source files for use in any given build.
ds@1952
    37
*/
ds@1952
    38
#include "sqliteInt.h"
ds@1952
    39
ds@1952
    40
/*
ds@1952
    41
** All of the static variables used by this module are collected
ds@1952
    42
** into a single structure named "mem".  This is to keep the
ds@1952
    43
** static variables organized and to reduce namespace pollution
ds@1952
    44
** when this module is combined with other in the amalgamation.
ds@1952
    45
*/
ds@1952
    46
static struct {
ds@1952
    47
  /*
ds@1952
    48
  ** The alarm callback and its arguments.  The mem.mutex lock will
ds@1952
    49
  ** be held while the callback is running.  Recursive calls into
ds@1952
    50
  ** the memory subsystem are allowed, but no new callbacks will be
ds@1952
    51
  ** issued.  The alarmBusy variable is set to prevent recursive
ds@1952
    52
  ** callbacks.
ds@1952
    53
  */
ds@1952
    54
  sqlite3_int64 alarmThreshold;
ds@1952
    55
  void (*alarmCallback)(void*, sqlite3_int64,int);
ds@1952
    56
  void *alarmArg;
ds@1952
    57
  int alarmBusy;
ds@1952
    58
  
ds@1952
    59
  /*
ds@1952
    60
  ** Mutex to control access to the memory allocation subsystem.
ds@1952
    61
  */
ds@1952
    62
  sqlite3_mutex *mutex;
ds@1952
    63
  
ds@1952
    64
  /*
ds@1952
    65
  ** Current allocation and high-water mark.
ds@1952
    66
  */
ds@1952
    67
  sqlite3_int64 nowUsed;
ds@1952
    68
  sqlite3_int64 mxUsed;
ds@1952
    69
  
ds@1952
    70
 
ds@1952
    71
} mem;
ds@1952
    72
ds@1952
    73
/*
ds@1952
    74
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
ds@1952
    75
*/
ds@1952
    76
static void enterMem(void){
ds@1952
    77
  if( mem.mutex==0 ){
ds@1952
    78
    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
ds@1952
    79
  }
ds@1952
    80
  sqlite3_mutex_enter(mem.mutex);
ds@1952
    81
}
ds@1952
    82
ds@1952
    83
/*
ds@1952
    84
** Return the amount of memory currently checked out.
ds@1952
    85
*/
ds@1952
    86
sqlite3_int64 sqlite3_memory_used(void){
ds@1952
    87
  sqlite3_int64 n;
ds@1952
    88
  enterMem();
ds@1952
    89
  n = mem.nowUsed;
ds@1952
    90
  sqlite3_mutex_leave(mem.mutex);  
ds@1952
    91
  return n;
ds@1952
    92
}
ds@1952
    93
ds@1952
    94
/*
ds@1952
    95
** Return the maximum amount of memory that has ever been
ds@1952
    96
** checked out since either the beginning of this process
ds@1952
    97
** or since the most recent reset.
ds@1952
    98
*/
ds@1952
    99
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
ds@1952
   100
  sqlite3_int64 n;
ds@1952
   101
  enterMem();
ds@1952
   102
  n = mem.mxUsed;
ds@1952
   103
  if( resetFlag ){
ds@1952
   104
    mem.mxUsed = mem.nowUsed;
ds@1952
   105
  }
ds@1952
   106
  sqlite3_mutex_leave(mem.mutex);  
ds@1952
   107
  return n;
ds@1952
   108
}
ds@1952
   109
ds@1952
   110
/*
ds@1952
   111
** Change the alarm callback
ds@1952
   112
*/
ds@1952
   113
int sqlite3_memory_alarm(
ds@1952
   114
  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
ds@1952
   115
  void *pArg,
ds@1952
   116
  sqlite3_int64 iThreshold
ds@1952
   117
){
ds@1952
   118
  enterMem();
ds@1952
   119
  mem.alarmCallback = xCallback;
ds@1952
   120
  mem.alarmArg = pArg;
ds@1952
   121
  mem.alarmThreshold = iThreshold;
ds@1952
   122
  sqlite3_mutex_leave(mem.mutex);
ds@1952
   123
  return SQLITE_OK;
ds@1952
   124
}
ds@1952
   125
ds@1952
   126
/*
ds@1952
   127
** Trigger the alarm 
ds@1952
   128
*/
ds@1952
   129
static void sqlite3MemsysAlarm(int nByte){
ds@1952
   130
  void (*xCallback)(void*,sqlite3_int64,int);
ds@1952
   131
  sqlite3_int64 nowUsed;
ds@1952
   132
  void *pArg;
ds@1952
   133
  if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
ds@1952
   134
  mem.alarmBusy = 1;
ds@1952
   135
  xCallback = mem.alarmCallback;
ds@1952
   136
  nowUsed = mem.nowUsed;
ds@1952
   137
  pArg = mem.alarmArg;
ds@1952
   138
  sqlite3_mutex_leave(mem.mutex);
ds@1952
   139
  xCallback(pArg, nowUsed, nByte);
ds@1952
   140
  sqlite3_mutex_enter(mem.mutex);
ds@1952
   141
  mem.alarmBusy = 0;
ds@1952
   142
}
ds@1952
   143
ds@1952
   144
/*
ds@1952
   145
** Allocate nBytes of memory
ds@1952
   146
*/
ds@1952
   147
void *sqlite3_malloc(int nBytes){
ds@1952
   148
  sqlite3_int64 *p = 0;
ds@1952
   149
  if( nBytes>0 ){
ds@1952
   150
    enterMem();
ds@1952
   151
    if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
ds@1952
   152
      sqlite3MemsysAlarm(nBytes);
ds@1952
   153
    }
ds@1952
   154
    p = malloc(nBytes+8);
ds@1952
   155
    if( p==0 ){
ds@1952
   156
      sqlite3MemsysAlarm(nBytes);
ds@1952
   157
      p = malloc(nBytes+8);
ds@1952
   158
    }
ds@1952
   159
    if( p ){
ds@1952
   160
      p[0] = nBytes;
ds@1952
   161
      p++;
ds@1952
   162
      mem.nowUsed += nBytes;
ds@1952
   163
      if( mem.nowUsed>mem.mxUsed ){
ds@1952
   164
        mem.mxUsed = mem.nowUsed;
ds@1952
   165
      }
ds@1952
   166
    }
ds@1952
   167
    sqlite3_mutex_leave(mem.mutex);
ds@1952
   168
  }
ds@1952
   169
  return (void*)p; 
ds@1952
   170
}
ds@1952
   171
ds@1952
   172
/*
ds@1952
   173
** Free memory.
ds@1952
   174
*/
ds@1952
   175
void sqlite3_free(void *pPrior){
ds@1952
   176
  sqlite3_int64 *p;
ds@1952
   177
  int nByte;
ds@1952
   178
  if( pPrior==0 ){
ds@1952
   179
    return;
ds@1952
   180
  }
ds@1952
   181
  assert( mem.mutex!=0 );
ds@1952
   182
  p = pPrior;
ds@1952
   183
  p--;
ds@1952
   184
  nByte = (int)*p;
ds@1952
   185
  sqlite3_mutex_enter(mem.mutex);
ds@1952
   186
  mem.nowUsed -= nByte;
ds@1952
   187
  free(p);
ds@1952
   188
  sqlite3_mutex_leave(mem.mutex);  
ds@1952
   189
}
ds@1952
   190
ds@1952
   191
/*
ds@1952
   192
** Change the size of an existing memory allocation
ds@1952
   193
*/
ds@1952
   194
void *sqlite3_realloc(void *pPrior, int nBytes){
ds@1952
   195
  int nOld;
ds@1952
   196
  sqlite3_int64 *p;
ds@1952
   197
  if( pPrior==0 ){
ds@1952
   198
    return sqlite3_malloc(nBytes);
ds@1952
   199
  }
ds@1952
   200
  if( nBytes<=0 ){
ds@1952
   201
    sqlite3_free(pPrior);
ds@1952
   202
    return 0;
ds@1952
   203
  }
ds@1952
   204
  p = pPrior;
ds@1952
   205
  p--;
ds@1952
   206
  nOld = (int)p[0];
ds@1952
   207
  assert( mem.mutex!=0 );
ds@1952
   208
  sqlite3_mutex_enter(mem.mutex);
ds@1952
   209
  if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
ds@1952
   210
    sqlite3MemsysAlarm(nBytes-nOld);
ds@1952
   211
  }
ds@1952
   212
  p = realloc(p, nBytes+8);
ds@1952
   213
  if( p==0 ){
ds@1952
   214
    sqlite3MemsysAlarm(nBytes);
ds@1952
   215
    p = realloc(p, nBytes+8);
ds@1952
   216
  }
ds@1952
   217
  if( p ){
ds@1952
   218
    p[0] = nBytes;
ds@1952
   219
    p++;
ds@1952
   220
    mem.nowUsed += nBytes-nOld;
ds@1952
   221
    if( mem.nowUsed>mem.mxUsed ){
ds@1952
   222
      mem.mxUsed = mem.nowUsed;
ds@1952
   223
    }
ds@1952
   224
  }
ds@1952
   225
  sqlite3_mutex_leave(mem.mutex);
ds@1952
   226
  return (void*)p;
ds@1952
   227
}
ds@1952
   228
ds@1952
   229
#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */