engine/sqlite/src/mem4.cpp
changeset 97 3903521a36da
parent 96 87e863f6f840
child 98 5f9e7e14eb11
--- a/engine/sqlite/src/mem4.cpp	Wed May 26 10:44:32 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +0,0 @@
-/*
-** 2007 August 14
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.  
-**
-** $Id: mem4.cpp 1282 2008-11-13 09:31:33Z LarsPson $
-*/
-
-/*
-** This version of the memory allocator attempts to obtain memory
-** from mmap() if the size of the allocation is close to the size
-** of a virtual memory page.  If the size of the allocation is different
-** from the virtual memory page size, then ordinary malloc() is used.
-** Ordinary malloc is also used if space allocated to mmap() is
-** exhausted.
-**
-** Enable this memory allocation by compiling with -DSQLITE_MMAP_HEAP_SIZE=nnn
-** where nnn is the maximum number of bytes of mmap-ed memory you want 
-** to support.   This module may choose to use less memory than requested.
-**
-*/
-#if defined(SQLITE_MMAP_HEAP_SIZE)
-
-#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE)
-# error cannot use SQLITE_MMAP_HEAP_SIZE with either SQLITE_MEMDEBUG \
-        or SQLITE_MEMORY_SIZE
-#endif
-
-/*
-** This is a test version of the memory allocator that attempts to
-** use mmap() and madvise() for allocations and frees of approximately
-** the virtual memory page size.
-*/
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include "sqliteInt.h"
-#include <unistd.h>
-
-
-/*
-** All of the static variables used by this module are collected
-** into a single structure named "mem".  This is to keep the
-** static variables organized and to reduce namespace pollution
-** when this module is combined with other in the amalgamation.
-*/
-static struct {
-  /*
-  ** The alarm callback and its arguments.  The mem.mutex lock will
-  ** be held while the callback is running.  Recursive calls into
-  ** the memory subsystem are allowed, but no new callbacks will be
-  ** issued.  The alarmBusy variable is set to prevent recursive
-  ** callbacks.
-  */
-  sqlite3_int64 alarmThreshold;
-  void (*alarmCallback)(void*, sqlite3_int64,int);
-  void *alarmArg;
-  int alarmBusy;
-  
-  /*
-  ** Mutex to control access to the memory allocation subsystem.
-  */
-  sqlite3_mutex *mutex;
-  
-  /*
-  ** Current allocation and high-water mark.
-  */
-  sqlite3_int64 nowUsed;
-  sqlite3_int64 mxUsed;
-
-  /*
-  ** Current allocation and high-water marks for mmap allocated memory.
-  */
-  sqlite3_int64 nowUsedMMap;
-  sqlite3_int64 mxUsedMMap;
-
-  /*
-  ** Size of a single mmap page.  Obtained from sysconf().
-  */
-  int szPage;
-  int mnPage;
-
-  /*
-  ** The number of available mmap pages.
-  */
-  int nPage;
-
-  /*
-  ** Index of the first free page.  0 means no pages have been freed.
-  */
-  int firstFree;
-
-  /* First unused page on the top of the heap.
-  */
-  int firstUnused;
-
-  /*
-  ** Bulk memory obtained from from mmap().
-  */
-  char *mmapHeap;   /* first byte of the heap */ 
-
-} mem;
-
-
-/*
-** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
-** The mmap() region is initialized the first time this routine is called.
-*/
-static void memsys4Enter(void){
-  if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
-  }
-  sqlite3_mutex_enter(mem.mutex);
-}
-
-/*
-** Attempt to free memory to the mmap heap.  This only works if
-** the pointer p is within the range of memory addresses that
-** comprise the mmap heap.  Return 1 if the memory was freed
-** successfully.  Return 0 if the pointer is out of range.
-*/
-static int mmapFree(void *p){
-  char *z;
-  int idx, *a;
-  if( mem.mmapHeap==MAP_FAILED || mem.nPage==0 ){
-    return 0;
-  }
-  z = (char*)p;
-  idx = (z - mem.mmapHeap)/mem.szPage;
-  if( idx<1 || idx>=mem.nPage ){
-    return 0;
-  }
-  a = (int*)mem.mmapHeap;
-  a[idx] = a[mem.firstFree];
-  mem.firstFree = idx;
-  mem.nowUsedMMap -= mem.szPage;
-  madvise(p, mem.szPage, MADV_DONTNEED);
-  return 1;
-}
-
-/*
-** Attempt to allocate nBytes from the mmap heap.  Return a pointer
-** to the allocated page.  Or, return NULL if the allocation fails.
-** 
-** The allocation will fail if nBytes is not the right size.
-** Or, the allocation will fail if the mmap heap has been exhausted.
-*/
-static void *mmapAlloc(int nBytes){
-  int idx = 0;
-  if( nBytes>mem.szPage || nBytes<mem.mnPage ){
-    return 0;
-  }
-  if( mem.nPage==0 ){
-    mem.szPage = sysconf(_SC_PAGE_SIZE);
-    mem.mnPage = mem.szPage - mem.szPage/10;
-    mem.nPage = SQLITE_MMAP_HEAP_SIZE/mem.szPage;
-    if( mem.nPage * sizeof(int) > mem.szPage ){
-      mem.nPage = mem.szPage/sizeof(int);
-    }
-    mem.mmapHeap =  mmap(0, mem.szPage*mem.nPage, PROT_WRITE|PROT_READ,
-                         MAP_ANONYMOUS|MAP_SHARED, -1, 0);
-    if( mem.mmapHeap==MAP_FAILED ){
-      mem.firstUnused = errno;
-    }else{
-      mem.firstUnused = 1;
-      mem.nowUsedMMap = mem.szPage;
-    }
-  }
-  if( mem.mmapHeap==MAP_FAILED ){
-    return 0;
-  }
-  if( mem.firstFree ){
-    int idx = mem.firstFree;
-    int *a = (int*)mem.mmapHeap;
-    mem.firstFree = a[idx];
-  }else if( mem.firstUnused<mem.nPage ){
-    idx = mem.firstUnused++;
-  }
-  if( idx ){
-    mem.nowUsedMMap += mem.szPage;
-    if( mem.nowUsedMMap>mem.mxUsedMMap ){
-      mem.mxUsedMMap = mem.nowUsedMMap;
-    }
-    return (void*)&mem.mmapHeap[idx*mem.szPage];
-  }else{
-    return 0;
-  }
-}
-
-/*
-** Release the mmap-ed memory region if it is currently allocated and
-** is not in use.
-*/
-static void mmapUnmap(void){
-  if( mem.mmapHeap==MAP_FAILED ) return;
-  if( mem.nPage==0 ) return;
-  if( mem.nowUsedMMap>mem.szPage ) return;
-  munmap(mem.mmapHeap, mem.nPage*mem.szPage);
-  mem.nowUsedMMap = 0;
-  mem.nPage = 0;
-}
-    
-
-/*
-** Return the amount of memory currently checked out.
-*/
-sqlite3_int64 sqlite3_memory_used(void){
-  sqlite3_int64 n;
-  memsys4Enter();
-  n = mem.nowUsed + mem.nowUsedMMap;
-  sqlite3_mutex_leave(mem.mutex);  
-  return n;
-}
-
-/*
-** Return the maximum amount of memory that has ever been
-** checked out since either the beginning of this process
-** or since the most recent reset.
-*/
-sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
-  sqlite3_int64 n;
-  memsys4Enter();
-  n = mem.mxUsed + mem.mxUsedMMap;
-  if( resetFlag ){
-    mem.mxUsed = mem.nowUsed;
-    mem.mxUsedMMap = mem.nowUsedMMap;
-  }
-  sqlite3_mutex_leave(mem.mutex);  
-  return n;
-}
-
-/*
-** Change the alarm callback
-*/
-int sqlite3_memory_alarm(
-  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
-  void *pArg,
-  sqlite3_int64 iThreshold
-){
-  memsys4Enter();
-  mem.alarmCallback = xCallback;
-  mem.alarmArg = pArg;
-  mem.alarmThreshold = iThreshold;
-  sqlite3_mutex_leave(mem.mutex);
-  return SQLITE_OK;
-}
-
-/*
-** Trigger the alarm 
-*/
-static void sqlite3MemsysAlarm(int nByte){
-  void (*xCallback)(void*,sqlite3_int64,int);
-  sqlite3_int64 nowUsed;
-  void *pArg;
-  if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
-  mem.alarmBusy = 1;
-  xCallback = mem.alarmCallback;
-  nowUsed = mem.nowUsed;
-  pArg = mem.alarmArg;
-  sqlite3_mutex_leave(mem.mutex);
-  xCallback(pArg, nowUsed, nByte);
-  sqlite3_mutex_enter(mem.mutex);
-  mem.alarmBusy = 0;
-}
-
-/*
-** Allocate nBytes of memory
-*/
-static void *memsys4Malloc(int nBytes){
-  sqlite3_int64 *p = 0;
-  if( mem.alarmCallback!=0
-         && mem.nowUsed+mem.nowUsedMMap+nBytes>=mem.alarmThreshold ){
-    sqlite3MemsysAlarm(nBytes);
-  }
-  if( (p = mmapAlloc(nBytes))==0 ){
-    p = malloc(nBytes+8);
-    if( p==0 ){
-      sqlite3MemsysAlarm(nBytes);
-      p = malloc(nBytes+8);
-    }
-    if( p ){
-      p[0] = nBytes;
-      p++;
-      mem.nowUsed += nBytes;
-      if( mem.nowUsed>mem.mxUsed ){
-        mem.mxUsed = mem.nowUsed;
-      }
-    }
-  }
-  return (void*)p; 
-}
-
-/*
-** Return the size of a memory allocation
-*/
-static int memsys4Size(void *pPrior){
-  char *z = (char*)pPrior;
-  int idx = mem.nPage ? (z - mem.mmapHeap)/mem.szPage : 0;
-  int nByte;
-  if( idx>=1 && idx<mem.nPage ){
-    nByte = mem.szPage;
-  }else{
-    sqlite3_int64 *p = pPrior;
-    p--;
-    nByte = (int)*p;
-  }
-  return nByte;
-}
-
-/*
-** Free memory.
-*/
-static void memsys4Free(void *pPrior){
-  sqlite3_int64 *p;
-  int nByte;
-  if( mmapFree(pPrior)==0 ){
-    p = pPrior;
-    p--;
-    nByte = (int)*p;
-    mem.nowUsed -= nByte;
-    free(p);
-    if( mem.nowUsed==0 ){
-      mmapUnmap();
-    }      
-  }
-}
-
-/*
-** Allocate nBytes of memory
-*/
-void *sqlite3_malloc(int nBytes){
-  sqlite3_int64 *p = 0;
-  if( nBytes>0 ){
-    memsys4Enter();
-    p = memsys4Malloc(nBytes);
-    sqlite3_mutex_leave(mem.mutex);
-  }
-  return (void*)p; 
-}
-
-/*
-** Free memory.
-*/
-void sqlite3_free(void *pPrior){
-  if( pPrior==0 ){
-    return;
-  }
-  assert( mem.mutex!=0 );
-  sqlite3_mutex_enter(mem.mutex);
-  memsys4Free(pPrior);
-  sqlite3_mutex_leave(mem.mutex);  
-}
-
-
-
-/*
-** Change the size of an existing memory allocation
-*/
-void *sqlite3_realloc(void *pPrior, int nBytes){
-  int nOld;
-  sqlite3_int64 *p;
-  if( pPrior==0 ){
-    return sqlite3_malloc(nBytes);
-  }
-  if( nBytes<=0 ){
-    sqlite3_free(pPrior);
-    return 0;
-  }
-  nOld = memsys4Size(pPrior);
-  if( nBytes<=nOld && nBytes>=nOld-128 ){
-    return pPrior;
-  }
-  assert( mem.mutex!=0 );
-  sqlite3_mutex_enter(mem.mutex);
-  p = memsys4Malloc(nBytes);
-  if( p ){
-    if( nOld<nBytes ){
-      memcpy(p, pPrior, nOld);
-    }else{
-      memcpy(p, pPrior, nBytes);
-    }
-    memsys4Free(pPrior);
-  }
-  assert( mem.mutex!=0 );
-  sqlite3_mutex_leave(mem.mutex);
-  return (void*)p;
-}
-
-#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */