mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-20 07:41:32 +03:00
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
This commit is contained in:
14
Makefile.in
14
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
|
||||
|
||||
|
5
main.mk
5
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 \
|
||||
|
27
manifest
27
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
|
||||
|
@@ -1 +1 @@
|
||||
e9c2adbcbf5c28837b06e0fbba93f1764cc3607f
|
||||
4651f590f0b8bf13938b2b15d5082136e763af8d
|
61
src/mem0.c
Normal file
61
src/mem0.c
Normal file
@@ -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 */
|
22
src/mem1.c
22
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 */
|
||||
|
19
src/mem2.c
19
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
393
src/mem4.c
393
src/mem4.c
@@ -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 <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.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 = 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.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_MMAP_HEAP_SIZE */
|
26
src/mem5.c
26
src/mem5.c
@@ -23,38 +23,16 @@
|
||||
** This version of the memory allocation subsystem is included
|
||||
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
|
||||
**
|
||||
** $Id: mem5.c,v 1.14 2008/09/02 17:52:52 danielk1977 Exp $
|
||||
** $Id: mem5.c,v 1.15 2008/10/28 18:58:20 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** This version of the memory allocator is used only when
|
||||
** SQLITE_POW2_MEMORY_SIZE is defined.
|
||||
** SQLITE_ENABLE_MEMSYS5 is defined.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMSYS5
|
||||
|
||||
/*
|
||||
** Log2 of the minimum size of an allocation. For example, if
|
||||
** 4 then all allocations will be rounded up to at least 16 bytes.
|
||||
** If 5 then all allocations will be rounded up to at least 32 bytes.
|
||||
*/
|
||||
#ifndef SQLITE_POW2_LOGMIN
|
||||
# define SQLITE_POW2_LOGMIN 6
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Log2 of the maximum size of an allocation.
|
||||
*/
|
||||
#ifndef SQLITE_POW2_LOGMAX
|
||||
# define SQLITE_POW2_LOGMAX 20
|
||||
#endif
|
||||
#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX)
|
||||
|
||||
/*
|
||||
** Number of distinct allocation sizes.
|
||||
*/
|
||||
#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)
|
||||
|
||||
/*
|
||||
** A minimum allocation is an instance of the following structure.
|
||||
** Larger allocations are an array of these structures where the
|
||||
|
498
src/mem6.c
498
src/mem6.c
@@ -1,498 +0,0 @@
|
||||
/*
|
||||
** 2008 July 24
|
||||
**
|
||||
** 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 an alternative memory allocation system for SQLite.
|
||||
** This system is implemented as a wrapper around the system provided
|
||||
** by the operating system - vanilla malloc(), realloc() and free().
|
||||
**
|
||||
** This system differentiates between requests for "small" allocations
|
||||
** (by default those of 128 bytes or less) and "large" allocations (all
|
||||
** others). The 256 byte threshhold is configurable at runtime.
|
||||
**
|
||||
** All requests for large allocations are passed through to the
|
||||
** default system.
|
||||
**
|
||||
** Requests for small allocations are met by allocating space within
|
||||
** one or more larger "chunks" of memory obtained from the default
|
||||
** memory allocation system. Chunks of memory are usually 64KB or
|
||||
** larger. The algorithm used to manage space within each chunk is
|
||||
** the same as that used by mem5.c.
|
||||
**
|
||||
** This strategy is designed to prevent the default memory allocation
|
||||
** system (usually the system malloc) from suffering from heap
|
||||
** fragmentation. On some systems, heap fragmentation can cause a
|
||||
** significant real-time slowdown.
|
||||
**
|
||||
** $Id: mem6.c,v 1.10 2008/09/02 17:52:52 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMSYS6
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Maximum size of any "small" allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom).
|
||||
** Mem6Chunk.nAtom is always at least 8, so this is not a practical
|
||||
** limitation
|
||||
*/
|
||||
#define LOGMAX 30
|
||||
|
||||
/*
|
||||
** Default value for the "small" allocation size threshold.
|
||||
*/
|
||||
#define SMALL_MALLOC_DEFAULT_THRESHOLD 256
|
||||
|
||||
/*
|
||||
** Minimum size for a memory chunk.
|
||||
*/
|
||||
#define MIN_CHUNKSIZE (1<<16)
|
||||
|
||||
#define LOG2_MINALLOC 4
|
||||
|
||||
|
||||
typedef struct Mem6Chunk Mem6Chunk;
|
||||
typedef struct Mem6Link Mem6Link;
|
||||
|
||||
/*
|
||||
** A minimum allocation is an instance of the following structure.
|
||||
** Larger allocations are an array of these structures where the
|
||||
** size of the array is a power of 2.
|
||||
*/
|
||||
struct Mem6Link {
|
||||
int next; /* Index of next free chunk */
|
||||
int prev; /* Index of previous free chunk */
|
||||
};
|
||||
|
||||
/*
|
||||
** Masks used for mem5.aCtrl[] elements.
|
||||
*/
|
||||
#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */
|
||||
#define CTRL_FREE 0x20 /* True if not checked out */
|
||||
|
||||
struct Mem6Chunk {
|
||||
Mem6Chunk *pNext;
|
||||
|
||||
/*
|
||||
** Lists of free blocks of various sizes.
|
||||
*/
|
||||
int aiFreelist[LOGMAX+1];
|
||||
|
||||
int nCheckedOut; /* Number of currently outstanding allocations */
|
||||
|
||||
/*
|
||||
** Space for tracking which blocks are checked out and the size
|
||||
** of each block. One byte per block.
|
||||
*/
|
||||
u8 *aCtrl;
|
||||
|
||||
/*
|
||||
** Memory available for allocation
|
||||
*/
|
||||
int nAtom; /* Smallest possible allocation in bytes */
|
||||
int nBlock; /* Number of nAtom sized blocks in zPool */
|
||||
u8 *zPool; /* Pointer to memory chunk from which allocations are made */
|
||||
};
|
||||
|
||||
#define MEM6LINK(idx) ((Mem6Link *)(&pChunk->zPool[(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 && i<pChunk->nBlock );
|
||||
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 && i<pChunk->nBlock );
|
||||
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( x<pChunk->nBlock );
|
||||
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 && iBlock<pChunk->nBlock );
|
||||
assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 );
|
||||
assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 );
|
||||
|
||||
iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE;
|
||||
size = 1<<iLogsize;
|
||||
assert( iBlock+size-1<pChunk->nBlock );
|
||||
|
||||
pChunk->aCtrl[iBlock] |= CTRL_FREE;
|
||||
pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE;
|
||||
|
||||
pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
|
||||
while( iLogsize<mem6.nLogThreshold ){
|
||||
int iBuddy;
|
||||
if( (iBlock>>iLogsize) & 1 ){
|
||||
iBuddy = iBlock - size;
|
||||
}else{
|
||||
iBuddy = iBlock + size;
|
||||
}
|
||||
assert( iBuddy>=0 );
|
||||
if( (iBuddy+(1<<iLogsize))>pChunk->nBlock ) break;
|
||||
if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
|
||||
memsys6Unlink(pChunk, iBuddy, iLogsize);
|
||||
iLogsize++;
|
||||
if( iBuddy<iBlock ){
|
||||
pChunk->aCtrl[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 && i<pChunk->nBlock );
|
||||
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<<ii);
|
||||
while( (iOffset+nAlloc)<=pChunk->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<<LOG2_MINALLOC) ){
|
||||
iLogsize = roundupLog2(nTotal) - LOG2_MINALLOC;
|
||||
}
|
||||
mem6Enter();
|
||||
for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->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<<roundupLog2(n));
|
||||
}
|
||||
}
|
||||
|
||||
static int memsys6Init(void *pCtx){
|
||||
u8 bMemstat = sqlite3GlobalConfig.bMemstat;
|
||||
mem6.nMinAlloc = (1 << LOG2_MINALLOC);
|
||||
mem6.pChunk = 0;
|
||||
mem6.nThreshold = sqlite3GlobalConfig.nSmall;
|
||||
if( mem6.nThreshold<=0 ){
|
||||
mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD;
|
||||
}
|
||||
mem6.nLogThreshold = roundupLog2(mem6.nThreshold) - LOG2_MINALLOC;
|
||||
if( !bMemstat ){
|
||||
mem6.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static void memsys6Shutdown(void *pCtx){
|
||||
memset(&mem6, 0, sizeof(mem6));
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is the only routine in this file with external
|
||||
** linkage. It returns a pointer to a static sqlite3_mem_methods
|
||||
** struct populated with the memsys6 methods.
|
||||
*/
|
||||
const sqlite3_mem_methods *sqlite3MemGetMemsys6(void){
|
||||
static const sqlite3_mem_methods memsys6Methods = {
|
||||
memsys6Malloc,
|
||||
memsys6Free,
|
||||
memsys6Realloc,
|
||||
memsys6Size,
|
||||
memsys6Roundup,
|
||||
memsys6Init,
|
||||
memsys6Shutdown,
|
||||
0
|
||||
};
|
||||
return &memsys6Methods;
|
||||
}
|
||||
|
||||
#endif
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.786 2008/10/28 17:52:39 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.787 2008/10/28 18:58:20 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@@ -2054,10 +2054,8 @@ void sqlite3ScratchFree(void*);
|
||||
void *sqlite3PageMalloc(int);
|
||||
void sqlite3PageFree(void*);
|
||||
void sqlite3MemSetDefault(void);
|
||||
const sqlite3_mem_methods *sqlite3MemGetDefault(void);
|
||||
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
|
||||
const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
|
||||
const sqlite3_mem_methods *sqlite3MemGetMemsys6(void);
|
||||
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
|
||||
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
|
||||
int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64);
|
||||
|
||||
|
@@ -211,11 +211,11 @@ foreach file {
|
||||
os.c
|
||||
|
||||
fault.c
|
||||
mem0.c
|
||||
mem1.c
|
||||
mem2.c
|
||||
mem3.c
|
||||
mem5.c
|
||||
mem6.c
|
||||
mutex.c
|
||||
mutex_noop.c
|
||||
mutex_os2.c
|
||||
|
Reference in New Issue
Block a user