mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-15 11:41:13 +03:00
Add the sqlite3_os_routine_set()/get() functions. (CVS 2818)
FossilOrigin-Name: c1ed79f594fb85009c2e9e5e281cbe66a9d2fa17
This commit is contained in:
39
src/os.c
39
src/os.c
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
22
src/os.h
22
src/os.h
@@ -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
|
||||
*/
|
||||
|
||||
@@ -1586,6 +1586,66 @@ static void unixLeaveMutex(){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** 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
|
||||
};
|
||||
|
||||
|
||||
|
||||
16
src/os_win.c
16
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 */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
43
src/util.c
43
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user