1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Arrange for some of the transient locks in WAL mode to block, as a single

to the OS to fix priority inversions.

FossilOrigin-Name: c6e6d5f4e06c3ac0bfb620c0c728fbc7230c4a02
This commit is contained in:
drh
2015-03-10 20:22:35 +00:00
parent 94929646f1
commit bbf76eec34
5 changed files with 48 additions and 26 deletions

View File

@@ -248,6 +248,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */
#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */
/*
** Include code that is common to all os_*.c files
@@ -4090,15 +4091,17 @@ struct unixShm {
** otherwise.
*/
static int unixShmSystemLock(
unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
unixFile *pFile, /* Open connection to the WAL file */
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
int ofst, /* First byte of the locking range */
int n /* Number of bytes to lock */
){
struct flock f; /* The posix advisory locking structure */
int rc = SQLITE_OK; /* Result code form fcntl() */
unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
struct flock f; /* The posix advisory locking structure */
int rc = SQLITE_OK; /* Result code form fcntl() */
/* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
/* Shared locks never span more than one byte */
@@ -4108,6 +4111,7 @@ static int unixShmSystemLock(
assert( n>=1 && n<SQLITE_SHM_NLOCK );
if( pShmNode->h>=0 ){
int lkType;
/* Initialize the locking parameters */
memset(&f, 0, sizeof(f));
f.l_type = lockType;
@@ -4115,8 +4119,10 @@ static int unixShmSystemLock(
f.l_start = ofst;
f.l_len = n;
rc = osFcntl(pShmNode->h, F_SETLK, &f);
lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK;
rc = osFcntl(pShmNode->h, lkType, &f);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
pFile->ctrlFlags &= ~UNIXFILE_BLOCK;
}
/* Update the global lock state and do debug tracing */
@@ -4326,13 +4332,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** If not, truncate the file to zero length.
*/
rc = SQLITE_OK;
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( robust_ftruncate(pShmNode->h, 0) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
}
}
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
@@ -4564,7 +4570,7 @@ static int unixShmLock(
/* Unlock the system-level locks */
if( (mask & allMask)==0 ){
rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
}else{
rc = SQLITE_OK;
}
@@ -4592,7 +4598,7 @@ static int unixShmLock(
/* Get shared locks at the system level, if necessary */
if( rc==SQLITE_OK ){
if( (allShared & mask)==0 ){
rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
}else{
rc = SQLITE_OK;
}
@@ -4617,7 +4623,7 @@ static int unixShmLock(
** also mark the local connection as being locked.
*/
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
p->exclMask |= mask;
@@ -7222,6 +7228,10 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
*/
static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
switch( op ){
case SQLITE_FCNTL_WAL_BLOCK: {
id->ctrlFlags |= UNIXFILE_BLOCK;
return SQLITE_OK;
}
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
unixFile *pFile = (unixFile*)id;
if( pFile->pMethod == &proxyIoMethods ){