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