Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -17,21 +17,19 @@ #if OS_UNIX /* This file is used on unix only */ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. +** large file support, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. -** -** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 @@ -49,14 +47,12 @@ #include #include #include /* -** Macros used to determine whether or not to use threads. The -** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for -** Posix threads and SQLITE_W32_THREADS is defined if we are -** synchronizing using Win32 threads. +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. */ #if defined(THREADSAFE) && THREADSAFE # include # define SQLITE_UNIX_THREADS 1 #endif @@ -83,11 +79,11 @@ unsigned char locktype; /* The type of lock held on this fd */ unsigned char isOpen; /* True if needs to be closed */ unsigned char fullSync; /* Use F_FULLSYNC if available */ int dirfd; /* File descriptor for the directory */ #ifdef SQLITE_UNIX_THREADS - pthread_t tid; /* The thread authorized to use this OsFile */ + pthread_t tid; /* The thread that "owns" this OsFile */ #endif }; /* ** Provide the ability to override some OS-layer functions during @@ -111,11 +107,11 @@ */ #include "os_common.h" /* ** Do not include any of the File I/O interface procedures if the -** SQLITE_OMIT_DISKIO macro is defined (indicating that there database +** SQLITE_OMIT_DISKIO macro is defined (indicating that the database ** will be in-memory only) */ #ifndef SQLITE_OMIT_DISKIO @@ -162,10 +158,17 @@ ** same thread is operating on the OsFile. Some operating systems do ** not allow locks to be overridden by other threads and that restriction ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. +** +** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the OsFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information */ #if defined(SQLITE_UNIX_THREADS) # define SET_THREADID(X) (X)->tid = pthread_self() # define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ !pthread_equal((X)->tid, pthread_self())) @@ -278,12 +281,12 @@ ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override -** each others locks then tid is always set to zero. tid is also -** set to zero if we compile without threading support. +** each others locks then tid is always set to zero. tid is omitted +** if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS @@ -331,12 +334,13 @@ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* -** These hash table maps inodes and process IDs into lockInfo and openCnt -** structures. Access to these hash tables must be protected by a mutex. +** These hash tables map inodes and file descriptors (really, lockKey and +** openKey structures) into lockInfo and openCnt structures. Access to +** these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; @@ -346,10 +350,14 @@ ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. +** +** This variable normally has file scope only. But during testing, we make +** it a global so that the test code can change its value in order to verify +** that the right stuff happens in either case. */ #ifdef SQLITE_TEST int threadsOverrideEachOthersLocks = -1; #else static int threadsOverrideEachOthersLocks = -1; @@ -370,11 +378,11 @@ ** Print out information about all locking operations. ** ** This routine is used for troubleshooting locks on multithreaded ** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE ** command-line option on the compiler. This code is normally -** turnned off. +** turned off. */ static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; int s; int savedErrno; @@ -608,11 +616,11 @@ ** unable to override locks created by a different thread. RedHat9 is ** an example of such a system. ** ** Ownership transfer is only allowed if the unixFile is currently unlocked. ** If the unixFile is locked and an ownership is wrong, then return -** SQLITE_MISUSE. Otherwise return SQLITE_OK. +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. */ #ifdef SQLITE_UNIX_THREADS static int transferOwnership(unixFile *pFile){ int rc; pthread_t hSelf; @@ -638,10 +646,11 @@ locktypeName(pFile->locktype), locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); return rc; } #else + /* On single-threaded builds, ownership transfer is a no-op */ # define transferOwnership(X) SQLITE_OK #endif /* ** Delete the named file @@ -832,10 +841,12 @@ /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. +** +** See also the "PRAGMA temp_store_directory" SQL command. */ char *sqlite3_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to @@ -1369,14 +1380,10 @@ ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. -** -** It is not possible for this routine to fail if the second argument -** is NO_LOCK. If the second argument is SHARED_LOCK, this routine -** might return SQLITE_IOERR instead of SQLITE_OK. */ static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; @@ -1388,11 +1395,13 @@ assert( locktype<=SHARED_LOCK ); if( pFile->locktype<=locktype ){ return SQLITE_OK; } - if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } sqlite3OsEnterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ assert( pLock->locktype==pFile->locktype ); @@ -1614,11 +1623,11 @@ ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means - ** that we always use the same random number sequence.* This makes the + ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset(zBuf, 0, 256); #if !defined(SQLITE_TEST) { @@ -1639,10 +1648,11 @@ return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. +** The argument is the number of milliseconds we want to sleep. */ int sqlite3UnixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; @@ -1665,10 +1675,12 @@ ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. +** +** This mutex is not recursive. */ void sqlite3UnixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif @@ -1710,13 +1722,13 @@ # define TSD_COUNTER(N) /* no-op */ #endif /* -** If called with allocateFlag>1, then return a pointer to thread +** If called with allocateFlag>0, then return a pointer to thread ** specific data for the current thread. Allocate and zero the -** thread-specific data if it does not already exist necessary. +** thread-specific data if it does not already exist. ** ** If called with allocateFlag==0, then check the current thread ** specific data. Return it if it exists. If it does not exist, ** then return NULL. **