engine/sqlite/src/mem1.cpp
changeset 2 29cda98b007e
equal deleted inserted replaced
1:5f8e5adbbed9 2:29cda98b007e
       
     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: mem1.cpp 1282 2008-11-13 09:31:33Z LarsPson $
       
    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_MEMORY_SIZE) \
       
    24      && !defined(SQLITE_MMAP_HEAP_SIZE)
       
    25 
       
    26 /*
       
    27 ** We will eventually construct multiple memory allocation subsystems
       
    28 ** suitable for use in various contexts:
       
    29 **
       
    30 **    *  Normal multi-threaded builds
       
    31 **    *  Normal single-threaded builds
       
    32 **    *  Debugging builds
       
    33 **
       
    34 ** This initial version is suitable for use in normal multi-threaded
       
    35 ** builds.  We envision that alternative versions will be stored in
       
    36 ** separate source files.  #ifdefs will be used to select the code from
       
    37 ** one of the various memN.c source files for use in any given build.
       
    38 */
       
    39 #include "sqliteInt.h"
       
    40 
       
    41 /*
       
    42 ** All of the static variables used by this module are collected
       
    43 ** into a single structure named "mem".  This is to keep the
       
    44 ** static variables organized and to reduce namespace pollution
       
    45 ** when this module is combined with other in the amalgamation.
       
    46 */
       
    47 static struct {
       
    48   /*
       
    49   ** The alarm callback and its arguments.  The mem.mutex lock will
       
    50   ** be held while the callback is running.  Recursive calls into
       
    51   ** the memory subsystem are allowed, but no new callbacks will be
       
    52   ** issued.  The alarmBusy variable is set to prevent recursive
       
    53   ** callbacks.
       
    54   */
       
    55   sqlite3_int64 alarmThreshold;
       
    56   void (*alarmCallback)(void*, sqlite3_int64,int);
       
    57   void *alarmArg;
       
    58   int alarmBusy;
       
    59   
       
    60   /*
       
    61   ** Mutex to control access to the memory allocation subsystem.
       
    62   */
       
    63   sqlite3_mutex *mutex;
       
    64   
       
    65   /*
       
    66   ** Current allocation and high-water mark.
       
    67   */
       
    68   sqlite3_int64 nowUsed;
       
    69   sqlite3_int64 mxUsed;
       
    70   
       
    71  
       
    72 } mem;
       
    73 
       
    74 /*
       
    75 ** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
       
    76 */
       
    77 static void enterMem(void){
       
    78   if( mem.mutex==0 ){
       
    79     mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
       
    80   }
       
    81   sqlite3_mutex_enter(mem.mutex);
       
    82 }
       
    83 
       
    84 /*
       
    85 ** Return the amount of memory currently checked out.
       
    86 */
       
    87 EXPORT_C sqlite3_int64 sqlite3_memory_used(void){
       
    88   sqlite3_int64 n;
       
    89   enterMem();
       
    90   n = mem.nowUsed;
       
    91   sqlite3_mutex_leave(mem.mutex);  
       
    92   return n;
       
    93 }
       
    94 
       
    95 /*
       
    96 ** Return the maximum amount of memory that has ever been
       
    97 ** checked out since either the beginning of this process
       
    98 ** or since the most recent reset.
       
    99 */
       
   100 EXPORT_C sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
       
   101   sqlite3_int64 n;
       
   102   enterMem();
       
   103   n = mem.mxUsed;
       
   104   if( resetFlag ){
       
   105     mem.mxUsed = mem.nowUsed;
       
   106   }
       
   107   sqlite3_mutex_leave(mem.mutex);  
       
   108   return n;
       
   109 }
       
   110 
       
   111 /*
       
   112 ** Change the alarm callback
       
   113 */
       
   114 EXPORT_C int sqlite3_memory_alarm(
       
   115   void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
       
   116   void *pArg,
       
   117   sqlite3_int64 iThreshold
       
   118 ){
       
   119   enterMem();
       
   120   mem.alarmCallback = xCallback;
       
   121   mem.alarmArg = pArg;
       
   122   mem.alarmThreshold = iThreshold;
       
   123   sqlite3_mutex_leave(mem.mutex);
       
   124   return SQLITE_OK;
       
   125 }
       
   126 
       
   127 /*
       
   128 ** Trigger the alarm 
       
   129 */
       
   130 static void sqlite3MemsysAlarm(int nByte){
       
   131   void (*xCallback)(void*,sqlite3_int64,int);
       
   132   sqlite3_int64 nowUsed;
       
   133   void *pArg;
       
   134   if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
       
   135   mem.alarmBusy = 1;
       
   136   xCallback = mem.alarmCallback;
       
   137   nowUsed = mem.nowUsed;
       
   138   pArg = mem.alarmArg;
       
   139   sqlite3_mutex_leave(mem.mutex);
       
   140   xCallback(pArg, nowUsed, nByte);
       
   141   sqlite3_mutex_enter(mem.mutex);
       
   142   mem.alarmBusy = 0;
       
   143 }
       
   144 
       
   145 /*
       
   146 ** Allocate nBytes of memory
       
   147 */
       
   148 EXPORT_C void *sqlite3_malloc(int nBytes){
       
   149   sqlite3_int64 *p = 0;
       
   150   if( nBytes>0 ){
       
   151     enterMem();
       
   152     if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
       
   153       sqlite3MemsysAlarm(nBytes);
       
   154     }
       
   155 	p = (sqlite3_int64*)malloc(nBytes+8);
       
   156     if( p==0 ){
       
   157       sqlite3MemsysAlarm(nBytes);
       
   158 	  p = (sqlite3_int64*)malloc(nBytes+8);
       
   159     }
       
   160     if( p ){
       
   161       p[0] = nBytes;
       
   162       p++;
       
   163       mem.nowUsed += nBytes;
       
   164       if( mem.nowUsed>mem.mxUsed ){
       
   165         mem.mxUsed = mem.nowUsed;
       
   166       }
       
   167     }
       
   168     sqlite3_mutex_leave(mem.mutex);
       
   169   }
       
   170   return (void*)p; 
       
   171 }
       
   172 
       
   173 /*
       
   174 ** Free memory.
       
   175 */
       
   176 EXPORT_C void sqlite3_free(void *pPrior){
       
   177   sqlite3_int64 *p;
       
   178   int nByte;
       
   179   if( pPrior==0 ){
       
   180     return;
       
   181   }
       
   182   assert( mem.mutex!=0 );
       
   183   p = (sqlite3_int64*)pPrior;
       
   184   p--;
       
   185   nByte = (int)*p;
       
   186   sqlite3_mutex_enter(mem.mutex);
       
   187   mem.nowUsed -= nByte;
       
   188   free(p);
       
   189   sqlite3_mutex_leave(mem.mutex);  
       
   190 }
       
   191 
       
   192 /*
       
   193 ** Change the size of an existing memory allocation
       
   194 */
       
   195 EXPORT_C void *sqlite3_realloc(void *pPrior, int nBytes){
       
   196   int nOld;
       
   197   sqlite3_int64 *p;
       
   198   if( pPrior==0 ){
       
   199     return sqlite3_malloc(nBytes);
       
   200   }
       
   201   if( nBytes<=0 ){
       
   202     sqlite3_free(pPrior);
       
   203     return 0;
       
   204   }
       
   205   p = (sqlite3_int64*)pPrior;
       
   206   p--;
       
   207   nOld = (int)p[0];
       
   208   assert( mem.mutex!=0 );
       
   209   sqlite3_mutex_enter(mem.mutex);
       
   210   if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
       
   211     sqlite3MemsysAlarm(nBytes-nOld);
       
   212   }
       
   213   p = (sqlite3_int64*)realloc(p, nBytes+8);
       
   214   if( p==0 ){
       
   215     sqlite3MemsysAlarm(nBytes);
       
   216 	p = (sqlite3_int64*)pPrior;
       
   217     p--;
       
   218 	p = (sqlite3_int64*)realloc(p, nBytes+8);
       
   219   }
       
   220   if( p ){
       
   221     p[0] = nBytes;
       
   222     p++;
       
   223     mem.nowUsed += nBytes-nOld;
       
   224     if( mem.nowUsed>mem.mxUsed ){
       
   225       mem.mxUsed = mem.nowUsed;
       
   226     }
       
   227   }
       
   228   sqlite3_mutex_leave(mem.mutex);
       
   229   return (void*)p;
       
   230 }
       
   231 
       
   232 #endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */