From d1370b6d92b40f546a78ff934178a320d57b55f6 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 28 Oct 2008 18:58:20 +0000 Subject: [PATCH] Remove the vestigial mem4 and mem6 memory allocators. Add the SQLITE_ZERO_MALLOC compile-time option and the mem0.c module to handle memory allocation for that case. (CVS 5848) FossilOrigin-Name: 4651f590f0b8bf13938b2b15d5082136e763af8d --- Makefile.in | 14 +- main.mk | 5 +- manifest | 27 ++- manifest.uuid | 2 +- src/mem0.c | 61 ++++++ src/mem1.c | 22 +- src/mem2.c | 19 +- src/mem4.c | 393 ---------------------------------- src/mem5.c | 26 +-- src/mem6.c | 498 -------------------------------------------- src/sqliteInt.h | 6 +- tool/mksqlite3c.tcl | 2 +- 12 files changed, 103 insertions(+), 972 deletions(-) create mode 100644 src/mem0.c delete mode 100644 src/mem4.c delete mode 100644 src/mem6.c diff --git a/Makefile.in b/Makefile.in index 2e8e0efb93..236bd4324b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -163,7 +163,7 @@ OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \ btree.lo build.lo callback.lo complete.lo date.lo \ delete.lo expr.lo fault.lo func.lo global.lo \ hash.lo journal.lo insert.lo legacy.lo loadext.lo \ - main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mem5.lo mem6.lo \ + main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.o \ mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \ opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ @@ -214,12 +214,11 @@ SRC = \ $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ $(TOP)/src/malloc.c \ + $(TOP)/src/mem0.c \ $(TOP)/src/mem1.c \ $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ - $(TOP)/src/mem4.c \ $(TOP)/src/mem5.c \ - $(TOP)/src/mem6.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ @@ -558,6 +557,9 @@ main.lo: $(TOP)/src/main.c $(HDR) malloc.lo: $(TOP)/src/malloc.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c +mem0.lo: $(TOP)/src/mem0.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem0.c + mem1.lo: $(TOP)/src/mem1.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c @@ -567,15 +569,9 @@ mem2.lo: $(TOP)/src/mem2.c $(HDR) mem3.lo: $(TOP)/src/mem3.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c -mem4.lo: $(TOP)/src/mem4.c $(HDR) - $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem4.c - mem5.lo: $(TOP)/src/mem5.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c -mem6.lo: $(TOP)/src/mem6.c $(HDR) - $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem6.c - memjournal.lo: $(TOP)/src/memjournal.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/memjournal.c diff --git a/main.mk b/main.mk index ee8d2d0064..cfd24468d6 100644 --- a/main.mk +++ b/main.mk @@ -56,7 +56,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \ fts3_tokenizer.o fts3_tokenizer1.o \ func.o global.o hash.o \ icu.o insert.o journal.o legacy.o loadext.o \ - main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \ + main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memjournal.o \ mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \ opcodes.o os.o os_os2.o os_unix.o os_win.o \ @@ -99,12 +99,11 @@ SRC = \ $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ $(TOP)/src/malloc.c \ + $(TOP)/src/mem0.c \ $(TOP)/src/mem1.c \ $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ - $(TOP)/src/mem4.c \ $(TOP)/src/mem5.c \ - $(TOP)/src/mem6.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/mutex.c \ $(TOP)/src/mutex.h \ diff --git a/manifest b/manifest index 55c6485881..48de859349 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Add\sdata\sstructure\sdescription\scomments\sto\smemjournal.c.\s(CVS\s5847) -D 2008-10-28T18:12:36 +C Remove\sthe\svestigial\smem4\sand\smem6\smemory\sallocators.\s\sAdd\sthe\nSQLITE_ZERO_MALLOC\scompile-time\soption\sand\sthe\smem0.c\smodule\sto\nhandle\smemory\sallocation\sfor\sthat\scase.\s(CVS\s5848) +D 2008-10-28T18:58:20 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 -F Makefile.in 3fe17eccd87d385b5adc9766828716cfdd154d6b +F Makefile.in da817da72422f9b876602c225fcd17d6ca4182f7 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F README b974cdc3f9f12b87e851b04e75996d720ebf81ac F VERSION 5ba795c6239d62450dd2cb8b469acebda412ebc9 @@ -79,7 +79,7 @@ F ext/rtree/tkt3363.test 6662237ea75bb431cd5d262dfc9535e1023315fc F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210 -F main.mk c0baa7e57584ce3666a854015ad8743c5fe38dec +F main.mk 187bbff650073ffad5e8313795665ea64f36c0d5 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -120,12 +120,11 @@ F src/legacy.c aac57bd984e666059011ea01ec4383892a253be3 F src/loadext.c 3872457afdf25bb174fd383cb4e3e0d2a9e60552 F src/main.c ff40f9f21c76d5062bc0bc06bd8853fc217dd170 F src/malloc.c a213fb461b8df08aed7606f6a1e1d3452e089000 -F src/mem1.c 5a529ff121c55ab067be14de00f86f6dcc4f4fb9 -F src/mem2.c f87e681d0d1ed8436870d089332ed0d27d885b5c +F src/mem0.c f2f84062d1f35814d6535c9f9e33de3bfb3b132c +F src/mem1.c 2091081d1c6bcd4516738f37cd84d42e814cf9a2 +F src/mem2.c 5d9968f576ba1babc787adbfb613cf428ab484ec F src/mem3.c 1594f117fde4cf11a6c16521f3f30af8d04bbe68 -F src/mem4.c 6703adb1717b26d9d70a1c2586b4b7b7ffee7909 -F src/mem5.c 706d462c13a9819dfec7c10d9dccedf8d199960c -F src/mem6.c febe4db9ddef73df500989e68a9d4ac68602a075 +F src/mem5.c 8cb9dfacf7e11a7822b4935757ae0c1749278b4e F src/memjournal.c 7ffe4ebf5e7792571c27d528ca005e495343d1c4 F src/mutex.c e9cb5fbe94afb4328869afaf3ac49bd1327559eb F src/mutex.h 9e686e83a88838dac8b9c51271c651e833060f1e @@ -153,7 +152,7 @@ F src/select.c d910d7350df0d918e22286c5bfd39d4ea68ec813 F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967 F src/sqlite.h.in ee95eeed2196e5fa98fdad007301b8d5d3733b6d F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 -F src/sqliteInt.h 0525efef6ba2b58a6e7a4a9353b496143147e288 +F src/sqliteInt.h 926279c94cdf21e53fc66badb8541d94aed25018 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8 @@ -637,7 +636,7 @@ F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf F tool/mkkeywordhash.c c219ee2b8b5b8e7011cccfa1caec62d9812e82e7 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 -F tool/mksqlite3c.tcl ab98a8321f292b4871e362bb4435be234993d46b +F tool/mksqlite3c.tcl f27bd970d5963cc4c6fb421d8553a2c439e61b9b F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87 F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c @@ -652,7 +651,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 679c0b35aaa1ea488a205cc03802e7078a2bcf29 -R 8c08739effdbffeefaabe6ecfcdcebaf +P e9c2adbcbf5c28837b06e0fbba93f1764cc3607f +R f7bf0b80936d7235124831741a662cca U drh -Z 35d81495d6d4eb3c73d75e648d0cc22a +Z dd0198037f61ae7a01ce16dbaae2a0df diff --git a/manifest.uuid b/manifest.uuid index ecefa85ba3..6008ce9f79 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e9c2adbcbf5c28837b06e0fbba93f1764cc3607f \ No newline at end of file +4651f590f0b8bf13938b2b15d5082136e763af8d \ No newline at end of file diff --git a/src/mem0.c b/src/mem0.c new file mode 100644 index 0000000000..0cac07bc80 --- /dev/null +++ b/src/mem0.c @@ -0,0 +1,61 @@ +/* +** 2008 October 28 +** +** 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 a no-op memory allocation drivers for use when +** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented +** here always fail. SQLite will not operate with these drivers. These +** are merely placeholders. Real drivers must be substituted using +** sqlite3_config() before SQLite will operate. +** +** $Id: mem0.c,v 1.1 2008/10/28 18:58:20 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** This version of the memory allocator is the default. It is +** used when no other memory allocator is specified using compile-time +** macros. +*/ +#ifdef SQLITE_ZERO_MALLOC + +/* +** No-op versions of all memory allocation routines +*/ +static void *sqlite3MemMalloc(int nByte){ return 0; } +static void sqlite3MemFree(void *pPrior){ return; } +static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; } +static int sqlite3MemSize(void *pPrior){ return 0; } +static int sqlite3MemRoundup(int n){ return n; } +static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; } +static void sqlite3MemShutdown(void *NotUsed){ return; } + +/* +** This routine is the only routine in this file with external linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. +*/ +void sqlite3MemSetDefault(void){ + static const sqlite3_mem_methods defaultMethods = { + sqlite3MemMalloc, + sqlite3MemFree, + sqlite3MemRealloc, + sqlite3MemSize, + sqlite3MemRoundup, + sqlite3MemInit, + sqlite3MemShutdown, + 0 + }; + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); +} + +#endif /* SQLITE_ZERO_MALLOC */ diff --git a/src/mem1.c b/src/mem1.c index 5f8dcea775..d85a39000a 100644 --- a/src/mem1.c +++ b/src/mem1.c @@ -17,7 +17,7 @@ ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. ** -** $Id: mem1.c,v 1.26 2008/09/01 18:34:20 danielk1977 Exp $ +** $Id: mem1.c,v 1.27 2008/10/28 18:58:20 drh Exp $ */ #include "sqliteInt.h" @@ -120,7 +120,13 @@ static void sqlite3MemShutdown(void *NotUsed){ return; } -const sqlite3_mem_methods *sqlite3MemGetDefault(void){ +/* +** This routine is the only routine in this file with external linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. +*/ +void sqlite3MemSetDefault(void){ static const sqlite3_mem_methods defaultMethods = { sqlite3MemMalloc, sqlite3MemFree, @@ -131,17 +137,7 @@ const sqlite3_mem_methods *sqlite3MemGetDefault(void){ sqlite3MemShutdown, 0 }; - return &defaultMethods; -} - -/* -** This routine is the only routine in this file with external linkage. -** -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. -*/ -void sqlite3MemSetDefault(void){ - sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault()); + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } #endif /* SQLITE_SYSTEM_MALLOC */ diff --git a/src/mem2.c b/src/mem2.c index 80fd387bd3..1fce769bf0 100644 --- a/src/mem2.c +++ b/src/mem2.c @@ -19,7 +19,7 @@ ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. ** -** $Id: mem2.c,v 1.39 2008/09/01 18:34:20 danielk1977 Exp $ +** $Id: mem2.c,v 1.40 2008/10/28 18:58:20 drh Exp $ */ #include "sqliteInt.h" @@ -323,8 +323,11 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){ return pNew; } - -const sqlite3_mem_methods *sqlite3MemGetDefault(void){ +/* +** Populate the low-level memory allocation function pointers in +** sqlite3GlobalConfig.m with pointers to the routines in this file. +*/ +void sqlite3MemSetDefault(void){ static const sqlite3_mem_methods defaultMethods = { sqlite3MemMalloc, sqlite3MemFree, @@ -335,15 +338,7 @@ const sqlite3_mem_methods *sqlite3MemGetDefault(void){ sqlite3MemShutdown, 0 }; - return &defaultMethods; -} - -/* -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. -*/ -void sqlite3MemSetDefault(void){ - sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault()); + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } /* diff --git a/src/mem4.c b/src/mem4.c deleted file mode 100644 index 5a78098561..0000000000 --- a/src/mem4.c +++ /dev/null @@ -1,393 +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.c,v 1.3 2008/06/18 17:09:10 danielk1977 Exp $ -*/ -#include "sqliteInt.h" - -/* -** 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. -** -*/ -#ifdef SQLITE_MMAP_HEAP_SIZE - -/* -** 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 -#include -#include -#include - - -/* -** 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 = sqlite3MutexAlloc(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.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.firstUnusedmem.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 && idx0 ){ - 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( nOldzPool[(idx)*pChunk->nAtom])) - -static SQLITE_WSD struct Mem6Global { - int nMinAlloc; /* Minimum allowed allocation size */ - int nThreshold; /* Allocs larger than this go to malloc() */ - int nLogThreshold; /* log2 of (nThreshold/nMinAlloc) */ - sqlite3_mutex *mutex; - Mem6Chunk *pChunk; /* Singly linked list of all memory chunks */ -} mem6 = { 48642791 }; - -#define mem6 GLOBAL(struct Mem6Global, mem6) - -/* -** Unlink the chunk at pChunk->aPool[i] from list it is currently -** on. It should be found on pChunk->aiFreelist[iLogsize]. -*/ -static void memsys6Unlink(Mem6Chunk *pChunk, int i, int iLogsize){ - int next, prev; - assert( i>=0 && inBlock ); - assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold ); - assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); - - next = MEM6LINK(i)->next; - prev = MEM6LINK(i)->prev; - if( prev<0 ){ - pChunk->aiFreelist[iLogsize] = next; - }else{ - MEM6LINK(prev)->next = next; - } - if( next>=0 ){ - MEM6LINK(next)->prev = prev; - } -} - -/* -** Link the chunk at mem5.aPool[i] so that is on the iLogsize -** free list. -*/ -static void memsys6Link(Mem6Chunk *pChunk, int i, int iLogsize){ - int x; - assert( i>=0 && inBlock ); - assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold ); - assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); - - x = MEM6LINK(i)->next = pChunk->aiFreelist[iLogsize]; - MEM6LINK(i)->prev = -1; - if( x>=0 ){ - assert( xnBlock ); - MEM6LINK(x)->prev = i; - } - pChunk->aiFreelist[iLogsize] = i; -} - - -/* -** Find the first entry on the freelist iLogsize. Unlink that -** entry and return its index. -*/ -static int memsys6UnlinkFirst(Mem6Chunk *pChunk, int iLogsize){ - int i; - int iFirst; - - assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold ); - i = iFirst = pChunk->aiFreelist[iLogsize]; - assert( iFirst>=0 ); - memsys6Unlink(pChunk, iFirst, iLogsize); - return iFirst; -} - -static int roundupLog2(int n){ - static const char LogTable256[256] = { - 0, /* 1 */ - 1, /* 2 */ - 2, 2, /* 3..4 */ - 3, 3, 3, 3, /* 5..8 */ - 4, 4, 4, 4, 4, 4, 4, 4, /* 9..16 */ - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* 17..32 */ - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, /* 33..64 */ - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* 65..128 */ - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* 129..256 */ - }; - - assert(n<=(1<<16) && n>0); - if( n<=256 ) return LogTable256[n-1]; - return LogTable256[(n>>8) - ((n&0xFF)?0:1)] + 8; -} - -/* -** Allocate and return a block of (pChunk->nAtom << iLogsize) bytes from chunk -** pChunk. If the allocation request cannot be satisfied, return 0. -*/ -static void *chunkMalloc(Mem6Chunk *pChunk, int iLogsize){ - int i; /* Index of a mem5.aPool[] slot */ - int iBin; /* Index into mem5.aiFreelist[] */ - - /* Make sure mem5.aiFreelist[iLogsize] contains at least one free - ** block. If not, then split a block of the next larger power of - ** two in order to create a new free block of size iLogsize. - */ - for(iBin=iLogsize; pChunk->aiFreelist[iBin]<0 && iBin<=mem6.nLogThreshold; iBin++){} - if( iBin>mem6.nLogThreshold ) return 0; - i = memsys6UnlinkFirst(pChunk, iBin); - while( iBin>iLogsize ){ - int newSize; - iBin--; - newSize = 1 << iBin; - pChunk->aCtrl[i+newSize] = CTRL_FREE | iBin; - memsys6Link(pChunk, i+newSize, iBin); - } - pChunk->aCtrl[i] = iLogsize; - - /* Return a pointer to the allocated memory. */ - pChunk->nCheckedOut++; - return (void*)&pChunk->zPool[i*pChunk->nAtom]; -} - -/* -** Free the allocation pointed to by p, which is guaranteed to be non-zero -** and a part of chunk object pChunk. -*/ -static void chunkFree(Mem6Chunk *pChunk, void *pOld){ - u32 size, iLogsize; - int iBlock; - - /* Set iBlock to the index of the block pointed to by pOld in - ** the array of pChunk->nAtom byte blocks pointed to by pChunk->zPool. - */ - iBlock = ((u8 *)pOld-pChunk->zPool)/pChunk->nAtom; - - /* Check that the pointer pOld points to a valid, non-free block. */ - assert( iBlock>=0 && iBlocknBlock ); - assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 ); - assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 ); - - iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE; - size = 1<nBlock ); - - pChunk->aCtrl[iBlock] |= CTRL_FREE; - pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE; - - pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize; - while( iLogsize>iLogsize) & 1 ){ - iBuddy = iBlock - size; - }else{ - iBuddy = iBlock + size; - } - assert( iBuddy>=0 ); - if( (iBuddy+(1<pChunk->nBlock ) break; - if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; - memsys6Unlink(pChunk, iBuddy, iLogsize); - iLogsize++; - if( iBuddyaCtrl[iBuddy] = CTRL_FREE | iLogsize; - pChunk->aCtrl[iBlock] = 0; - iBlock = iBuddy; - }else{ - pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize; - pChunk->aCtrl[iBuddy] = 0; - } - size *= 2; - } - pChunk->nCheckedOut--; - memsys6Link(pChunk, iBlock, iLogsize); -} - -/* -** Return the actual size of the block pointed to by p, which is guaranteed -** to have been allocated from chunk pChunk. -*/ -static int chunkSize(Mem6Chunk *pChunk, void *p){ - int iSize = 0; - if( p ){ - int i = ((u8 *)p-pChunk->zPool)/pChunk->nAtom; - assert( i>=0 && inBlock ); - iSize = pChunk->nAtom * (1 << (pChunk->aCtrl[i]&CTRL_LOGSIZE)); - } - return iSize; -} - -/* -** Return true if there are currently no outstanding allocations. -*/ -static int chunkIsEmpty(Mem6Chunk *pChunk){ - return (pChunk->nCheckedOut==0); -} - -/* -** Initialize the buffer zChunk, which is nChunk bytes in size, as -** an Mem6Chunk object. Return a copy of the zChunk pointer. -*/ -static Mem6Chunk *chunkInit(u8 *zChunk, int nChunk, int nMinAlloc){ - int ii; - int iOffset; - Mem6Chunk *pChunk = (Mem6Chunk *)zChunk; - - assert( nChunk>sizeof(Mem6Chunk) ); - assert( nMinAlloc>sizeof(Mem6Link) ); - - memset(pChunk, 0, sizeof(Mem6Chunk)); - pChunk->nAtom = nMinAlloc; - pChunk->nBlock = ((nChunk-sizeof(Mem6Chunk)) / (pChunk->nAtom+sizeof(u8))); - - pChunk->zPool = (u8 *)&pChunk[1]; - pChunk->aCtrl = &pChunk->zPool[pChunk->nBlock*pChunk->nAtom]; - - for(ii=0; ii<=mem6.nLogThreshold; ii++){ - pChunk->aiFreelist[ii] = -1; - } - - iOffset = 0; - for(ii=mem6.nLogThreshold; ii>=0; ii--){ - int nAlloc = (1<nBlock ){ - pChunk->aCtrl[iOffset] = ii | CTRL_FREE; - memsys6Link(pChunk, iOffset, ii); - iOffset += nAlloc; - } - } - - return pChunk; -} - - -static void mem6Enter(void){ - sqlite3_mutex_enter(mem6.mutex); -} - -static void mem6Leave(void){ - sqlite3_mutex_leave(mem6.mutex); -} - -/* -** Based on the number and size of the currently allocated chunks, return -** the size of the next chunk to allocate, in bytes. -*/ -static int nextChunkSize(void){ - int iTotal = MIN_CHUNKSIZE; - Mem6Chunk *p; - for(p=mem6.pChunk; p; p=p->pNext){ - iTotal = iTotal*2; - } - return iTotal; -} - -static void freeChunk(Mem6Chunk *pChunk){ - Mem6Chunk **pp = &mem6.pChunk; - for( pp=&mem6.pChunk; *pp!=pChunk; pp = &(*pp)->pNext ); - *pp = (*pp)->pNext; - free(pChunk); -} - -static void *memsys6Malloc(int nByte){ - Mem6Chunk *pChunk; - void *p = 0; - int nTotal = nByte+8; - int iOffset = 0; - - if( nTotal>mem6.nThreshold ){ - p = malloc(nTotal); - }else{ - int iLogsize = 0; - if( nTotal>(1<pNext){ - p = chunkMalloc(pChunk, iLogsize); - if( p ){ - break; - } - } - if( !p ){ - int iSize = nextChunkSize(); - p = malloc(iSize); - if( p ){ - pChunk = chunkInit((u8 *)p, iSize, mem6.nMinAlloc); - pChunk->pNext = mem6.pChunk; - mem6.pChunk = pChunk; - p = chunkMalloc(pChunk, iLogsize); - assert(p); - } - } - iOffset = ((u8*)p - (u8*)pChunk); - mem6Leave(); - } - - if( !p ){ - return 0; - } - ((u32 *)p)[0] = iOffset; - ((u32 *)p)[1] = nByte; - return &((u32 *)p)[2]; -} - -static int memsys6Size(void *pPrior){ - if( pPrior==0 ) return 0; - return ((u32*)pPrior)[-1]; -} - -static void memsys6Free(void *pPrior){ - int iSlot; - void *p = &((u32 *)pPrior)[-2]; - iSlot = ((u32 *)p)[0]; - if( iSlot ){ - Mem6Chunk *pChunk; - mem6Enter(); - pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]); - chunkFree(pChunk, p); - if( chunkIsEmpty(pChunk) ){ - freeChunk(pChunk); - } - mem6Leave(); - }else{ - free(p); - } -} - -static void *memsys6Realloc(void *p, int nByte){ - void *p2; - - if( p && nByte<=memsys6Size(p) ){ - p2 = p; - }else{ - p2 = memsys6Malloc(nByte); - if( p && p2 ){ - memcpy(p2, p, memsys6Size(p)); - memsys6Free(p); - } - } - - return p2; -} - -static int memsys6Roundup(int n){ - if( n>mem6.nThreshold ){ - return n; - }else{ - return (1<