-C Fix\sfurther\swarnings/compilation\serrors\sin\stest\scode.\s(CVS\s5558)
-D 2008-08-12T15:04:59
+C Revise\sthe\sinitialization\sand\sshutdown\slogic\sso\sthat\sit\sno\slonger\skeeps\na\srecursive\smutex\sallocated\sfor\sthe\swhole\sinterval\sbut\sinstead\sreleases\nthe\smutex\sas\ssoon\sas\spossible.\s\sDo\snot\sreset\sstatus\svalues\supon\sinitialization.\s(CVS\s5559)
+D 2008-08-12T15:21:12
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 2713ea64947be3b35f35d9a3158bb8299c90b019
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e
F src/legacy.c aac57bd984e666059011ea01ec4383892a253be3
F src/loadext.c eb1fe4f44d7c8ff53fc0c6a4388ab79fbd34cd64
-F src/main.c 9707706f62adc7a6830f7128eaaae6f3410046ae
+F src/main.c c5ed24ad2b27bc93aea580a17f370a19897165f6
F src/malloc.c 22c68fc62f0c2df0f1deb8cd9a5ea968f995cac2
F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a
F src/mem1.c 3a7fe31d8290baa3bb203af72f7dfd6323966bcd
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
F src/sqlite.h.in 54e51c22e2294c5989156b0aec87aa44168ac1f0
F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
-F src/sqliteInt.h 685b9cf6537e59e4453269b43acb33c59b566346
+F src/sqliteInt.h be39605e2deee45c1004c8bf3927bdab2ec97e0c
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
-F src/status.c b39b4468fe97c7d26be2de052804887c099312e7
+F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
F src/tclsqlite.c ec46084184f033ba396a9ee7b5514b695083d0f3
F src/test1.c 0ae2203b03dec8ecf8ad731038df47ba27bfe68c
F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8
F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893
F test/memleak.test d2d2a1ff7105d32dc3fdf691458cf6cba58c7217
-F test/memsubsys1.test 4896d75373f55e61d80b12261d88192861d18b53
-F test/memsubsys2.test c05b541f9c2a1234a9dc2ff2233b3a9544fa5139
+F test/memsubsys1.test 3cfd3237dbbceaf65673be7265c58d8a34d63cbb
+F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
F test/minmax3.test 94742aa922153953ce3562702815e4f1f079bdb8
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P e3935502fdca486613c8116b6057bfdd37545e58
-R 81992e6503b50b00362c1f386109d2c1
-U danielk1977
-Z 15fdebe7ba6a81553a61856d47818587
+P 42247b917ae5a5c0d81b934200810755d0040282
+R 69ce11efb4890d98b6c9a2863d484581
+U drh
+Z be8367a1b5dd5ee08063dfae6619d193
-42247b917ae5a5c0d81b934200810755d0040282
\ No newline at end of file
+697fe7a3167c22a3232ce154e9d47cf75af613c4
\ No newline at end of file
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.487 2008/08/08 14:33:13 drh Exp $
+** $Id: main.c,v 1.488 2008/08/12 15:21:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
-** VFS, and mutex subsystesms prior to doing any serious work with
+** VFS, and mutex subsystems prior to doing any serious work with
** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.
+**
+** The first thread to call this routine runs the initialization to
+** completion. If subsequent threads call this routine before the first
+** thread has finished the initialization process, then the subsequent
+** threads must block until the first thread finishes with the initialization.
+**
+** The first thread might call this routine recursively. Recursive
+** calls to this routine should not block, of course. Otherwise the
+** initialization process would never complete.
+**
+** Let X be the first thread to enter this routine. Let Y be some other
+** thread. Then while the initial invocation of this routine by X is
+** incomplete, it is required that:
+**
+** * Calls to this routine from Y must block until the outer-most
+** call by X completes.
+**
+** * Recursive calls to this routine from thread X return immediately
+** without blocking.
*/
int sqlite3_initialize(void){
- static int inProgress = 0;
- int rc;
-
- /* If SQLite is already initialized, this call is a no-op. */
+ static int inProgress = 0; /* Prevent recursion */
+ sqlite3_mutex *pMaster; /* The main static mutex */
+ int rc; /* Result code */
+
+ /* If SQLite is already completely initialized, then this call
+ ** to sqlite3_initialize() should be a no-op. But the initialization
+ ** must be complete. So isInit must not be set until the very end
+ ** of this routine.
+ */
if( sqlite3Config.isInit ) return SQLITE_OK;
- /* Make sure the mutex system is initialized. */
+ /* Make sure the mutex subsystem is initialized. If unable to
+ ** initialize the mutex subsystem, return early with the error.
+ ** If the system is so sick that we are unable to allocate a mutex,
+ ** there is not much SQLite is going to be able to do.
+ **
+ ** The mutex subsystem must take care of serializing its own
+ ** initialization.
+ */
rc = sqlite3MutexInit();
+ if( rc ) return rc;
+ /* Initialize the malloc() system and the recursive pInitMutex mutex.
+ ** This operation is protected by the STATIC_MASTER mutex. Note that
+ ** MutexAlloc() is called for a static mutex prior to initializing the
+ ** malloc subsystem - this implies that the allocation of a static
+ ** mutex must not require support from the malloc subsystem.
+ */
+ pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ sqlite3_mutex_enter(pMaster);
+ if( !sqlite3Config.isMallocInit ){
+ rc = sqlite3MallocInit();
+ }
if( rc==SQLITE_OK ){
-
- /* Initialize the malloc() system and the recursive pInitMutex mutex.
- ** This operation is protected by the STATIC_MASTER mutex.
- */
- sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- sqlite3_mutex_enter(pMaster);
- if( !sqlite3Config.isMallocInit ){
- rc = sqlite3MallocInit();
- }
- if( rc==SQLITE_OK ){
- sqlite3Config.isMallocInit = 1;
- if( !sqlite3Config.pInitMutex ){
- sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
- rc = SQLITE_NOMEM;
- }
+ sqlite3Config.isMallocInit = 1;
+ if( !sqlite3Config.pInitMutex ){
+ sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
+ rc = SQLITE_NOMEM;
}
}
- sqlite3_mutex_leave(pMaster);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ sqlite3Config.nRefInitMutex++;
+ }
+ sqlite3_mutex_leave(pMaster);
- /* Enter the recursive pInitMutex mutex. After doing so, if the
- ** sqlite3Config.isInit flag is true, then some other thread has
- ** finished doing the initialization. If the inProgress flag is
- ** true, then this function is being called recursively from within
- ** the sqlite3_os_init() call below. In either case, exit early.
- */
- sqlite3_mutex_enter(sqlite3Config.pInitMutex);
- if( sqlite3Config.isInit || inProgress ){
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
- return SQLITE_OK;
- }
- sqlite3StatusReset();
+ /* If unable to initialize the malloc subsystem, then return early.
+ ** There is little hope of getting SQLite to run if the malloc
+ ** subsystem cannot be initialized.
+ */
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* Do the rest of the initialization under the recursive mutex so
+ ** that we will be able to handle recursive calls into
+ ** sqlite3_initialize(). The recursive calls normally come through
+ ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
+ ** recursive calls might also be possible.
+ */
+ sqlite3_mutex_enter(sqlite3Config.pInitMutex);
+ if( sqlite3Config.isInit==0 && inProgress==0 ){
inProgress = 1;
rc = sqlite3_os_init();
inProgress = 0;
sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
}
+ sqlite3_mutex_leave(sqlite3Config.pInitMutex);
- /* Check NaN support. */
+ /* Go back under the static mutex and clean up the recursive
+ ** mutex to prevent a resource leak.
+ */
+ sqlite3_mutex_enter(pMaster);
+ sqlite3Config.nRefInitMutex--;
+ if( sqlite3Config.nRefInitMutex<=0 ){
+ assert( sqlite3Config.nRefInitMutex==0 );
+ sqlite3_mutex_free(sqlite3Config.pInitMutex);
+ sqlite3Config.pInitMutex = 0;
+ }
+ sqlite3_mutex_leave(pMaster);
+
+ /* The following is just a sanity check to make sure SQLite has
+ ** been compiled correctly. It is important to run this code, but
+ ** we don't want to run it too often and soak up CPU cycles for no
+ ** reason. So we run it once during initialization.
+ */
#ifndef NDEBUG
/* This section of code's only "output" is via assert() statements. */
if ( rc==SQLITE_OK ){
** routine is not threadsafe. Not by a long shot.
*/
int sqlite3_shutdown(void){
- sqlite3_mutex_free(sqlite3Config.pInitMutex);
- sqlite3Config.pInitMutex = 0;
sqlite3Config.isMallocInit = 0;
if( sqlite3Config.isInit ){
sqlite3_os_end();
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.752 2008/08/04 20:13:27 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.753 2008/08/12 15:21:12 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
int isInit; /* True after initialization has finished */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
+ int nRefInitMutex; /* Number of users of pInitMutex */
int nSmall; /* alloc size threshold used by mem6.c */
int mxParserStack; /* maximum depth of the parser stack */
};
int sqlite3MutexEnd(void);
#endif
-void sqlite3StatusReset(void);
int sqlite3StatusValue(int);
void sqlite3StatusAdd(int, int);
void sqlite3StatusSet(int, int);
** This module implements the sqlite3_status() interface and related
** functionality.
**
-** $Id: status.c,v 1.7 2008/08/05 17:53:23 drh Exp $
+** $Id: status.c,v 1.8 2008/08/12 15:21:12 drh Exp $
*/
#include "sqliteInt.h"
} sqlite3Stat;
-/*
-** Reset the status records. This routine is called by
-** sqlite3_initialize().
-*/
-void sqlite3StatusReset(void){
- memset(&sqlite3Stat, 0, sizeof(sqlite3Stat));
-}
-
/*
** Return the current value of a status parameter.
*/
#
# This file contains tests of the memory allocation subsystem
#
-# $Id: memsubsys1.test,v 1.8 2008/08/04 20:13:27 drh Exp $
+# $Id: memsubsys1.test,v 1.9 2008/08/12 15:21:12 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
integrity_check $testname.2
}
+# Reset all of the highwater marks.
+#
+proc reset_highwater_marks {} {
+ sqlite3_status SQLITE_STATUS_MEMORY_USED 1
+ sqlite3_status SQLITE_STATUS_MALLOC_SIZE 1
+ sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
+ sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 1
+ sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 1
+ sqlite3_status SQLITE_STATUS_SCRATCH_USED 1
+ sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 1
+ sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 1
+ sqlite3_status SQLITE_STATUS_PARSER_STACK 1
+}
+
# Test 1: Both PAGECACHE and SCRATCH are shut down.
#
db close
sqlite3_shutdown
sqlite3_config_lookaside 0 0
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-1 {PRAGMA page_size=1024}
do_test memsubsys1-1.3 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
sqlite3_shutdown
sqlite3_config_pagecache 1024 20
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-2 {PRAGMA page_size=1024}
#show_memstats
do_test memsubsys1-2.3 {
sqlite3_shutdown
sqlite3_config_pagecache 512 20
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-3.1 {PRAGMA page_size=1024}
#show_memstats
do_test memsubsys1-3.1.3 {
sqlite3_shutdown
sqlite3_config_pagecache 2048 20
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-3.2 {PRAGMA page_size=2048}
#show_memstats
do_test memsubsys1-3.2.3 {
sqlite3_config_pagecache 1024 50
sqlite3_config_scratch 6000 2
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-4 {PRAGMA page_size=1024}
#show_memstats
do_test memsubsys1-4.3 {
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 6000 2
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-5 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-5.3 {
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-6 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-6.3 {
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
+reset_highwater_marks
build_test_db memsubsys1-7 {
PRAGMA page_size=4096;
PRAGMA cache_size=10;
#
# This file contains tests of the memory allocation subsystem.
#
-# $Id: memsubsys2.test,v 1.1 2008/07/10 18:13:43 drh Exp $
+# $Id: memsubsys2.test,v 1.2 2008/08/12 15:21:12 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
integrity_check $testname.2
}
+# Reset all of the highwater marks.
+#
+proc reset_highwater_marks {} {
+ sqlite3_status SQLITE_STATUS_MEMORY_USED 1
+ sqlite3_status SQLITE_STATUS_MALLOC_SIZE 1
+ sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
+ sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 1
+ sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 1
+ sqlite3_status SQLITE_STATUS_SCRATCH_USED 1
+ sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 1
+ sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 1
+ sqlite3_status SQLITE_STATUS_PARSER_STACK 1
+}
+
# Test 1: Verify that calling sqlite3_malloc(0) returns a NULL
# pointer.
#
sqlite3_shutdown
sqlite3_config_memstatus 0
sqlite3_initialize
+reset_highwater_marks
set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-3.1 {
set highwater
sqlite3_shutdown
sqlite3_config_memstatus 1
sqlite3_initialize
+reset_highwater_marks
set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-4.1 {
set highwater