Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -77,11 +77,12 @@ assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); zRet = sqlite4MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, zTableName, tname.z+tname.n); - sqlite4_result_text(context, zRet, -1, SQLITE_DYNAMIC); + sqlite4_result_text(context, zRet, -1, SQLITE_TRANSIENT); + sqlite4DbFree(db, zRet); } } /* ** This C function implements an SQL user function that is used by SQL code @@ -139,12 +140,13 @@ sqlite4DbFree(db, zParent); } } zResult = sqlite4MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), - sqlite4_result_text(context, zResult, -1, SQLITE_DYNAMIC); + sqlite4_result_text(context, zResult, -1, SQLITE_TRANSIENT); sqlite4DbFree(db, zOutput); + sqlite4DbFree(db, zResult); } #endif #ifndef SQLITE_OMIT_TRIGGER /* This function is used by SQL generated to implement the @@ -216,19 +218,20 @@ /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ zRet = sqlite4MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, zTableName, tname.z+tname.n); - sqlite4_result_text(context, zRet, -1, SQLITE_DYNAMIC); + sqlite4_result_text(context, zRet, -1, SQLITE_TRANSIENT); + sqlite4DbFree(db, zRet); } } #endif /* !SQLITE_OMIT_TRIGGER */ /* ** Register built-in functions used to help implement ALTER TABLE */ -void sqlite4AlterFunctions(void){ +void sqlite4AlterFunctions(sqlite4_env *pEnv){ static SQLITE_WSD FuncDef aAlterTableFuncs[] = { FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), #ifndef SQLITE_OMIT_TRIGGER FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), #endif @@ -235,11 +238,11 @@ #ifndef SQLITE_OMIT_FOREIGN_KEY FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), #endif }; int i; - FuncDefHash *pHash = &sqlite4GlobalFunctions; + FuncDefHash *pHash = &pEnv->hashGlobalFuncs; FuncDef *aFunc = (FuncDef*)aAlterTableFuncs; for(i=0; iflags & SQLITE_PreferBuiltin)!=0) ){ - FuncDefHash *pHash = &sqlite4GlobalFunctions; + FuncDefHash *pHash = &db->pEnv->hashGlobalFuncs; bestScore = 0; p = functionSearch(pHash, h, zName, nName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ Index: src/date.c ================================================================== --- src/date.c +++ src/date.c @@ -1114,11 +1114,11 @@ STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), #endif }; int i; - FuncDefHash *pHash = &sqlite4GlobalFunctions; + FuncDefHash *pHash = &pEnv->hashGlobalFuncs; FuncDef *aFunc = (FuncDef*)aDateTimeFuncs; for(i=0; ihashGlobalFuncs; FuncDef *aFunc = (FuncDef*)aBuiltinFunc; for(i=0; iisInit ) return SQLITE_OK; - /* 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 = sqlite4MutexInit(); - 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. - */ - MUTEX_LOGIC( pMaster = sqlite4MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) - sqlite4_mutex_enter(pMaster); - pEnv->isMutexInit = 1; - if( !pEnv->isMallocInit ){ - rc = sqlite4MallocInit(pEnv); - } - if( rc==SQLITE_OK ){ - pEnv->isMallocInit = 1; - if( !pEnv->pInitMutex ){ - pEnv->pInitMutex = - sqlite4MutexAlloc(SQLITE_MUTEX_RECURSIVE); - if( pEnv->bCoreMutex && !pEnv->pInitMutex ){ - rc = SQLITE_NOMEM; - } - } - } - if( rc==SQLITE_OK ){ - pEnv->nRefInitMutex++; - } - sqlite4_mutex_leave(pMaster); - - /* If rc is not SQLITE_OK at this point, then either the malloc - ** subsystem could not be initialized or the system failed to allocate - ** the pInitMutex mutex. Return an error in either case. */ - if( rc!=SQLITE_OK ){ + /* Initialize the mutex subsystem + */ + rc = sqlite4MutexInit(pEnv); + if( rc ){ + sqlite4MallocEnd(pEnv); return rc; } - /* Do the rest of the initialization under the recursive mutex so - ** that we will be able to handle recursive calls into - ** sqlite4_initialize(). The recursive calls normally come through - ** sqlite4_os_init() when it invokes sqlite4_vfs_register(), but other - ** recursive calls might also be possible. + /* Initialize the memory allocation subsystem + */ + rc = sqlite4MallocInit(pEnv); + if( rc ) return rc; + + /* Create required mutexes */ - sqlite4_mutex_enter(pEnv->pInitMutex); - if( pEnv->isInit==0 && pEnv->inProgress==0 ){ - FuncDefHash *pHash = &sqlite4GlobalFunctions; - pEnv->inProgress = 1; - memset(pHash, 0, sizeof(sqlite4GlobalFunctions)); + if( pEnv->bCoreMutex ){ + pEnv->pMemMutex = sqlite4MutexAlloc(pEnv, SQLITE_MUTEX_FAST); + pEnv->pPrngMutex = sqlite4MutexAlloc(pEnv, SQLITE_MUTEX_FAST); + if( pEnv->pMemMutex==0 || pEnv->pPrngMutex==0 ) rc = SQLITE_NOMEM; + }else{ + pEnv->pMemMutex = 0; + pEnv->pPrngMutex = 0; + } + pEnv->isInit = 1; + + sqlite4OsInit(pEnv); + + /* Register global functions */ + if( rc==SQLITE_OK ){ sqlite4RegisterGlobalFunctions(pEnv); - rc = sqlite4OsInit(0); - pEnv->inProgress = 0; - } - sqlite4_mutex_leave(pEnv->pInitMutex); - - /* Go back under the static mutex and clean up the recursive - ** mutex to prevent a resource leak. - */ - sqlite4_mutex_enter(pMaster); - pEnv->nRefInitMutex--; - if( pEnv->nRefInitMutex<=0 ){ - assert( pEnv->nRefInitMutex==0 ); - sqlite4_mutex_free(pEnv->pInitMutex); - pEnv->pInitMutex = 0; - } - sqlite4_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. @@ -205,20 +149,10 @@ assert( sqlite4IsNaN(y) ); } #endif #endif - /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT - ** compile-time option. - */ -#ifdef SQLITE_EXTRA_INIT - if( rc==SQLITE_OK && pEnv->isInit ){ - int SQLITE_EXTRA_INIT(const char*); - rc = SQLITE_EXTRA_INIT(0); - } -#endif - return rc; } /* ** Undo the effects of sqlite4_initialize(). Must not be called while @@ -229,23 +163,16 @@ ** when this routine is invoked, then this routine is a harmless no-op. */ int sqlite4_shutdown(sqlite4_env *pEnv){ if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; if( pEnv->isInit ){ -#ifdef SQLITE_EXTRA_SHUTDOWN - void SQLITE_EXTRA_SHUTDOWN(void); - SQLITE_EXTRA_SHUTDOWN(); -#endif - /*sqlite4_os_end();*/ - /* sqlite4_reset_auto_extension(); */ + sqlite4_mutex_free(pEnv->pMemMutex); + pEnv->pMemMutex = 0; + sqlite4MutexEnd(pEnv); + sqlite4MallocEnd(pEnv); pEnv->isInit = 0; } - if( pEnv->isMallocInit ){ - sqlite4MallocEnd(pEnv); - pEnv->isMallocInit = 0; - } - return SQLITE_OK; } /* ** This API allows applications to modify the configuration described by @@ -261,23 +188,10 @@ ** the SQLite library is in use. */ if( pEnv->isInit ) return SQLITE_MISUSE_BKPT; va_start(ap, op); switch( op ){ - case SQLITE_CONFIG_SET_KVFACTORY: { - pEnv->xKVFile = *va_arg(ap, - int (*)(sqlite4_env*, KVStore **, const char *, unsigned int) - ); - break; - } - - case SQLITE_CONFIG_GET_KVFACTORY: { - *va_arg(ap, int(**)(sqlite4_env*, KVStore**, const char*, unsigned int)) = - pEnv->xKVFile; - break; - } - default: { rc = SQLITE_ERROR; break; } } @@ -468,24 +382,48 @@ ** ** Push a new KVStore factory onto the factory stack. The new factory ** takes priority over prior factories. */ case SQLITE_ENVCONFIG_KVSTORE_PUSH: { - pEnv->xKVFile = *va_arg(ap, - int (*)(sqlite4_env*, KVStore **, const char *, unsigned int) - ); + const char *zName = va_arg(ap, const char*); + if( strcmp(zName, "temp")==0 ){ + pEnv->xKVTmp = *va_arg(ap, + int (*)(sqlite4_env*, KVStore **, const char *, unsigned int) + ); + }else{ + pEnv->xKVFile = *va_arg(ap, + int (*)(sqlite4_env*, KVStore **, const char *, unsigned int) + ); + } break; } /* ** sqlite4_env_config(pEnv, SQLITE_ENVCONFIG_KVSTORE_POP, zName); ** ** Remove a KVStore factory from the stack. */ case SQLITE_ENVCONFIG_KVSTORE_POP: { - *va_arg(ap, int(**)(sqlite4_env*, KVStore**, const char*, unsigned int)) = - pEnv->xKVFile; + /* TBD */ + break; + } + + /* + ** sqlite4_env_config(pEnv, SQLITE_ENVCONFIG_KVSTORE_GET, zName,&pxFactory); + ** + ** Get the current factory pointer with the given name. + */ + case SQLITE_ENVCONFIG_KVSTORE_GET: { + const char *zName = va_arg(ap, const char*); + int(*xFactory)(sqlite4_env*,KVStore**,const char*,unsigned); + if( strcmp(zName, "temp")==0 ){ + xFactory = pEnv->xKVTmp; + }else{ + xFactory = pEnv->xKVFile; + } + *va_arg(ap, int(**)(sqlite4_env*, KVStore**, const char*, unsigned int)) + = xFactory; break; } default: { @@ -1753,11 +1691,11 @@ /* Allocate the sqlite data structure */ db = sqlite4MallocZero(pEnv, sizeof(sqlite4) ); if( db==0 ) goto opendb_out; db->pEnv = pEnv; if( isThreadsafe ){ - db->mutex = sqlite4MutexAlloc(SQLITE_MUTEX_RECURSIVE); + db->mutex = sqlite4MutexAlloc(pEnv, SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ sqlite4_free(pEnv, db); db = 0; goto opendb_out; } @@ -2084,38 +2022,10 @@ #ifndef SQLITE_OMIT_BUILTIN_TEST va_list ap; va_start(ap, op); switch( op ){ - /* - ** Save the current state of the PRNG. - */ - case SQLITE_TESTCTRL_PRNG_SAVE: { - sqlite4PrngSaveState(); - break; - } - - /* - ** Restore the state of the PRNG to the last state saved using - ** PRNG_SAVE. If PRNG_SAVE has never before been called, then - ** this verb acts like PRNG_RESET. - */ - case SQLITE_TESTCTRL_PRNG_RESTORE: { - sqlite4PrngRestoreState(); - break; - } - - /* - ** Reset the PRNG back to its uninitialized state. The next call - ** to sqlite4_randomness() will reseed the PRNG using a single call - ** to the xRandomness method of the default VFS. - */ - case SQLITE_TESTCTRL_PRNG_RESET: { - sqlite4PrngResetState(); - break; - } - /* ** sqlite4_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd) ** ** Register hooks to call to indicate which malloc() failures ** are benign. Index: src/malloc.c ================================================================== --- src/malloc.c +++ src/malloc.c @@ -13,39 +13,27 @@ ** Memory allocation functions used throughout sqlite. */ #include "sqliteInt.h" #include -/* -** State information local to the memory allocation subsystem. -*/ -static SQLITE_WSD struct Mem0Global { - sqlite4_mutex *mutex; /* Mutex to serialize access */ -} mem0 = { 0 }; - /* ** Initialize the memory allocation subsystem. */ int sqlite4MallocInit(sqlite4_env *pEnv){ if( pEnv->m.xMalloc==0 ){ sqlite4MemSetDefault(pEnv); } - memset(&mem0, 0, sizeof(mem0)); - if( pEnv->bCoreMutex ){ - mem0.mutex = sqlite4MutexAlloc(SQLITE_MUTEX_STATIC_MEM); - } - return pEnv->m.xInit(pEnv->m.pAppData); + return pEnv->m.xInit(pEnv->m.pMemEnv); } /* ** Deinitialize the memory allocation subsystem. */ void sqlite4MallocEnd(sqlite4_env *pEnv){ if( pEnv->m.xShutdown ){ - pEnv->m.xShutdown(pEnv->m.pAppData); + pEnv->m.xShutdown(pEnv->m.pMemEnv); } - memset(&mem0, 0, sizeof(mem0)); } /* ** Return the amount of memory currently checked out. */ @@ -85,21 +73,21 @@ ** 255 bytes of overhead. SQLite itself will never use anything near ** this amount. The only way to reach the limit is with sqlite4_malloc() */ p = 0; }else if( pEnv->bMemstat ){ int nFull = (n + 7)&~7; - sqlite4_mutex_enter(mem0.mutex); - p = pEnv->m.xMalloc(pEnv->m.pAppData, nFull); + sqlite4_mutex_enter(pEnv->pMemMutex); + p = pEnv->m.xMalloc(pEnv->m.pMemEnv, nFull); if( p ){ nFull = sqlite4MallocSize(pEnv, p); sqlite4StatusAdd(pEnv, SQLITE_ENVSTATUS_MEMORY_USED, nFull); sqlite4StatusAdd(pEnv, SQLITE_ENVSTATUS_MALLOC_COUNT, 1); } sqlite4StatusSet(pEnv, SQLITE_ENVSTATUS_MALLOC_SIZE, n); - sqlite4_mutex_leave(mem0.mutex); + sqlite4_mutex_leave(pEnv->pMemMutex); }else{ - p = pEnv->m.xMalloc(pEnv->m.pAppData, n); + p = pEnv->m.xMalloc(pEnv->m.pMemEnv, n); } assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */ return p; } @@ -134,11 +122,11 @@ */ int sqlite4MallocSize(sqlite4_env *pEnv, void *p){ assert( sqlite4MemdebugHasType(p, MEMTYPE_HEAP) ); assert( sqlite4MemdebugNoType(p, MEMTYPE_DB) ); if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; - return pEnv->m.xSize(pEnv->m.pAppData, p); + return pEnv->m.xSize(pEnv->m.pMemEnv, p); } int sqlite4DbMallocSize(sqlite4 *db, void *p){ assert( db==0 || sqlite4_mutex_held(db->mutex) ); if( db && isLookaside(db, p) ){ return db->lookaside.sz; @@ -145,11 +133,11 @@ }else{ sqlite4_env *pEnv = db->pEnv; assert( sqlite4MemdebugHasType(p, MEMTYPE_DB) ); assert( sqlite4MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); assert( db!=0 || sqlite4MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); - return pEnv->m.xSize(pEnv->m.pAppData, p); + return pEnv->m.xSize(pEnv->m.pMemEnv, p); } } /* ** Free memory previously obtained from sqlite4Malloc(). @@ -158,18 +146,18 @@ if( p==0 ) return; /* IMP: R-49053-54554 */ assert( sqlite4MemdebugNoType(p, MEMTYPE_DB) ); assert( sqlite4MemdebugHasType(p, MEMTYPE_HEAP) ); if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; if( pEnv->bMemstat ){ - sqlite4_mutex_enter(mem0.mutex); + sqlite4_mutex_enter(pEnv->pMemMutex); sqlite4StatusAdd(pEnv,SQLITE_ENVSTATUS_MEMORY_USED, -sqlite4MallocSize(pEnv, p)); sqlite4StatusAdd(pEnv,SQLITE_ENVSTATUS_MALLOC_COUNT, -1); - pEnv->m.xFree(pEnv->m.pAppData, p); - sqlite4_mutex_leave(mem0.mutex); + pEnv->m.xFree(pEnv->m.pMemEnv, p); + sqlite4_mutex_leave(pEnv->pMemMutex); }else{ - pEnv->m.xFree(pEnv->m.pAppData, p); + pEnv->m.xFree(pEnv->m.pMemEnv, p); } } /* ** Free memory that might be associated with a particular database @@ -217,22 +205,22 @@ return 0; } nOld = sqlite4MallocSize(pEnv, pOld); nNew = (nBytes + 7)&~7; if( pEnv->bMemstat ){ - sqlite4_mutex_enter(mem0.mutex); + sqlite4_mutex_enter(pEnv->pMemMutex); sqlite4StatusSet(pEnv, SQLITE_ENVSTATUS_MALLOC_SIZE, nBytes); assert( sqlite4MemdebugHasType(pOld, MEMTYPE_HEAP) ); assert( sqlite4MemdebugNoType(pOld, ~MEMTYPE_HEAP) ); - pNew = pEnv->m.xRealloc(pEnv->m.pAppData, pOld, nNew); + pNew = pEnv->m.xRealloc(pEnv->m.pMemEnv, pOld, nNew); if( pNew ){ nNew = sqlite4MallocSize(pEnv, pNew); sqlite4StatusAdd(pEnv, SQLITE_ENVSTATUS_MEMORY_USED, nNew-nOld); } - sqlite4_mutex_leave(mem0.mutex); + sqlite4_mutex_leave(pEnv->pMemMutex); }else{ - pNew = pEnv->m.xRealloc(pEnv->m.pAppData, pOld, nNew); + pNew = pEnv->m.xRealloc(pEnv->m.pMemEnv, pOld, nNew); } assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */ return pNew; } Index: src/mem0.c ================================================================== --- src/mem0.c +++ src/mem0.c @@ -54,8 +54,9 @@ 0, 0, 0 }; pEnv->m = defaultMethods; + pEnv->m.pMemEnv = (void*)pEnv; } #endif /* SQLITE_ZERO_MALLOC */ Index: src/mem1.c ================================================================== --- src/mem1.c +++ src/mem1.c @@ -277,8 +277,9 @@ 0, 0, 0 }; pEnv->m = defaultMethods; + pEnv->m.pMemEnv = (void*)pEnv; } #endif /* SQLITE_SYSTEM_MALLOC */ Index: src/mem2.c ================================================================== --- src/mem2.c +++ src/mem2.c @@ -184,26 +184,27 @@ } /* ** Initialize the memory allocation subsystem. */ -static int sqlite4MemInit(void *pMem){ - assert( pMem==(void*)&mem2 ); +static int sqlite4MemInit(void *pMallocEnv){ + sqlite4_env *pEnv = (sqlite4_env*)pMallocEnv; + int rc = SQLITE_OK; assert( (sizeof(struct MemBlockHdr)&7) == 0 ); - if( !sqlite4DefaultEnv.bMemstat ){ - /* If memory status is enabled, then the malloc.c wrapper will already - ** hold the STATIC_MEM mutex when the routines here are invoked. */ - mem2.mutex = sqlite4MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + if( !pEnv->bMemstat ){ + mem2.mutex = sqlite4MutexAlloc(pEnv, SQLITE_MUTEX_FAST); + if( mem2.mutex==0 && pEnv->bCoreMutex ) rc = SQLITE_NOMEM; } - return SQLITE_OK; + return rc; } /* ** Deinitialize the memory allocation subsystem. */ -static void sqlite4MemShutdown(void *pMem){ - assert( pMem==(void*)&mem2 ); +static void sqlite4MemShutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); + sqlite4_mutex_free(mem2.mutex); mem2.mutex = 0; } /* ** Fill a buffer with pseudo-random bytes. This is used to preset @@ -392,11 +393,11 @@ ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite4MemdebugHasType(p, MEMTYPE_DB) ); */ -int sqlite4MemdebugHasType(void *p, u8 eType){ +int sqlite4MemdebugHasType(const void *p, u8 eType){ int rc = 1; if( p && sqlite4DefaultEnv.m.xMalloc==sqlite4MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite4MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ @@ -414,11 +415,11 @@ ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite4MemdebugNoType(p, MEMTYPE_DB) ); */ -int sqlite4MemdebugNoType(void *p, u8 eType){ +int sqlite4MemdebugNoType(const void *p, u8 eType){ int rc = 1; if( p && sqlite4DefaultEnv.m.xMalloc==sqlite4MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite4MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ Index: src/mutex.c ================================================================== --- src/mutex.c +++ src/mutex.c @@ -12,106 +12,75 @@ ** This file contains the C functions that implement mutexes. ** ** This file contains code that is common across all mutex implementations. */ #include "sqliteInt.h" - -#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) -/* -** For debugging purposes, record when the mutex subsystem is initialized -** and uninitialized so that we can assert() if there is an attempt to -** allocate a mutex while the system is uninitialized. -*/ -static SQLITE_WSD int mutexIsInit = 0; -#endif /* SQLITE_DEBUG */ - #ifndef SQLITE_MUTEX_OMIT /* ** Initialize the mutex system. */ -int sqlite4MutexInit(void){ +int sqlite4MutexInit(sqlite4_env *pEnv){ int rc = SQLITE_OK; - if( !sqlite4DefaultEnv.mutex.xMutexAlloc ){ - /* If the xMutexAlloc method has not been set, then the user did not - ** install a mutex implementation via sqlite4_config() prior to - ** sqlite4_initialize() being called. This block copies pointers to - ** the default implementation into the sqlite4DefaultEnv structure. - */ - sqlite4_mutex_methods const *pFrom; - sqlite4_mutex_methods *pTo = &sqlite4DefaultEnv.mutex; - - if( sqlite4DefaultEnv.bCoreMutex ){ - pFrom = sqlite4DefaultMutex(); + if( !pEnv->mutex.xMutexAlloc ){ + if( pEnv->bCoreMutex ){ + pEnv->mutex = *sqlite4DefaultMutex(); }else{ - pFrom = sqlite4NoopMutex(); - } - memcpy(pTo, pFrom, offsetof(sqlite4_mutex_methods, xMutexAlloc)); - memcpy(&pTo->xMutexFree, &pFrom->xMutexFree, - sizeof(*pTo) - offsetof(sqlite4_mutex_methods, xMutexFree)); - pTo->xMutexAlloc = pFrom->xMutexAlloc; - } - rc = sqlite4DefaultEnv.mutex.xMutexInit(); - -#ifdef SQLITE_DEBUG - mutexIsInit = 1; -#endif - + pEnv->mutex = *sqlite4NoopMutex(); + } + pEnv->mutex.pMutexEnv = pEnv; + } + rc = pEnv->mutex.xMutexInit(pEnv->mutex.pMutexEnv); return rc; } /* ** Shutdown the mutex system. This call frees resources allocated by ** sqlite4MutexInit(). */ -int sqlite4MutexEnd(void){ +int sqlite4MutexEnd(sqlite4_env *pEnv){ int rc = SQLITE_OK; - if( sqlite4DefaultEnv.mutex.xMutexEnd ){ - rc = sqlite4DefaultEnv.mutex.xMutexEnd(); - } - -#ifdef SQLITE_DEBUG - mutexIsInit = 0; -#endif - + if( pEnv->mutex.xMutexEnd ){ + rc = pEnv->mutex.xMutexEnd(pEnv->mutex.pMutexEnv); + } return rc; } /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ -sqlite4_mutex *sqlite4_mutex_alloc(int id){ +sqlite4_mutex *sqlite4_mutex_alloc(sqlite4_env *pEnv, int id){ + if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; #ifndef SQLITE_OMIT_AUTOINIT - if( sqlite4_initialize(0) ) return 0; + if( sqlite4_initialize(pEnv) ) return 0; #endif - return sqlite4DefaultEnv.mutex.xMutexAlloc(id); + return pEnv->mutex.xMutexAlloc(pEnv->mutex.pMutexEnv, id); } -sqlite4_mutex *sqlite4MutexAlloc(int id){ - if( !sqlite4DefaultEnv.bCoreMutex ){ +sqlite4_mutex *sqlite4MutexAlloc(sqlite4_env *pEnv, int id){ + if( !pEnv->bCoreMutex ){ return 0; } - assert( mutexIsInit ); - return sqlite4DefaultEnv.mutex.xMutexAlloc(id); + return pEnv->mutex.xMutexAlloc(pEnv->mutex.pMutexEnv, id); } /* ** Free a dynamic mutex. */ void sqlite4_mutex_free(sqlite4_mutex *p){ if( p ){ - sqlite4DefaultEnv.mutex.xMutexFree(p); + p->pMutexMethods->xMutexFree(p); } } /* ** Obtain the mutex p. If some other thread already has the mutex, block ** until it can be obtained. */ void sqlite4_mutex_enter(sqlite4_mutex *p){ if( p ){ - sqlite4DefaultEnv.mutex.xMutexEnter(p); + p->pMutexMethods->xMutexEnter(p); } } /* ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another @@ -118,11 +87,11 @@ ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. */ int sqlite4_mutex_try(sqlite4_mutex *p){ int rc = SQLITE_OK; if( p ){ - return sqlite4DefaultEnv.mutex.xMutexTry(p); + return p->pMutexMethods->xMutexTry(p); } return rc; } /* @@ -131,23 +100,23 @@ ** is not currently entered. If a NULL pointer is passed as an argument ** this function is a no-op. */ void sqlite4_mutex_leave(sqlite4_mutex *p){ if( p ){ - sqlite4DefaultEnv.mutex.xMutexLeave(p); + p->pMutexMethods->xMutexLeave(p); } } #ifndef NDEBUG /* ** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are ** intended for use inside assert() statements. */ int sqlite4_mutex_held(sqlite4_mutex *p){ - return p==0 || sqlite4DefaultEnv.mutex.xMutexHeld(p); + return p==0 || p->pMutexMethods->xMutexHeld(p); } int sqlite4_mutex_notheld(sqlite4_mutex *p){ - return p==0 || sqlite4DefaultEnv.mutex.xMutexNotheld(p); + return p==0 || p->pMutexMethods->xMutexNotheld(p); } #endif #endif /* !defined(SQLITE_MUTEX_OMIT) */ Index: src/mutex.h ================================================================== --- src/mutex.h +++ src/mutex.h @@ -52,19 +52,19 @@ #ifdef SQLITE_MUTEX_OMIT /* ** If this is a no-op implementation, implement everything as macros. */ -#define sqlite4_mutex_alloc(X) ((sqlite4_mutex*)8) +#define sqlite4_mutex_alloc(X,Y) ((sqlite4_mutex*)8) #define sqlite4_mutex_free(X) #define sqlite4_mutex_enter(X) #define sqlite4_mutex_try(X) SQLITE_OK #define sqlite4_mutex_leave(X) #define sqlite4_mutex_held(X) ((void)(X),1) #define sqlite4_mutex_notheld(X) ((void)(X),1) -#define sqlite4MutexAlloc(X) ((sqlite4_mutex*)8) -#define sqlite4MutexInit() SQLITE_OK -#define sqlite4MutexEnd() +#define sqlite4MutexAlloc(X,Y) ((sqlite4_mutex*)8) +#define sqlite4MutexInit(E) SQLITE_OK +#define sqlite4MutexEnd(E) #define MUTEX_LOGIC(X) #else #define MUTEX_LOGIC(X) X #endif /* defined(SQLITE_MUTEX_OMIT) */ Index: src/mutex_noop.c ================================================================== --- src/mutex_noop.c +++ src/mutex_noop.c @@ -33,13 +33,14 @@ /* ** Stub routines for all mutex methods. ** ** This routines provide no mutual exclusion or error checking. */ -static int noopMutexInit(void){ return SQLITE_OK; } -static int noopMutexEnd(void){ return SQLITE_OK; } -static sqlite4_mutex *noopMutexAlloc(int id){ +static int noopMutexInit(void *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } +static int noopMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } +static sqlite4_mutex *noopMutexAlloc(sqlite4_env *pEnv, int id){ + UNUSED_PARAMETER(pEnv); UNUSED_PARAMETER(id); return (sqlite4_mutex*)8; } static void noopMutexFree(sqlite4_mutex *p){ UNUSED_PARAMETER(p); return; } static void noopMutexEnter(sqlite4_mutex *p){ UNUSED_PARAMETER(p); return; } @@ -56,15 +57,14 @@ noopMutexAlloc, noopMutexFree, noopMutexEnter, noopMutexTry, noopMutexLeave, - 0, 0, + 0 }; - return &sMutex; } #endif /* !SQLITE_DEBUG */ #ifdef SQLITE_DEBUG @@ -75,71 +75,59 @@ */ /* ** The mutex object */ -typedef struct sqlite4_debug_mutex { - int id; /* The mutex type */ - int cnt; /* Number of entries without a matching leave */ -} sqlite4_debug_mutex; +typedef struct sqlite4DebugMutex { + sqlite4_mutex base; /* Base class. Must be first */ + sqlite4_env *pEnv; /* Run-time environment */ + int id; /* Type of mutex */ + int cnt; /* Number of entries without a matching leave */ +} sqlite4DebugMutex; /* ** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are ** intended for use inside assert() statements. */ static int debugMutexHeld(sqlite4_mutex *pX){ - sqlite4_debug_mutex *p = (sqlite4_debug_mutex*)pX; + sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX; return p==0 || p->cnt>0; } static int debugMutexNotheld(sqlite4_mutex *pX){ - sqlite4_debug_mutex *p = (sqlite4_debug_mutex*)pX; + sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX; return p==0 || p->cnt==0; } /* ** Initialize and deinitialize the mutex subsystem. */ -static int debugMutexInit(void){ return SQLITE_OK; } -static int debugMutexEnd(void){ return SQLITE_OK; } +static int debugMutexInit(void *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } +static int debugMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } /* ** The sqlite4_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. */ -static sqlite4_mutex *debugMutexAlloc(int id){ - static sqlite4_debug_mutex aStatic[6]; - sqlite4_debug_mutex *pNew = 0; - switch( id ){ - case SQLITE_MUTEX_FAST: - case SQLITE_MUTEX_RECURSIVE: { - pNew = sqlite4Malloc(0, sizeof(*pNew)); - if( pNew ){ - pNew->id = id; - pNew->cnt = 0; - } - break; - } - default: { - assert( id-2 >= 0 ); - assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) ); - pNew = &aStatic[id-2]; - pNew->id = id; - break; - } +static sqlite4_mutex *debugMutexAlloc(sqlite4_env *pEnv, int id){ + sqlite4DebugMutex *pNew = 0; + pNew = sqlite4Malloc(pEnv, sizeof(*pNew)); + if( pNew ){ + pNew->id = id; + pNew->cnt = 0; + pNew->pEnv = pEnv; } return (sqlite4_mutex*)pNew; } /* ** This routine deallocates a previously allocated mutex. */ static void debugMutexFree(sqlite4_mutex *pX){ - sqlite4_debug_mutex *p = (sqlite4_debug_mutex*)pX; + sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX; assert( p->cnt==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); - sqlite4_free(0, p); + sqlite4_free(p->pEnv, p); } /* ** The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt ** to enter a mutex. If another thread is already within the mutex, @@ -150,16 +138,16 @@ ** mutex must be exited an equal number of times before another thread ** can enter. If the same thread tries to enter any other kind of mutex ** more than once, the behavior is undefined. */ static void debugMutexEnter(sqlite4_mutex *pX){ - sqlite4_debug_mutex *p = (sqlite4_debug_mutex*)pX; + sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX; assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); p->cnt++; } static int debugMutexTry(sqlite4_mutex *pX){ - sqlite4_debug_mutex *p = (sqlite4_debug_mutex*)pX; + sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX; assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); p->cnt++; return SQLITE_OK; } @@ -168,11 +156,11 @@ ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ static void debugMutexLeave(sqlite4_mutex *pX){ - sqlite4_debug_mutex *p = (sqlite4_debug_mutex*)pX; + sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX; assert( debugMutexHeld(pX) ); p->cnt--; assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); } @@ -183,13 +171,13 @@ debugMutexAlloc, debugMutexFree, debugMutexEnter, debugMutexTry, debugMutexLeave, - debugMutexHeld, - debugMutexNotheld + debugMutexNotheld, + 0 }; return &sMutex; } #endif /* SQLITE_DEBUG */ Index: src/mutex_unix.c ================================================================== --- src/mutex_unix.c +++ src/mutex_unix.c @@ -36,23 +36,25 @@ #endif /* ** Each recursive mutex is an instance of the following structure. */ -struct sqlite4_mutex { +typedef struct sqlite4UnixMutex { + sqlite4_mutex base; /* Base class. Must be first */ pthread_mutex_t mutex; /* Mutex controlling the lock */ #if SQLITE_MUTEX_NREF int id; /* Mutex type */ volatile int nRef; /* Number of entrances */ volatile pthread_t owner; /* Thread that is within this mutex */ int trace; /* True to trace changes */ #endif -}; +} sqlite4UnixMutex; #if SQLITE_MUTEX_NREF -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 } +#define SQLITE3_MUTEX_INITIALIZER \ + { 0, PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 } #else -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } +#define SQLITE3_MUTEX_INITIALIZER { 0, PTHREAD_MUTEX_INITIALIZER } #endif /* ** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are ** intended for use only inside assert() statements. On some platforms, @@ -68,23 +70,25 @@ ** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to ** make sure no assert() statements are evaluated and hence these ** routines are never called. */ #if !defined(NDEBUG) || defined(SQLITE_DEBUG) -static int pthreadMutexHeld(sqlite4_mutex *p){ +static int pthreadMutexHeld(sqlite4_mutex *pMutex){ + sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex; return (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); } -static int pthreadMutexNotheld(sqlite4_mutex *p){ +static int pthreadMutexNotheld(sqlite4_mutex *pMutex){ + sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex; return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0; } #endif /* ** Initialize and deinitialize the mutex subsystem. */ -static int pthreadMutexInit(void){ return SQLITE_OK; } -static int pthreadMutexEnd(void){ return SQLITE_OK; } +static int pthreadMutexInit(void *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } +static int pthreadMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } /* ** The sqlite4_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. SQLite @@ -124,23 +128,16 @@ ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite4_mutex_alloc() ** returns a different mutex on every call. But for the static ** mutex types, the same mutex is returned on every call that has ** the same type number. */ -static sqlite4_mutex *pthreadMutexAlloc(int iType){ - static sqlite4_mutex staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER - }; - sqlite4_mutex *p; +static sqlite4_mutex *pthreadMutexAlloc(void *pMutexEnv, int iType){ + sqlite4_env *pEnv = (sqlite4_env*)pMutexEnv; + sqlite4UnixMutex *p; switch( iType ){ case SQLITE_MUTEX_RECURSIVE: { - p = sqlite4MallocZero(0, sizeof(*p) ); + p = sqlite4MallocZero(pEnv, sizeof(*p) ); if( p ){ #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX /* If recursive mutexes are not available, we will have to ** build our own. See below. */ pthread_mutex_init(&p->mutex, 0); @@ -153,47 +150,48 @@ pthread_mutexattr_destroy(&recursiveAttr); #endif #if SQLITE_MUTEX_NREF p->id = iType; #endif + p->base.pMutexMethods = &pEnv->mutex; } break; } case SQLITE_MUTEX_FAST: { - p = sqlite4MallocZero(0, sizeof(*p) ); + p = sqlite4MallocZero(pEnv, sizeof(*p) ); if( p ){ #if SQLITE_MUTEX_NREF p->id = iType; #endif pthread_mutex_init(&p->mutex, 0); + p->base.pMutexMethods = &pEnv->mutex; + assert( p->base.pMutexMethods->pMutexEnv==(void*)pEnv ); } break; } default: { - assert( iType-2 >= 0 ); - assert( iType-2 < ArraySize(staticMutexes) ); - p = &staticMutexes[iType-2]; -#if SQLITE_MUTEX_NREF - p->id = iType; -#endif + p = 0; break; } } - return p; + return (sqlite4_mutex*)p; } /* ** This routine deallocates a previously ** allocated mutex. SQLite is careful to deallocate every ** mutex that it allocates. */ -static void pthreadMutexFree(sqlite4_mutex *p){ +static void pthreadMutexFree(sqlite4_mutex *pMutex){ + sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex; + sqlite4_env *pEnv; assert( p->nRef==0 ); assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); pthread_mutex_destroy(&p->mutex); - sqlite4_free(0, p); + pEnv = (sqlite4_env*)p->base.pMutexMethods->pMutexEnv; + sqlite4_free(pEnv, p); } /* ** The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt ** to enter a mutex. If another thread is already within the mutex, @@ -203,12 +201,13 @@ ** be entered multiple times by the same thread. In such cases the, ** mutex must be exited an equal number of times before another thread ** can enter. If the same thread tries to enter any other kind of mutex ** more than once, the behavior is undefined. */ -static void pthreadMutexEnter(sqlite4_mutex *p){ - assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); +static void pthreadMutexEnter(sqlite4_mutex *pMutex){ + sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex; + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(pMutex) ); #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX /* If recursive mutexes are not available, then we have to grow ** our own. This implementation assumes that pthread_equal() ** is atomic - that it cannot be deceived into thinking self @@ -245,13 +244,14 @@ if( p->trace ){ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif } -static int pthreadMutexTry(sqlite4_mutex *p){ +static int pthreadMutexTry(sqlite4_mutex *pMutex){ int rc; - assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); + sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex; + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(pMutex) ); #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX /* If recursive mutexes are not available, then we have to grow ** our own. This implementation assumes that pthread_equal() ** is atomic - that it cannot be deceived into thinking self @@ -302,12 +302,13 @@ ** The sqlite4_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ -static void pthreadMutexLeave(sqlite4_mutex *p){ - assert( pthreadMutexHeld(p) ); +static void pthreadMutexLeave(sqlite4_mutex *pMutex){ + sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex; + assert( pthreadMutexHeld(pMutex) ); #if SQLITE_MUTEX_NREF p->nRef--; if( p->nRef==0 ) p->owner = 0; #endif assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); @@ -336,16 +337,17 @@ pthreadMutexEnter, pthreadMutexTry, pthreadMutexLeave, #ifdef SQLITE_DEBUG pthreadMutexHeld, - pthreadMutexNotheld + pthreadMutexNotheld, #else 0, - 0 + 0, #endif + 0 }; return &sMutex; } #endif /* SQLITE_MUTEX_PTHREADS */ Index: src/os.c ================================================================== --- src/os.c +++ src/os.c @@ -15,24 +15,80 @@ */ #define _SQLITE_OS_C_ 1 #include "sqliteInt.h" #undef _SQLITE_OS_C_ -int sqlite4OsRandomness(sqlite4_env *pEnv, int nByte, unsigned char *zBufOut){ - memset(zBufOut, 0, nByte); - return SQLITE_OK; -} +#if SQLITE_OS_UNIX +#include +#endif /* ** The following variable, if set to a non-zero value, is interpreted as ** the number of seconds since 1970 and is used to set the result of ** sqlite4OsCurrentTime() during testing. */ unsigned int sqlite4_current_time = 0; /* Fake system time */ int sqlite4OsCurrentTime(sqlite4_env *pEnv, sqlite4_uint64 *pTimeOut){ + int rc = SQLITE_OK; + if( sqlite4_current_time ){ + *pTimeOut = (sqlite4_uint64)sqlite4_current_time * 1000; + return SQLITE_OK; + } +#if SQLITE_OS_UNIX + static const sqlite4_int64 unixEpoch = 24405875*(sqlite4_int64)8640000; + struct timeval sNow; + if( gettimeofday(&sNow, 0)==0 ){ + *pTimeOut = unixEpoch + 1000*(sqlite4_int64)sNow.tv_sec + sNow.tv_usec/1000; + }else{ + rc = SQLITE_ERROR; + } + UNUSED_PARAMETER(pEnv); +#endif +#if SQLITE_OS_WIN + FILETIME ft; + static const sqlite4_int64 winFiletimeEpoch = + 23058135*(sqlite4_int64)8640000; + /* 2^32 - to avoid use of LL and warnings in gcc */ + static const sqlite4_int64 max32BitValue = + (sqlite4_int64)2000000000 + (sqlite4_int64)2000000000 + + (sqlite4_int64)294967296; + GetSystemTimeAsFileTime( &ft ); + *pTimeOut = winFiletimeEpoch + + ((((sqlite4_int64)ft.dwHighDateTime)*max32BitValue) + + (sqlite4_int64)ft.dwLowDateTime)/(sqlite4_int64)10000; UNUSED_PARAMETER(pEnv); - *pTimeOut = (sqlite4_uint64)sqlite4_current_time * 1000; +#endif + return rc; +} + +/* +** Write nByte bytes of randomness into zBufOut[]. This is used to initialize +** the PRNGs. nByte will always be 8. +*/ +int sqlite4OsRandomness(sqlite4_env *pEnv, int nByte, unsigned char *zBufOut){ + static sqlite4_uint64 cnt = 0; + unsigned char *p; + int i; + sqlite4_uint64 now; + sqlite4_uint64 x = 0; + +#if 0 && SQLITE_OS_UNIX + int fd = open("/dev/urandom", O_RDONLY, 0); + if( fd>=0 ){ + read(fd, zBufOut, nByte); + close(fd); + } + x = getpid(); +#endif + sqlite4OsCurrentTime(pEnv, &now); + x ^= now; + memset(zBufOut, 0, nByte); + cnt++; + x ^= cnt; + p = (unsigned char*)&x; + for(i=0; i<8; i++) zBufOut[i%nByte] ^= p[i]; + return SQLITE_OK; } /* ** This function is a wrapper around the OS specific implementation of @@ -42,7 +98,8 @@ */ int sqlite4OsInit(sqlite4_env *pEnv){ void *p = sqlite4_malloc(pEnv, 10); if( p==0 ) return SQLITE_NOMEM; sqlite4_free(pEnv, p); + sqlite4OsRandomness(pEnv, 8, (unsigned char*)&pEnv->prngX); return SQLITE_OK; /*sqlite4_os_init();*/ } Index: src/random.c ================================================================== --- src/random.c +++ src/random.c @@ -16,122 +16,27 @@ ** to generate random integer keys for tables or random filenames. */ #include "sqliteInt.h" -/* All threads share a single random number generator. -** This structure is the current state of the generator. -*/ -static SQLITE_WSD struct sqlite4PrngType { - unsigned char isInit; /* True if initialized */ - unsigned char i, j; /* State variables */ - unsigned char s[256]; /* State variables */ -} sqlite4Prng; - -/* -** Get a single 8-bit random value from the RC4 PRNG. The Mutex -** must be held while executing this routine. -** -** Why not just use a library random generator like lrand48() for this? -** Because the OP_NewRowid opcode in the VDBE depends on having a very -** good source of random numbers. The lrand48() library function may -** well be good enough. But maybe not. Or maybe lrand48() has some -** subtle problems on some systems that could cause problems. It is hard -** to know. To minimize the risk of problems due to bad lrand48() -** implementations, SQLite uses this random number generator based -** on RC4, which we know works very well. -** -** (Later): Actually, OP_NewRowid does not depend on a good source of -** randomness any more. But we will leave this code in all the same. -*/ -static u8 randomByte(void){ - unsigned char t; - - - /* The "wsdPrng" macro will resolve to the pseudo-random number generator - ** state vector. If writable static data is unsupported on the target, - ** we have to locate the state vector at run-time. In the more common - ** case where writable static data is supported, wsdPrng can refer directly - ** to the "sqlite4Prng" state vector declared above. - */ -#ifdef SQLITE_OMIT_WSD - struct sqlite4PrngType *p = sqlite4Prng; -# define wsdPrng p[0] -#else -# define wsdPrng sqlite4Prng -#endif - - - /* Initialize the state of the random number generator once, - ** the first time this routine is called. The seed value does - ** not need to contain a lot of randomness since we are not - ** trying to do secure encryption or anything like that... - ** - ** Nothing in this file or anywhere else in SQLite does any kind of - ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random - ** number generator) not as an encryption device. - */ - if( !wsdPrng.isInit ){ - int i; - char k[256]; - wsdPrng.j = 0; - wsdPrng.i = 0; - sqlite4OsRandomness(0, 256, k); - for(i=0; i<256; i++){ - wsdPrng.s[i] = (u8)i; - } - for(i=0; i<256; i++){ - wsdPrng.j += wsdPrng.s[i] + k[i]; - t = wsdPrng.s[wsdPrng.j]; - wsdPrng.s[wsdPrng.j] = wsdPrng.s[i]; - wsdPrng.s[i] = t; - } - wsdPrng.isInit = 1; - } - - /* Generate and return single random byte - */ - wsdPrng.i++; - t = wsdPrng.s[wsdPrng.i]; - wsdPrng.j += t; - wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j]; - wsdPrng.s[wsdPrng.j] = t; - t += wsdPrng.s[wsdPrng.i]; - return wsdPrng.s[t]; +/* +** Get a single 8-bit random value from the PRNG. The Mutex +** must be held while executing this routine. +*/ +static u8 randomByte(sqlite4_env *pEnv){ + pEnv->prngX = (pEnv->prngX>>1) ^ ((-(pEnv->prngX&1)) & 0xd0000001); + pEnv->prngY = pEnv->prngY*1103515245 + 12345; + return (u8)((pEnv->prngX ^ pEnv->prngY)&0xff); } /* ** Return N random bytes. */ void sqlite4_randomness(sqlite4_env *pEnv, int N, void *pBuf){ unsigned char *zBuf = pBuf; -#if SQLITE_THREADSAFE - sqlite4_mutex *mutex = sqlite4MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); -#endif - sqlite4_mutex_enter(mutex); - while( N-- ){ - *(zBuf++) = randomByte(); - } - sqlite4_mutex_leave(mutex); -} - -#ifndef SQLITE_OMIT_BUILTIN_TEST -/* -** For testing purposes, we sometimes want to preserve the state of -** PRNG and restore the PRNG to its saved state at a later time, or -** to reset the PRNG to its initial state. These routines accomplish -** those tasks. -** -** The sqlite4_test_control() interface calls these routines to -** control the PRNG. -*/ -static SQLITE_WSD struct sqlite4PrngType sqlite4SavedPrng; -void sqlite4PrngSaveState(void){ - memcpy(&sqlite4SavedPrng, &sqlite4Prng, sizeof(sqlite4Prng)); -} -void sqlite4PrngRestoreState(void){ - memcpy(&sqlite4Prng, &sqlite4SavedPrng, sizeof(sqlite4Prng)); -} -void sqlite4PrngResetState(void){ - sqlite4Prng.isInit = 0; -} -#endif /* SQLITE_OMIT_BUILTIN_TEST */ + if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; + sqlite4_mutex_enter(pEnv->pPrngMutex); + while( N-- ){ + *(zBuf++) = randomByte(pEnv); + } + sqlite4_mutex_leave(pEnv->pPrngMutex); +} Index: src/shell.c ================================================================== --- src/shell.c +++ src/shell.c @@ -2119,13 +2119,10 @@ if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ static const struct { const char *zCtrlName; /* Name of a test-control option */ int ctrlCode; /* Integer code for that option */ } aCtrl[] = { - { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, - { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, - { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, { "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS }, { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE }, { "assert", SQLITE_TESTCTRL_ASSERT }, { "always", SQLITE_TESTCTRL_ALWAYS }, @@ -2167,22 +2164,10 @@ printf("%d (0x%08x)\n", rc, rc); } else { fprintf(stderr,"Error: testctrl %s takes a single int option\n", azArg[1]); } - break; - - /* sqlite4_test_control(int) */ - case SQLITE_TESTCTRL_PRNG_SAVE: - case SQLITE_TESTCTRL_PRNG_RESTORE: - case SQLITE_TESTCTRL_PRNG_RESET: - if( nArg==2 ){ - rc = sqlite4_test_control(testctrl); - printf("%d (0x%08x)\n", rc, rc); - } else { - fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]); - } break; /* sqlite4_test_control(int, uint) */ case SQLITE_TESTCTRL_PENDING_BYTE: if( nArg==3 ){ Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -121,10 +121,11 @@ #define SQLITE_ENVCONFIG_MEMSTATUS 9 /* boolean */ #define SQLITE_ENVCONFIG_LOOKASIDE 10 /* size, count */ #define SQLITE_ENVCONFIG_LOG 11 /* xLog, pArg */ #define SQLITE_ENVCONFIG_KVSTORE_PUSH 12 /* name, factory */ #define SQLITE_ENVCONFIG_KVSTORE_POP 13 /* name */ +#define SQLITE_ENVCONFIG_KVSTORE_GET 14 /* name, *factor */ /* ** CAPIREF: Compile-Time Library Version Numbers ** @@ -533,10 +534,14 @@ ** deals with pointers to the [sqlite4_mutex] object. ** ** Mutexes are created using [sqlite4_mutex_alloc()]. */ typedef struct sqlite4_mutex sqlite4_mutex; +struct sqlite4_mutex { + struct sqlite4_mutex_methods *pMutexMethods; + /* Subclasses will typically add additional fields */ +}; /* ** CAPIREF: Initialize The SQLite Library ** ** ^The sqlite4_initialize(A) routine initializes an sqlite4_env object A. @@ -648,14 +653,14 @@ ** An instance of this object defines the interface between SQLite ** and low-level memory allocation routines. ** ** This object is used in only one place in the SQLite interface. ** A pointer to an instance of this object is the argument to -** [sqlite4_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** [sqlite4_env_config()] when the configuration option is +** [SQLITE_ENVCONFIG_MALLOC] or [SQLITE_ENVCONFIG_GETMALLOC]. ** By creating an instance of this object -** and passing it to [sqlite4_config]([SQLITE_CONFIG_MALLOC]) +** and passing it to [sqlite4_env_config]([SQLITE_ENVCONFIG_MALLOC]) ** during configuration, an application can specify an alternative ** memory allocation subsystem for SQLite to use for all of its ** dynamic memory needs. ** ** Note that SQLite comes with several [built-in memory allocators] @@ -686,11 +691,11 @@ ** ** The xInit method initializes the memory allocator. (For example, ** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite4_shutdown()] and should deallocate any resources acquired -** by xInit. The pAppData pointer is used as the only parameter to +** by xInit. The pMemEnv pointer is used as the only parameter to ** xInit and xShutdown. ** ** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes ** the xInit method, so the xInit method need not be threadsafe. The ** xShutdown method is only called from [sqlite4_shutdown()] so it does @@ -713,175 +718,13 @@ sqlite4_size_t (*xSize)(void*,void*); /* Return the size of an allocation */ int (*xInit)(void*); /* Initialize the memory allocator */ void (*xShutdown)(void*); /* Deinitialize the allocator */ void (*xBeginBenign)(void*); /* Enter a benign malloc region */ void (*xEndBenign)(void*); /* Leave a benign malloc region */ - void *pAppData; /* 1st argument to all routines */ + void *pMemEnv; /* 1st argument to all routines */ }; -/* -** CAPIREF: Configuration Options -** KEYWORDS: {configuration option} -** -** These constants are the available integer configuration options that -** can be passed as the first argument to the [sqlite4_config()] interface. -** -** New configuration options may be added in future releases of SQLite. -** Existing configuration options might be discontinued. Applications -** should check the return code from [sqlite4_config()] to make sure that -** the call worked. The [sqlite4_config()] interface will return a -** non-zero [error code] if a discontinued or unsupported configuration option -** is invoked. -** -**
-** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Single-thread. In other words, it disables -** all mutexing and puts SQLite into a mode where it can only be used -** by a single thread. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to change the [threading mode] from its default -** value of Single-thread and so [sqlite4_config()] will return -** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD -** configuration option.
-** -** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Multi-thread. In other words, it disables -** mutexing on [database connection] and [prepared statement] objects. -** The application is responsible for serializing access to -** [database connections] and [prepared statements]. But other mutexes -** are enabled so that SQLite will be safe to use in a multi-threaded -** environment as long as no two threads attempt to use the same -** [database connection] at the same time. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to set the Multi-thread [threading mode] and -** [sqlite4_config()] will return [SQLITE_ERROR] if called with the -** SQLITE_CONFIG_MULTITHREAD configuration option.
-** -** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Serialized. In other words, this option enables -** all mutexes including the recursive -** mutexes on [database connection] and [prepared statement] objects. -** In this mode (which is the default when SQLite is compiled with -** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access -** to [database connections] and [prepared statements] so that the -** application is free to use the same [database connection] or the -** same [prepared statement] in different threads at the same time. -** ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to set the Serialized [threading mode] and -** [sqlite4_config()] will return [SQLITE_ERROR] if called with the -** SQLITE_CONFIG_SERIALIZED configuration option.
-** -** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite4_mem_methods] structure. The argument specifies -** alternative low-level memory allocation routines to be used in place of -** the memory allocation routines built into SQLite.)^ ^SQLite makes -** its own private copy of the content of the [sqlite4_mem_methods] structure -** before the [sqlite4_config()] call returns.
-** -** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite4_mem_methods] structure. The [sqlite4_mem_methods] -** structure is filled with the currently defined memory allocation routines.)^ -** This option can be used to overload the default memory allocation -** routines with a wrapper that simulations memory allocation failure or -** tracks memory usage, for example.
-** -** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
-**
^This option takes single argument of type int, interpreted as a -** boolean, which enables or disables the collection of memory allocation -** statistics. ^(When memory allocation statistics are disabled, the -** following SQLite interfaces become non-operational: -**
    -**
  • [sqlite4_memory_used()] -**
  • [sqlite4_memory_highwater()] -**
  • [sqlite4_soft_heap_limit64()] -**
  • [sqlite4_status()] -**
)^ -** ^Memory allocation statistics are enabled by default unless SQLite is -** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory -** allocation statistics are disabled by default. -**
-** -** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
-**
^This option specifies a static memory buffer that SQLite will use -** for all of its dynamic memory allocation needs beyond those provided -** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. -** There are three arguments: An 8-byte aligned pointer to the memory, -** the number of bytes in the memory buffer, and the minimum allocation size. -** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts -** to using its default memory allocator (the system malloc() implementation), -** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the -** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or -** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory -** allocator is engaged to handle all of SQLites memory allocation needs. -** The first pointer (the memory pointer) must be aligned to an 8-byte -** boundary or subsequent behavior of SQLite will be undefined. -** The minimum allocation size is capped at 2**12. Reasonable values -** for the minimum allocation size are 2**5 through 2**8.
-** -** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite4_mutex_methods] structure. The argument specifies -** alternative low-level mutex routines to be used in place -** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the -** content of the [sqlite4_mutex_methods] structure before the call to -** [sqlite4_config()] returns. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** the entire mutexing subsystem is omitted from the build and hence calls to -** [sqlite4_config()] with the SQLITE_CONFIG_MUTEX configuration option will -** return [SQLITE_ERROR].
-** -** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite4_mutex_methods] structure. The -** [sqlite4_mutex_methods] -** structure is filled with the currently defined mutex routines.)^ -** This option can be used to overload the default mutex allocation -** routines with a wrapper used to track mutex usage for performance -** profiling or testing, for example. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** the entire mutexing subsystem is omitted from the build and hence calls to -** [sqlite4_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will -** return [SQLITE_ERROR].
-** -** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
-**
^(This option takes two arguments that determine the default -** memory allocation for the lookaside memory allocator on each -** [database connection]. The first argument is the -** size of each lookaside buffer slot and the second is the number of -** slots allocated to each database connection.)^ ^(This option sets the -** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] -** verb to [sqlite4_db_config()] can be used to change the lookaside -** configuration on individual connections.)^
-** -** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
-**
^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,int,const char*), -** and a pointer to void. ^If the function pointer is not NULL, it is -** invoked by [sqlite4_log()] to process each logging event. ^If the -** function pointer is NULL, the [sqlite4_log()] interface becomes a no-op. -** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is -** passed through as the first parameter to the application-defined logger -** function whenever that function is invoked. ^The second parameter to -** the logger function is a copy of the first parameter to the corresponding -** [sqlite4_log()] call and is intended to be a [result code] or an -** [extended result code]. ^The third parameter passed to the logger is -** log message after formatting via [sqlite4_snprintf()]. -** The SQLite logging interface is not reentrant; the logger function -** supplied by the application must not invoke any SQLite interface. -** In a multi-threaded application, the application-defined logger -** function must be threadsafe.
-** -**
-*/ -#define SQLITE_CONFIG_SET_KVFACTORY 20 /* int(*)(KVStore**,const char*,u32) */ -#define SQLITE_CONFIG_GET_KVFACTORY 21 /* int(**)(KVStore**,const char*,u32) */ /* ** CAPIREF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that @@ -3675,10 +3518,13 @@ ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ int sqlite4_overload_function(sqlite4*, const char *zFuncName, int nArg); +/* +** + /* ** CAPIREF: Mutexes ** ** The SQLite core uses these routines for thread ** synchronization. Though they are intended for internal @@ -3717,50 +3563,23 @@ ** to sqlite4_mutex_alloc() is one of these integer constants: ** **
    **
  • SQLITE_MUTEX_FAST **
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
  • SQLITE_MUTEX_STATIC_LRU2 **
)^ ** -** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) -** cause sqlite4_mutex_alloc() to create -** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. ** The mutex implementation does not need to make a distinction ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does ** not want to. ^SQLite will only request a recursive mutex in ** cases where it really needs one. ^If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** -** ^The other allowed parameters to sqlite4_mutex_alloc() (anything other -** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return -** a pointer to a static preexisting mutex. ^Six static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite4_mutex_alloc() -** returns a different mutex on every call. ^But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. -** ** ^The sqlite4_mutex_free() routine deallocates a previously -** allocated dynamic mutex. ^SQLite is careful to deallocate every -** dynamic mutex that it allocates. The dynamic mutexes must not be in -** use when they are deallocated. Attempting to deallocate a static -** mutex results in undefined behavior. ^SQLite never deallocates -** a static mutex. +** allocated mutex. ** ** ^The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt ** to enter a mutex. ^If another thread is already within the mutex, ** sqlite4_mutex_enter() will block and sqlite4_mutex_try() will return ** SQLITE_BUSY. ^The sqlite4_mutex_try() interface returns [SQLITE_OK] @@ -3788,11 +3607,11 @@ ** sqlite4_mutex_leave() is a NULL pointer, then all three routines ** behave as no-ops. ** ** See also: [sqlite4_mutex_held()] and [sqlite4_mutex_notheld()]. */ -sqlite4_mutex *sqlite4_mutex_alloc(int); +sqlite4_mutex *sqlite4_mutex_alloc(sqlite4_env*, int); void sqlite4_mutex_free(sqlite4_mutex*); void sqlite4_mutex_enter(sqlite4_mutex*); int sqlite4_mutex_try(sqlite4_mutex*); void sqlite4_mutex_leave(sqlite4_mutex*); @@ -3861,19 +3680,20 @@ ** If xMutexInit fails in any way, it is expected to clean up after itself ** prior to returning. */ typedef struct sqlite4_mutex_methods sqlite4_mutex_methods; struct sqlite4_mutex_methods { - int (*xMutexInit)(void); - int (*xMutexEnd)(void); - sqlite4_mutex *(*xMutexAlloc)(int); + int (*xMutexInit)(void*); + int (*xMutexEnd)(void*); + sqlite4_mutex *(*xMutexAlloc)(void*,int); void (*xMutexFree)(sqlite4_mutex *); void (*xMutexEnter)(sqlite4_mutex *); int (*xMutexTry)(sqlite4_mutex *); void (*xMutexLeave)(sqlite4_mutex *); int (*xMutexHeld)(sqlite4_mutex *); int (*xMutexNotheld)(sqlite4_mutex *); + void *pMutexEnv; }; /* ** CAPIREF: Mutex Verification Routines ** @@ -3918,18 +3738,10 @@ ** next. Applications that override the built-in mutex logic must be ** prepared to accommodate additional static mutexes. */ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite4_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_OPEN 4 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite4_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ -#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite4PageMalloc() */ /* ** CAPIREF: Retrieve the mutex for a database connection ** ** ^This interface returns a pointer the [sqlite4_mutex] object that @@ -4010,25 +3822,22 @@ ** These parameters and their meanings are subject to change ** without notice. These values are for testing purposes only. ** Applications should not use any of these parameters or the ** [sqlite4_test_control()] interface. */ -#define SQLITE_TESTCTRL_FIRST 5 -#define SQLITE_TESTCTRL_PRNG_SAVE 5 -#define SQLITE_TESTCTRL_PRNG_RESTORE 6 -#define SQLITE_TESTCTRL_PRNG_RESET 7 -#define SQLITE_TESTCTRL_FAULT_INSTALL 9 -#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 -#define SQLITE_TESTCTRL_PENDING_BYTE 11 -#define SQLITE_TESTCTRL_ASSERT 12 -#define SQLITE_TESTCTRL_ALWAYS 13 -#define SQLITE_TESTCTRL_RESERVE 14 -#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 -#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 -#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 -#define SQLITE_TESTCTRL_LAST 19 +#define SQLITE_TESTCTRL_FIRST 1 +#define SQLITE_TESTCTRL_FAULT_INSTALL 2 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 3 +#define SQLITE_TESTCTRL_PENDING_BYTE 4 +#define SQLITE_TESTCTRL_ASSERT 5 +#define SQLITE_TESTCTRL_ALWAYS 6 +#define SQLITE_TESTCTRL_RESERVE 7 +#define SQLITE_TESTCTRL_OPTIMIZATIONS 8 +#define SQLITE_TESTCTRL_ISKEYWORD 9 +#define SQLITE_TESTCTRL_LOCALTIME_FAULT 10 +#define SQLITE_TESTCTRL_EXPLAIN_STMT 11 +#define SQLITE_TESTCTRL_LAST 11 /* ** CAPIREF: SQLite Runtime Status ** ** ^This interface is used to retrieve runtime status information Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2411,20 +2411,19 @@ int (*xRandomness)(sqlite4_env*, int, unsigned char*); int (*xCurrentTime)(sqlite4_env*, sqlite4_uint64*); /* The above might be initialized to non-zero. The following need to always ** initially be zero, however. */ int isInit; /* True after initialization has finished */ - int inProgress; /* True while initialization in progress */ - int isMutexInit; /* True after mutexes are initialized */ - int isMallocInit; /* True after malloc is initialized */ - sqlite4_mutex *pInitMutex; /* Mutex used by sqlite4_initialize() */ - int nRefInitMutex; /* Number of users of pInitMutex */ + sqlite4_mutex *pPrngMutex; /* Mutex for the PRNG */ + u32 prngX, prngY; /* State of the PRNG */ void (*xLog)(void*,int,const char*); /* Function for logging */ void *pLogArg; /* First argument to xLog() */ int bLocaltimeFault; /* True to fail localtime() calls */ + sqlite4_mutex *pMemMutex; /* Mutex for nowValue[] and mxValue[] */ sqlite4_uint64 nowValue[4]; /* sqlite4_env_status() current values */ sqlite4_uint64 mxValue[4]; /* sqlite4_env_status() max values */ + FuncDefHash hashGlobalFuncs; /* Hash table of global functions */ }; /* ** Context pointer passed down through the tree-walk. */ @@ -2570,13 +2569,13 @@ #ifndef SQLITE_MUTEX_OMIT sqlite4_mutex_methods const *sqlite4DefaultMutex(void); sqlite4_mutex_methods const *sqlite4NoopMutex(void); - sqlite4_mutex *sqlite4MutexAlloc(int); - int sqlite4MutexInit(void); - int sqlite4MutexEnd(void); + sqlite4_mutex *sqlite4MutexAlloc(sqlite4_env*,int); + int sqlite4MutexInit(sqlite4_env*); + int sqlite4MutexEnd(sqlite4_env*); #endif void sqlite4StatusAdd(sqlite4_env*, int, sqlite4_int64); void sqlite4StatusSet(sqlite4_env*, int, sqlite4_uint64); @@ -2957,11 +2956,11 @@ extern int sqlite4PendingByte; #endif #endif void sqlite4RootPageMoved(sqlite4*, int, int, int); void sqlite4Reindex(Parse*, Token*, Token*); -void sqlite4AlterFunctions(void); +void sqlite4AlterFunctions(sqlite4_env*); void sqlite4AlterRenameTable(Parse*, SrcList*, Token*); int sqlite4GetToken(const unsigned char *, int *); void sqlite4NestedParse(Parse*, const char*, ...); void sqlite4ExpirePreparedStatements(sqlite4*); int sqlite4CodeSubselect(Parse *, Expr *, int, int); @@ -3196,12 +3195,12 @@ ** All of this is no-op for a production build. It only comes into ** play when the SQLITE_MEMDEBUG compile-time option is used. */ #ifdef SQLITE_MEMDEBUG void sqlite4MemdebugSetType(void*,u8); - int sqlite4MemdebugHasType(void*,u8); - int sqlite4MemdebugNoType(void*,u8); + int sqlite4MemdebugHasType(const void*,u8); + int sqlite4MemdebugNoType(const void*,u8); #else # define sqlite4MemdebugSetType(X,Y) /* no-op */ # define sqlite4MemdebugHasType(X,Y) 1 # define sqlite4MemdebugNoType(X,Y) 1 #endif Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -193,10 +193,15 @@ const char *z, /* String pointer */ int n, /* Bytes in string, or negative */ u8 enc, /* Encoding of z. 0 for BLOBs */ void (*xDel)(void*) /* Destructor function */ ){ + if( xDel==SQLITE_DYNAMIC ){ + assert( sqlite4MemdebugHasType(z, MEMTYPE_HEAP) ); + assert( sqlite4MemdebugNoType(z, ~MEMTYPE_HEAP) ); + sqlite4MemdebugSetType(z, MEMTYPE_DB | MEMTYPE_HEAP); + } if( sqlite4VdbeMemSetStr(&pCtx->s, z, n, enc, xDel)==SQLITE_TOOBIG ){ sqlite4_result_error_toobig(pCtx); } } void sqlite4_result_blob( Index: test/log1.test ================================================================== --- test/log1.test +++ test/log1.test @@ -436,10 +436,11 @@ execsql { SELECT count(*) FROM t1 ; PRAGMA integrity_check } db2 } {21 ok} db2 close do_test 11.21 { sqlite4_lsm_work db main -flush } {0} +db eval {SELECT randstr(5,5)} do_execsql_test 11.22 { INSERT INTO t1 VALUES(randstr(10,10), randstr(100,100)); } do_test 11.23 { sqlite4_lsm_info db main log-structure Index: test/test_main.c ================================================================== --- test/test_main.c +++ test/test_main.c @@ -3971,55 +3971,10 @@ rc = sqlite4_limit(db, id, val); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } -/* -** tclcmd: save_prng_state -** -** Save the state of the pseudo-random number generator. -** At the same time, verify that sqlite4_test_control works even when -** called with an out-of-range opcode. -*/ -static int save_prng_state( - ClientData clientData, /* Pointer to sqlite4_enable_XXX function */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - int rc = sqlite4_test_control(9999); - assert( rc==0 ); - rc = sqlite4_test_control(-1); - assert( rc==0 ); - sqlite4_test_control(SQLITE_TESTCTRL_PRNG_SAVE); - return TCL_OK; -} -/* -** tclcmd: restore_prng_state -*/ -static int restore_prng_state( - ClientData clientData, /* Pointer to sqlite4_enable_XXX function */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - sqlite4_test_control(SQLITE_TESTCTRL_PRNG_RESTORE); - return TCL_OK; -} -/* -** tclcmd: reset_prng_state -*/ -static int reset_prng_state( - ClientData clientData, /* Pointer to sqlite4_enable_XXX function */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - sqlite4_test_control(SQLITE_TESTCTRL_PRNG_RESET); - return TCL_OK; -} - #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY static void test_unlock_notify_cb(void **aArg, int nArg){ int ii; for(ii=0; iipReal); } /* Return true if the countable mutex is not currently held */ -static int counterMutexNotheld(sqlite4_mutex *p){ +static int counterMutexNotheld(sqlite4_mutex *pMutex){ + sqlite4CounterMutex *p = (sqlite4CounterMutex*)pMutex; return g.m.xMutexNotheld(p->pReal); } /* Initialize the countable mutex interface ** Or, if g.disableInit is non-zero, then do not initialize but instead ** return the value of g.disableInit as the result code. This can be used ** to simulate an initialization failure. */ -static int counterMutexInit(void){ +static int counterMutexInit(void *p){ int rc; if( g.disableInit ) return g.disableInit; - rc = g.m.xMutexInit(); + rc = g.m.xMutexInit(p); g.isInit = 1; return rc; } /* ** Uninitialize the mutex subsystem */ -static int counterMutexEnd(void){ +static int counterMutexEnd(void *p){ g.isInit = 0; - return g.m.xMutexEnd(); + return g.m.xMutexEnd(p); } /* ** Allocate a countable mutex */ -static sqlite4_mutex *counterMutexAlloc(int eType){ +static sqlite4_mutex *counterMutexAlloc(void *pMutexEnv, int eType){ sqlite4_mutex *pReal; - sqlite4_mutex *pRet = 0; + sqlite4CounterMutex *pRet = 0; assert( g.isInit ); assert(eType<8 && eType>=0); - pReal = g.m.xMutexAlloc(eType); + pReal = g.m.xMutexAlloc(g.m.pMutexEnv, eType); if( !pReal ) return 0; - - if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){ - pRet = (sqlite4_mutex *)malloc(sizeof(sqlite4_mutex)); - }else{ - pRet = &g.aStatic[eType-2]; - } - + pRet = (sqlite4CounterMutex *)malloc(sizeof(*pRet)); pRet->eType = eType; pRet->pReal = pReal; - return pRet; + return (sqlite4_mutex*)pRet; } /* ** Free a countable mutex */ -static void counterMutexFree(sqlite4_mutex *p){ +static void counterMutexFree(sqlite4_mutex *pMutex){ + sqlite4CounterMutex *p = (sqlite4CounterMutex*)pMutex; assert( g.isInit ); g.m.xMutexFree(p->pReal); if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){ free(p); } @@ -106,29 +103,32 @@ } /* ** Enter a countable mutex. Block until entry is safe. */ -static void counterMutexEnter(sqlite4_mutex *p){ +static void counterMutexEnter(sqlite4_mutex *pMutex){ + sqlite4CounterMutex *p = (sqlite4CounterMutex*)pMutex; assert( g.isInit ); g.aCounter[p->eType]++; g.m.xMutexEnter(p->pReal); } /* ** Try to enter a mutex. Return true on success. */ -static int counterMutexTry(sqlite4_mutex *p){ +static int counterMutexTry(sqlite4_mutex *pMutex){ + sqlite4CounterMutex *p = (sqlite4CounterMutex*)pMutex; assert( g.isInit ); g.aCounter[p->eType]++; if( g.disableTry ) return SQLITE_BUSY; return g.m.xMutexTry(p->pReal); } /* Leave a mutex */ -static void counterMutexLeave(sqlite4_mutex *p){ +static void counterMutexLeave(sqlite4_mutex *pMutex){ + sqlite4CounterMutex *p = (sqlite4CounterMutex*)pMutex; assert( g.isInit ); g.m.xMutexLeave(p->pReal); } /* @@ -192,11 +192,12 @@ counterMutexFree, counterMutexEnter, counterMutexTry, counterMutexLeave, counterMutexHeld, - counterMutexNotheld + counterMutexNotheld, + 0 }; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); return TCL_ERROR; @@ -299,11 +300,11 @@ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ #if SQLITE_THREADSAFE - sqlite4_mutex *p = sqlite4_mutex_alloc(SQLITE_MUTEX_FAST); + sqlite4_mutex *p = sqlite4_mutex_alloc(0, SQLITE_MUTEX_FAST); char zBuf[100]; sqlite4_mutex_free(p); sqlite4_snprintf(zBuf, sizeof(zBuf), "%p", p); Tcl_AppendResult(interp, zBuf, (char*)0); #endif Index: test/test_storage2.c ================================================================== --- test/test_storage2.c +++ test/test_storage2.c @@ -287,12 +287,12 @@ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } if( kvwg.xFactory==0 ){ - sqlite4_config(0, SQLITE_CONFIG_GET_KVFACTORY, &kvwg.xFactory); - sqlite4_config(0, SQLITE_CONFIG_SET_KVFACTORY, newFileStorage); + sqlite4_env_config(0, SQLITE_ENVCONFIG_KVSTORE_GET, "main", &kvwg.xFactory); + sqlite4_env_config(0, SQLITE_ENVCONFIG_KVSTORE_PUSH, "main",newFileStorage); } return TCL_OK; } static int kvwrap_seek_cmd(Tcl_Interp *interp, int objc, Tcl_Obj **objv){ Index: test/tester.tcl ================================================================== --- test/tester.tcl +++ test/tester.tcl @@ -1036,11 +1036,11 @@ # a couple of obscure IO errors that do not return them. set ::ioerropts(-erc) 0 set ::go 1 #reset_prng_state - save_prng_state + #save_prng_state for {set n $::ioerropts(-start)} {$::go} {incr n} { set ::TN $n incr ::ioerropts(-count) -1 if {$::ioerropts(-count)<0} break @@ -1459,11 +1459,11 @@ } # Run the test script in a slave interpreter. # unset -nocomplain ::run_thread_tests_called - reset_prng_state + #reset_prng_state set time [time { slave_test_script [list source $zFile] }] set ms [expr [lindex $time 0] / 1000] # Add some info to the output. # Index: test/where.test ================================================================== --- test/where.test +++ test/where.test @@ -14,10 +14,14 @@ # $Id: where.test,v 1.50 2008/11/03 09:06:06 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl +db close +kvwrap install +sqlite4 db test.db + # Build some test data # do_test where-1.0 { execsql { CREATE TABLE t1(w int, x int, y int);