mem4.c.svn-base
上传用户:sunhongbo
上传日期:2022-01-25
资源大小:3010k
文件大小:9k
源码类别:

数据库系统

开发平台:

C/C++

  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: mem4.c,v 1.2 2008/02/14 23:26:56 drh Exp $
  16. */
  17. #include "sqliteInt.h"
  18. /*
  19. ** This version of the memory allocator attempts to obtain memory
  20. ** from mmap() if the size of the allocation is close to the size
  21. ** of a virtual memory page.  If the size of the allocation is different
  22. ** from the virtual memory page size, then ordinary malloc() is used.
  23. ** Ordinary malloc is also used if space allocated to mmap() is
  24. ** exhausted.
  25. **
  26. ** Enable this memory allocation by compiling with -DSQLITE_MMAP_HEAP_SIZE=nnn
  27. ** where nnn is the maximum number of bytes of mmap-ed memory you want 
  28. ** to support.   This module may choose to use less memory than requested.
  29. **
  30. */
  31. #ifdef SQLITE_MMAP_HEAP_SIZE
  32. /*
  33. ** This is a test version of the memory allocator that attempts to
  34. ** use mmap() and madvise() for allocations and frees of approximately
  35. ** the virtual memory page size.
  36. */
  37. #include <sys/types.h>
  38. #include <sys/mman.h>
  39. #include <errno.h>
  40. #include <unistd.h>
  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.   ** Current allocation and high-water marks for mmap allocated memory.
  72.   */
  73.   sqlite3_int64 nowUsedMMap;
  74.   sqlite3_int64 mxUsedMMap;
  75.   /*
  76.   ** Size of a single mmap page.  Obtained from sysconf().
  77.   */
  78.   int szPage;
  79.   int mnPage;
  80.   /*
  81.   ** The number of available mmap pages.
  82.   */
  83.   int nPage;
  84.   /*
  85.   ** Index of the first free page.  0 means no pages have been freed.
  86.   */
  87.   int firstFree;
  88.   /* First unused page on the top of the heap.
  89.   */
  90.   int firstUnused;
  91.   /*
  92.   ** Bulk memory obtained from from mmap().
  93.   */
  94.   char *mmapHeap;   /* first byte of the heap */ 
  95. } mem;
  96. /*
  97. ** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
  98. ** The mmap() region is initialized the first time this routine is called.
  99. */
  100. static void memsys4Enter(void){
  101.   if( mem.mutex==0 ){
  102.     mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
  103.   }
  104.   sqlite3_mutex_enter(mem.mutex);
  105. }
  106. /*
  107. ** Attempt to free memory to the mmap heap.  This only works if
  108. ** the pointer p is within the range of memory addresses that
  109. ** comprise the mmap heap.  Return 1 if the memory was freed
  110. ** successfully.  Return 0 if the pointer is out of range.
  111. */
  112. static int mmapFree(void *p){
  113.   char *z;
  114.   int idx, *a;
  115.   if( mem.mmapHeap==MAP_FAILED || mem.nPage==0 ){
  116.     return 0;
  117.   }
  118.   z = (char*)p;
  119.   idx = (z - mem.mmapHeap)/mem.szPage;
  120.   if( idx<1 || idx>=mem.nPage ){
  121.     return 0;
  122.   }
  123.   a = (int*)mem.mmapHeap;
  124.   a[idx] = a[mem.firstFree];
  125.   mem.firstFree = idx;
  126.   mem.nowUsedMMap -= mem.szPage;
  127.   madvise(p, mem.szPage, MADV_DONTNEED);
  128.   return 1;
  129. }
  130. /*
  131. ** Attempt to allocate nBytes from the mmap heap.  Return a pointer
  132. ** to the allocated page.  Or, return NULL if the allocation fails.
  133. ** 
  134. ** The allocation will fail if nBytes is not the right size.
  135. ** Or, the allocation will fail if the mmap heap has been exhausted.
  136. */
  137. static void *mmapAlloc(int nBytes){
  138.   int idx = 0;
  139.   if( nBytes>mem.szPage || nBytes<mem.mnPage ){
  140.     return 0;
  141.   }
  142.   if( mem.nPage==0 ){
  143.     mem.szPage = sysconf(_SC_PAGE_SIZE);
  144.     mem.mnPage = mem.szPage - mem.szPage/10;
  145.     mem.nPage = SQLITE_MMAP_HEAP_SIZE/mem.szPage;
  146.     if( mem.nPage * sizeof(int) > mem.szPage ){
  147.       mem.nPage = mem.szPage/sizeof(int);
  148.     }
  149.     mem.mmapHeap =  mmap(0, mem.szPage*mem.nPage, PROT_WRITE|PROT_READ,
  150.                          MAP_ANONYMOUS|MAP_SHARED, -1, 0);
  151.     if( mem.mmapHeap==MAP_FAILED ){
  152.       mem.firstUnused = errno;
  153.     }else{
  154.       mem.firstUnused = 1;
  155.       mem.nowUsedMMap = mem.szPage;
  156.     }
  157.   }
  158.   if( mem.mmapHeap==MAP_FAILED ){
  159.     return 0;
  160.   }
  161.   if( mem.firstFree ){
  162.     int idx = mem.firstFree;
  163.     int *a = (int*)mem.mmapHeap;
  164.     mem.firstFree = a[idx];
  165.   }else if( mem.firstUnused<mem.nPage ){
  166.     idx = mem.firstUnused++;
  167.   }
  168.   if( idx ){
  169.     mem.nowUsedMMap += mem.szPage;
  170.     if( mem.nowUsedMMap>mem.mxUsedMMap ){
  171.       mem.mxUsedMMap = mem.nowUsedMMap;
  172.     }
  173.     return (void*)&mem.mmapHeap[idx*mem.szPage];
  174.   }else{
  175.     return 0;
  176.   }
  177. }
  178. /*
  179. ** Release the mmap-ed memory region if it is currently allocated and
  180. ** is not in use.
  181. */
  182. static void mmapUnmap(void){
  183.   if( mem.mmapHeap==MAP_FAILED ) return;
  184.   if( mem.nPage==0 ) return;
  185.   if( mem.nowUsedMMap>mem.szPage ) return;
  186.   munmap(mem.mmapHeap, mem.nPage*mem.szPage);
  187.   mem.nowUsedMMap = 0;
  188.   mem.nPage = 0;
  189. }
  190.     
  191. /*
  192. ** Return the amount of memory currently checked out.
  193. */
  194. sqlite3_int64 sqlite3_memory_used(void){
  195.   sqlite3_int64 n;
  196.   memsys4Enter();
  197.   n = mem.nowUsed + mem.nowUsedMMap;
  198.   sqlite3_mutex_leave(mem.mutex);  
  199.   return n;
  200. }
  201. /*
  202. ** Return the maximum amount of memory that has ever been
  203. ** checked out since either the beginning of this process
  204. ** or since the most recent reset.
  205. */
  206. sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
  207.   sqlite3_int64 n;
  208.   memsys4Enter();
  209.   n = mem.mxUsed + mem.mxUsedMMap;
  210.   if( resetFlag ){
  211.     mem.mxUsed = mem.nowUsed;
  212.     mem.mxUsedMMap = mem.nowUsedMMap;
  213.   }
  214.   sqlite3_mutex_leave(mem.mutex);  
  215.   return n;
  216. }
  217. /*
  218. ** Change the alarm callback
  219. */
  220. int sqlite3_memory_alarm(
  221.   void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
  222.   void *pArg,
  223.   sqlite3_int64 iThreshold
  224. ){
  225.   memsys4Enter();
  226.   mem.alarmCallback = xCallback;
  227.   mem.alarmArg = pArg;
  228.   mem.alarmThreshold = iThreshold;
  229.   sqlite3_mutex_leave(mem.mutex);
  230.   return SQLITE_OK;
  231. }
  232. /*
  233. ** Trigger the alarm 
  234. */
  235. static void sqlite3MemsysAlarm(int nByte){
  236.   void (*xCallback)(void*,sqlite3_int64,int);
  237.   sqlite3_int64 nowUsed;
  238.   void *pArg;
  239.   if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
  240.   mem.alarmBusy = 1;
  241.   xCallback = mem.alarmCallback;
  242.   nowUsed = mem.nowUsed;
  243.   pArg = mem.alarmArg;
  244.   sqlite3_mutex_leave(mem.mutex);
  245.   xCallback(pArg, nowUsed, nByte);
  246.   sqlite3_mutex_enter(mem.mutex);
  247.   mem.alarmBusy = 0;
  248. }
  249. /*
  250. ** Allocate nBytes of memory
  251. */
  252. static void *memsys4Malloc(int nBytes){
  253.   sqlite3_int64 *p = 0;
  254.   if( mem.alarmCallback!=0
  255.          && mem.nowUsed+mem.nowUsedMMap+nBytes>=mem.alarmThreshold ){
  256.     sqlite3MemsysAlarm(nBytes);
  257.   }
  258.   if( (p = mmapAlloc(nBytes))==0 ){
  259.     p = malloc(nBytes+8);
  260.     if( p==0 ){
  261.       sqlite3MemsysAlarm(nBytes);
  262.       p = malloc(nBytes+8);
  263.     }
  264.     if( p ){
  265.       p[0] = nBytes;
  266.       p++;
  267.       mem.nowUsed += nBytes;
  268.       if( mem.nowUsed>mem.mxUsed ){
  269.         mem.mxUsed = mem.nowUsed;
  270.       }
  271.     }
  272.   }
  273.   return (void*)p; 
  274. }
  275. /*
  276. ** Return the size of a memory allocation
  277. */
  278. static int memsys4Size(void *pPrior){
  279.   char *z = (char*)pPrior;
  280.   int idx = mem.nPage ? (z - mem.mmapHeap)/mem.szPage : 0;
  281.   int nByte;
  282.   if( idx>=1 && idx<mem.nPage ){
  283.     nByte = mem.szPage;
  284.   }else{
  285.     sqlite3_int64 *p = pPrior;
  286.     p--;
  287.     nByte = (int)*p;
  288.   }
  289.   return nByte;
  290. }
  291. /*
  292. ** Free memory.
  293. */
  294. static void memsys4Free(void *pPrior){
  295.   sqlite3_int64 *p;
  296.   int nByte;
  297.   if( mmapFree(pPrior)==0 ){
  298.     p = pPrior;
  299.     p--;
  300.     nByte = (int)*p;
  301.     mem.nowUsed -= nByte;
  302.     free(p);
  303.     if( mem.nowUsed==0 ){
  304.       mmapUnmap();
  305.     }      
  306.   }
  307. }
  308. /*
  309. ** Allocate nBytes of memory
  310. */
  311. void *sqlite3_malloc(int nBytes){
  312.   sqlite3_int64 *p = 0;
  313.   if( nBytes>0 ){
  314.     memsys4Enter();
  315.     p = memsys4Malloc(nBytes);
  316.     sqlite3_mutex_leave(mem.mutex);
  317.   }
  318.   return (void*)p; 
  319. }
  320. /*
  321. ** Free memory.
  322. */
  323. void sqlite3_free(void *pPrior){
  324.   if( pPrior==0 ){
  325.     return;
  326.   }
  327.   assert( mem.mutex!=0 );
  328.   sqlite3_mutex_enter(mem.mutex);
  329.   memsys4Free(pPrior);
  330.   sqlite3_mutex_leave(mem.mutex);  
  331. }
  332. /*
  333. ** Change the size of an existing memory allocation
  334. */
  335. void *sqlite3_realloc(void *pPrior, int nBytes){
  336.   int nOld;
  337.   sqlite3_int64 *p;
  338.   if( pPrior==0 ){
  339.     return sqlite3_malloc(nBytes);
  340.   }
  341.   if( nBytes<=0 ){
  342.     sqlite3_free(pPrior);
  343.     return 0;
  344.   }
  345.   nOld = memsys4Size(pPrior);
  346.   if( nBytes<=nOld && nBytes>=nOld-128 ){
  347.     return pPrior;
  348.   }
  349.   assert( mem.mutex!=0 );
  350.   sqlite3_mutex_enter(mem.mutex);
  351.   p = memsys4Malloc(nBytes);
  352.   if( p ){
  353.     if( nOld<nBytes ){
  354.       memcpy(p, pPrior, nOld);
  355.     }else{
  356.       memcpy(p, pPrior, nBytes);
  357.     }
  358.     memsys4Free(pPrior);
  359.   }
  360.   assert( mem.mutex!=0 );
  361.   sqlite3_mutex_leave(mem.mutex);
  362.   return (void*)p;
  363. }
  364. #endif /* SQLITE_MMAP_HEAP_SIZE */