diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/os.c | 39 | ||||
-rw-r--r-- | src/os.h | 22 | ||||
-rw-r--r-- | src/os_unix.c | 61 | ||||
-rw-r--r-- | src/os_win.c | 16 | ||||
-rw-r--r-- | src/sqlite.h.in | 6 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/tclsqlite.c | 4 | ||||
-rw-r--r-- | src/util.c | 43 |
8 files changed, 171 insertions, 23 deletions
@@ -69,3 +69,42 @@ int sqlite3OsLockState(OsFile *id){ int sqlite3OsCheckReservedLock(OsFile *id){ return id->pMethod->xCheckReservedLock(id); } + +static void**getOsRoutinePtr(int eRoutine){ + switch( eRoutine ){ + case SQLITE_OS_ROUTINE_OPENREADWRITE: + return (void **)(&sqlite3Os.xOpenReadWrite); + case SQLITE_OS_ROUTINE_OPENREADONLY: + return (void **)(&sqlite3Os.xOpenReadOnly); + case SQLITE_OS_ROUTINE_OPENEXCLUSIVE: + return (void **)(&sqlite3Os.xOpenExclusive); + case SQLITE_OS_ROUTINE_DELETE: + return (void **)(&sqlite3Os.xDelete); + case SQLITE_OS_ROUTINE_FILEEXISTS: + return (void **)(&sqlite3Os.xFileExists); + case SQLITE_OS_ROUTINE_SYNCDIRECTORY: + return (void **)(&sqlite3Os.xSyncDirectory); + default: + assert(!"Illegal eRoutine value"); + } + return 0; +} + +void *sqlite3_os_routine_get(int eRoutine){ + return *getOsRoutinePtr(eRoutine); +} + +void *sqlite3_os_routine_set(int eRoutine, void *pRoutine){ + void **ppRet = getOsRoutinePtr(eRoutine); + void *pRet = *ppRet; + *ppRet = pRoutine; + return pRet; +} + +void sqlite3_os_enter_mutex(){ + sqlite3Os.xEnterMutex(); +} +void sqlite3_os_leave_mutex(){ + sqlite3Os.xLeaveMutex(); +} + @@ -222,8 +222,30 @@ extern struct sqlite3OsVtbl { int (*xCurrentTime)(double*); void (*xEnterMutex)(void); void (*xLeaveMutex)(void); + void *(*xThreadSpecificData)(int); } sqlite3Os; + +/* +** The semi-published API for setting and getting methods from the +** global sqlite3OsVtbl structure. Neither sqlite3_os_routine_XXX() function +** is intriniscally thread-safe. +** +** External get/set access is only provided to the routines identified +** by the hash-defined SQLITE_OS_ROUTINE symbols. +*/ +#define SQLITE_OS_ROUTINE_OPENREADWRITE 1 +#define SQLITE_OS_ROUTINE_OPENREADONLY 2 +#define SQLITE_OS_ROUTINE_OPENEXCLUSIVE 3 +#define SQLITE_OS_ROUTINE_DELETE 4 +#define SQLITE_OS_ROUTINE_FILEEXISTS 5 +#define SQLITE_OS_ROUTINE_SYNCDIRECTORY 6 +void *sqlite3_os_routine_get(int); +void *sqlite3_os_routine_set(int, void *); + +void sqlite3_os_enter_mutex(); +void sqlite3_os_leave_mutex(); + /* ** Prototypes for routines found in os.c */ diff --git a/src/os_unix.c b/src/os_unix.c index 349db3d7c..a7f1271ac 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1587,6 +1587,66 @@ static void unixLeaveMutex(){ } /* +** This function is called automatically when a thread exists to delete +** the threads SqliteTsd structure. +** +** Because the SqliteTsd structure is required by higher level routines +** such as sqliteMalloc() we use OsFree() and OsMalloc() directly to +** allocate the thread specific data. +*/ +static void deleteTsd(void *pTsd){ + sqlite3OsFree(pTsd); +} + +/* +** The first time this function is called from a specific thread, nByte +** bytes of data area are allocated and zeroed. A pointer to the new +** allocation is returned to the caller. +** +** Each subsequent call to this function from the thread returns the same +** pointer. The argument is ignored in this case. +*/ +static void *unixThreadSpecificData(int nByte){ +#ifdef SQLITE_UNIX_THREADS + static pthread_key_t key; + static int keyInit = 0; + void *pTsd; + + if( !keyInit ){ + sqlite3Os.xEnterMutex(); + if( !keyInit ){ + int rc; + rc = pthread_key_create(&key, deleteTsd); + if( rc ){ + return 0; + } + keyInit = 1; + } + sqlite3Os.xLeaveMutex(); + } + + pTsd = (SqliteTsd *)pthread_getspecific(key); + if( !pTsd ){ + pTsd = sqlite3OsMalloc(sizeof(SqliteTsd)); + if( pTsd ){ + memset(pTsd, 0, sizeof(SqliteTsd)); + pthread_setspecific(key, pTsd); + } + } + return pTsd; +#else + static char tsd[sizeof(SqliteTsd)]; + static isInit = 0; + assert( nByte==sizeof(SqliteTsd) ); + if( !isInit ){ + memset(tsd, 0, sizeof(SqliteTsd)); + isInit = 1; + } + return (void *)tsd; +#endif +} + +/* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqlite3Os.xCurrentTime(). This is used for testing. */ @@ -1644,6 +1704,7 @@ struct sqlite3OsVtbl sqlite3Os = { unixCurrentTime, unixEnterMutex, unixLeaveMutex, + unixThreadSpecificData }; diff --git a/src/os_win.c b/src/os_win.c index be561b75f..bfa0af033 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1020,6 +1020,21 @@ static int winCurrentTime(double *prNow){ return 0; } + +/* +** Todo: This is a place-holder only +*/ +static void *winThreadSpecificData(int nByte){ + static char tsd[sizeof(SqliteTsd)]; + static isInit = 0; + assert( nByte==sizeof(SqliteTsd) ); + if( !isInit ){ + memset(tsd, 0, sizeof(SqliteTsd)); + isInit = 1; + } + return (void *)tsd; +} + /* Macro used to comment out routines that do not exists when there is ** no disk I/O */ @@ -1047,6 +1062,7 @@ struct sqlite3OsVtbl sqlite3Os = { winCurrentTime, winEnterMutex, winLeaveMutex, + winThreadSpecificData }; #endif /* OS_WIN */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 8c9e95a50..27551e533 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.144 2005/12/12 06:53:05 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.145 2005/12/15 10:11:32 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1291,6 +1291,10 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*); */ void sqlite3_soft_heap_limit(int); + +int sqlite3_set_io_routine(int, void *); +void *sqlite3_get_io_routine(int); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index aa1bf3e26..daf146da0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.435 2005/12/15 03:04:11 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.436 2005/12/15 10:11:32 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -268,6 +268,7 @@ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ */ typedef struct SqliteTsd SqliteTsd; struct SqliteTsd { + int isInit; /* True if structure has been initialised */ int mallocFailed; /* True after a malloc() has failed */ #ifndef SQLITE_OMIT_SOFTHEAPLIMIT unsigned int nSoftHeapLimit; /* (uint)-1 for unlimited */ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 3b58df75c..af6c9101a 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.137 2005/12/12 06:53:05 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.138 2005/12/15 10:11:32 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -2092,6 +2092,7 @@ int TCLSH_MAIN(int argc, char **argv){ extern int Sqlitetest4_Init(Tcl_Interp*); extern int Sqlitetest5_Init(Tcl_Interp*); extern int Sqlitetest6_Init(Tcl_Interp*); + extern int Sqlitetestasync_Init(Tcl_Interp*); extern int Md5_Init(Tcl_Interp*); extern int Sqlitetestsse_Init(Tcl_Interp*); @@ -2101,6 +2102,7 @@ int TCLSH_MAIN(int argc, char **argv){ Sqlitetest4_Init(interp); Sqlitetest5_Init(interp); Sqlitetest6_Init(interp); + Sqlitetestasync_Init(interp); Md5_Init(interp); #ifdef SQLITE_SSE Sqlitetestsse_Init(interp); diff --git a/src/util.c b/src/util.c index 49b2c76df..b91339f65 100644 --- a/src/util.c +++ b/src/util.c @@ -14,9 +14,10 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.152 2005/12/12 06:53:05 danielk1977 Exp $ +** $Id: util.c,v 1.153 2005/12/15 10:11:32 danielk1977 Exp $ */ #include "sqliteInt.h" +#include "os.h" #include <stdarg.h> #include <ctype.h> @@ -107,6 +108,10 @@ int sqlite3OsAllocationSize(void *p){ ** Begin code for memory allocation system test layer. ** ** Memory debugging is turned on by defining the SQLITE_MEMDEBUG macro. +** +** SQLITE_MEMDEBUG==1 -> Fence-posting only (thread safe) +** SQLITE_MEMDEBUG==2 -> Fence-posting + linked list of allocations (not ts) +** SQLITE_MEMDEBUG==3 -> Above + backtraces (not thread safe, req. glibc) */ /* Figure out whether or not to store backtrace() information for each malloc. @@ -114,7 +119,7 @@ int sqlite3OsAllocationSize(void *p){ ** greater and glibc is in use. If we don't want to use backtrace(), then just ** define it as an empty macro and set the amount of space reserved to 0. */ -#if defined(__GLIBC__) && SQLITE_MEMDEBUG>1 +#if defined(__GLIBC__) && SQLITE_MEMDEBUG>2 extern int backtrace(void **, int); #define TESTALLOC_STACKSIZE 128 #define TESTALLOC_STACKFRAMES ((TESTALLOC_STACKSIZE-8)/sizeof(void*)) @@ -302,6 +307,8 @@ static void *getOsPointer(void *p) return (void *)(&z[-1 * TESTALLOC_OFFSET_DATA(p)]); } + +#if SQLITE_MEMDEBUG>1 /* ** The argument points to an Os level allocation. Link it into the threads list ** of allocations. @@ -363,6 +370,11 @@ static void relinkAlloc(void *p) ((void **)(pp[1]))[0] = p; } } +#else +#define linkAlloc(x) +#define relinkAlloc(x) +#define unlinkAlloc(x) +#endif /* ** This function sets the result of the Tcl interpreter passed as an argument @@ -1248,26 +1260,17 @@ void *sqlite3TextToPtr(const char *z){ /* ** Return a pointer to the SqliteTsd associated with the calling thread. -** TODO: Actually return thread-specific-data instead of this global pointer. */ SqliteTsd *sqlite3Tsd(){ - static SqliteTsd tsd = { - 0 /* mallocFailed flag */ - #ifndef SQLITE_OMIT_SOFTHEAPLIMIT - , 0xFFFFFFFF /* nSoftHeapLimit */ - , 0 /* nAlloc */ - #endif - #ifndef NDEBUG - , 1 /* mallocAllowed flag */ - #endif - #ifdef SQLITE_MEMDEBUG - , 0 - , 0 - , 0 - , 0 - #endif - }; - return &tsd; + SqliteTsd *pTsd = sqlite3Os.xThreadSpecificData(sizeof(SqliteTsd)); + if( pTsd && !pTsd->isInit ){ + pTsd->nSoftHeapLimit = 0xFFFFFFFF; +#ifndef NDEBUG + pTsd->mallocAllowed = 1; +#endif + pTsd->isInit = 1; + } + return pTsd; } /* |