mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
First attempt at reducing mutex contention in the unix VFS by providing
a separate mutex for each unixInodeInfo object. FossilOrigin-Name: f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8
This commit is contained in:
@@ -1108,15 +1108,29 @@ struct unixFileId {
|
||||
** A single inode can have multiple file descriptors, so each unixFile
|
||||
** structure contains a pointer to an instance of this object and this
|
||||
** object keeps a count of the number of unixFile pointing to it.
|
||||
**
|
||||
** Mutex rules:
|
||||
**
|
||||
** (1) The pLockMutex mutex must be held in order to read or write
|
||||
** any of the locking fields:
|
||||
** nShared, nLock, eFileLock, or bProcessLock
|
||||
**
|
||||
** (2) When nRef>0, then the following fields are unchanging and can
|
||||
** be read (but not written) without holding any mutex:
|
||||
** fileId, pLockMutex
|
||||
**
|
||||
** (3) With the exceptions above, all the fields may only be read
|
||||
** or written while holding the global unixBigLock mutex.
|
||||
*/
|
||||
struct unixInodeInfo {
|
||||
struct unixFileId fileId; /* The lookup key */
|
||||
int nShared; /* Number of SHARED locks held */
|
||||
unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
||||
unsigned char bProcessLock; /* An exclusive process lock is held */
|
||||
sqlite3_mutex *pLockMutex; /* Hold this mutex for... */
|
||||
int nShared; /* Number of SHARED locks held */
|
||||
int nLock; /* Number of outstanding file locks */
|
||||
unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
||||
unsigned char bProcessLock; /* An exclusive process lock is held */
|
||||
int nRef; /* Number of pointers to this structure */
|
||||
unixShmNode *pShmNode; /* Shared memory associated with this inode */
|
||||
int nLock; /* Number of outstanding file locks */
|
||||
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
|
||||
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
|
||||
unixInodeInfo *pPrev; /* .... doubly linked */
|
||||
@@ -1273,6 +1287,7 @@ static void releaseInodeInfo(unixFile *pFile){
|
||||
assert( pInode->pNext->pPrev==pInode );
|
||||
pInode->pNext->pPrev = pInode->pPrev;
|
||||
}
|
||||
sqlite3_mutex_free(pInode->pLockMutex);
|
||||
sqlite3_free(pInode);
|
||||
}
|
||||
}
|
||||
@@ -1358,6 +1373,7 @@ static int findInodeInfo(
|
||||
}
|
||||
memset(pInode, 0, sizeof(*pInode));
|
||||
memcpy(&pInode->fileId, &fileId, sizeof(fileId));
|
||||
pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
pInode->nRef = 1;
|
||||
pInode->pNext = inodeList;
|
||||
pInode->pPrev = 0;
|
||||
@@ -1436,7 +1452,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
|
||||
assert( pFile );
|
||||
assert( pFile->eFileLock<=SHARED_LOCK );
|
||||
unixEnterMutex(); /* Because pFile->pInode is shared across threads */
|
||||
sqlite3_mutex_enter(pFile->pInode->pLockMutex);
|
||||
|
||||
/* Check if a thread in this process holds such a lock */
|
||||
if( pFile->pInode->eFileLock>SHARED_LOCK ){
|
||||
@@ -1461,7 +1477,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
}
|
||||
#endif
|
||||
|
||||
unixLeaveMutex();
|
||||
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
|
||||
OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
|
||||
|
||||
*pResOut = reserved;
|
||||
@@ -1527,8 +1543,8 @@ static int osSetPosixAdvisoryLock(
|
||||
static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
||||
int rc;
|
||||
unixInodeInfo *pInode = pFile->pInode;
|
||||
assert( unixMutexHeld() );
|
||||
assert( pInode!=0 );
|
||||
assert( sqlite3_mutex_held(pInode->pLockMutex) );
|
||||
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
|
||||
if( pInode->bProcessLock==0 ){
|
||||
struct flock lock;
|
||||
@@ -1647,8 +1663,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
||||
|
||||
/* This mutex is needed because pFile->pInode is shared across threads
|
||||
*/
|
||||
unixEnterMutex();
|
||||
pInode = pFile->pInode;
|
||||
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||
|
||||
/* If some thread using this PID has a lock via a different unixFile*
|
||||
** handle that precludes the requested lock, return BUSY.
|
||||
@@ -1791,7 +1807,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
||||
}
|
||||
|
||||
end_lock:
|
||||
unixLeaveMutex();
|
||||
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||
OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
|
||||
rc==SQLITE_OK ? "ok" : "failed"));
|
||||
return rc;
|
||||
@@ -1839,8 +1855,8 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
if( pFile->eFileLock<=eFileLock ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
unixEnterMutex();
|
||||
pInode = pFile->pInode;
|
||||
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||
assert( pInode->nShared!=0 );
|
||||
if( pFile->eFileLock>SHARED_LOCK ){
|
||||
assert( pInode->eFileLock==pFile->eFileLock );
|
||||
@@ -1972,7 +1988,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
}
|
||||
|
||||
end_unlock:
|
||||
unixLeaveMutex();
|
||||
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
|
||||
return rc;
|
||||
}
|
||||
@@ -2771,8 +2787,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
*pResOut = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
unixEnterMutex(); /* Because pFile->pInode is shared across threads */
|
||||
|
||||
sqlite3_mutex_enter(pFile->pInode->pLockMutex);
|
||||
/* Check if a thread in this process holds such a lock */
|
||||
if( pFile->pInode->eFileLock>SHARED_LOCK ){
|
||||
reserved = 1;
|
||||
@@ -2796,7 +2811,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
}
|
||||
}
|
||||
|
||||
unixLeaveMutex();
|
||||
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
|
||||
OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
|
||||
|
||||
*pResOut = reserved;
|
||||
@@ -2859,8 +2874,8 @@ static int afpLock(sqlite3_file *id, int eFileLock){
|
||||
|
||||
/* This mutex is needed because pFile->pInode is shared across threads
|
||||
*/
|
||||
unixEnterMutex();
|
||||
pInode = pFile->pInode;
|
||||
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||
|
||||
/* If some thread using this PID has a lock via a different unixFile*
|
||||
** handle that precludes the requested lock, return BUSY.
|
||||
@@ -2996,7 +3011,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
|
||||
}
|
||||
|
||||
afp_end_lock:
|
||||
unixLeaveMutex();
|
||||
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||
OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
|
||||
rc==SQLITE_OK ? "ok" : "failed"));
|
||||
return rc;
|
||||
@@ -3028,8 +3043,8 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
||||
if( pFile->eFileLock<=eFileLock ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
unixEnterMutex();
|
||||
pInode = pFile->pInode;
|
||||
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||
assert( pInode->nShared!=0 );
|
||||
if( pFile->eFileLock>SHARED_LOCK ){
|
||||
assert( pInode->eFileLock==pFile->eFileLock );
|
||||
@@ -3104,7 +3119,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
||||
}
|
||||
}
|
||||
|
||||
unixLeaveMutex();
|
||||
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user