From: drh Date: Mon, 23 Jul 2018 21:10:37 +0000 (+0000) Subject: First attempt at reducing mutex contention in the unix VFS by providing X-Git-Tag: version-3.25.0~96^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da6dc2404a062a02ff5e0c7ab8ba59a5dfe40965;p=thirdparty%2Fsqlite.git First attempt at reducing mutex contention in the unix VFS by providing a separate mutex for each unixInodeInfo object. FossilOrigin-Name: f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8 --- diff --git a/manifest b/manifest index 6af55b184c..572f99e747 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sof\s'SQLITE_OMIT_WINDOWFUNC'. -D 2018-07-23T18:53:49.829 +C First\sattempt\sat\sreducing\smutex\scontention\sin\sthe\sunix\sVFS\sby\sproviding\na\sseparate\smutex\sfor\seach\sunixInodeInfo\sobject. +D 2018-07-23T21:10:37.802 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -481,7 +481,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9 +F src/os_unix.c c275a32d1112973457908bee494ae0444468c0b96c07057913ade6d69781dab3 F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9 @@ -1750,7 +1750,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 46dd076af5880e6e9a7de974758b26bc43d0dc074f8143234038fa9cdcc726ee -R 386d9db3da1c3cf3e08fdb519ac6201a -U mistachkin -Z 0f7169e4827257e93fc7e2c2fe7438e0 +P 8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc +R acece63ae9d3f4b29a8a0d5614555a1e +T *branch * separate-lock-mutex +T *sym-separate-lock-mutex * +T -sym-trunk * +U drh +Z c02c3e5d8cc1425b437d3294ad5c5e34 diff --git a/manifest.uuid b/manifest.uuid index 800ba6509c..de8e1e71e2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8607b84a5c53d8c9218c90802160a3000f1138b1f188e411a3af46253e0a69cc \ No newline at end of file +f69afaf00a659cd768a863c5f4a1d527f01187e037240da0ada527cb52c5afe8 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 0dd461da0a..48067f4cc3 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -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; }