Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Define an invariant to guarantee deadlock-free operation of SHM in os_unix.c and check that invariant with assert() statements. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | wal |
Files: | files | file ages | folders |
SHA1: |
6af2dca75b8139134ea394c1d71aefc6 |
User & Date: | drh 2010-05-01 17:57:36.000 |
Context
2010-05-03
| ||
08:04 | Add the sqlite3_wal_checkpoint() and sqlite3_wal_autocheckpoint() APIs. (check-in: 9803196dec user: dan tags: wal) | |
2010-05-01
| ||
18:23 | Remove the xShmPush and xShmPull methods from the VFS. (check-in: 69e07fdbde user: drh tags: wal) | |
17:57 | Define an invariant to guarantee deadlock-free operation of SHM in os_unix.c and check that invariant with assert() statements. (check-in: 6af2dca75b user: drh tags: wal) | |
17:50 | Rework mutexes on the SHM implemention for os_unix to avoid a deadlock during WAL recovery. (check-in: 1a0f69bef2 user: drh tags: wal) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 | ** ** fid ** zFilename ** ** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and ** unixMutexHeld() is true when reading or writing any other field ** in this structure. */ struct unixShmFile { struct unixFileId fid; /* Unique file identifier */ sqlite3_mutex *mutex; /* Mutex to access this object */ sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */ char *zFilename; /* Name of the file */ int h; /* Open file descriptor */ | > > > > > > | 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 | ** ** fid ** zFilename ** ** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and ** unixMutexHeld() is true when reading or writing any other field ** in this structure. ** ** To avoid deadlocks, mutex and mutexBuf are always released in the ** reverse order that they are acquired. mutexBuf is always acquired ** first and released last. This invariant is check by asserting ** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or ** released. */ struct unixShmFile { struct unixFileId fid; /* Unique file identifier */ sqlite3_mutex *mutex; /* Mutex to access this object */ sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */ char *zFilename; /* Name of the file */ int h; /* Open file descriptor */ |
︙ | ︙ | |||
5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 | void **ppBuf /* Write mapping buffer origin here */ ){ unixShm *p = (unixShm*)pSharedMem; unixShmFile *pFile = p->pFile; int rc = SQLITE_OK; if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){ sqlite3_mutex_enter(pFile->mutexBuf); p->hasMutexBuf = 1; } sqlite3_mutex_enter(pFile->mutex); if( pFile->szMap==0 || reqMapSize>pFile->szMap ){ int actualSize; if( unixShmSize(pSharedMem, -1, &actualSize)==SQLITE_OK | > | 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 | void **ppBuf /* Write mapping buffer origin here */ ){ unixShm *p = (unixShm*)pSharedMem; unixShmFile *pFile = p->pFile; int rc = SQLITE_OK; if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){ assert( sqlite3_mutex_notheld(pFile->mutex) ); sqlite3_mutex_enter(pFile->mutexBuf); p->hasMutexBuf = 1; } sqlite3_mutex_enter(pFile->mutex); if( pFile->szMap==0 || reqMapSize>pFile->szMap ){ int actualSize; if( unixShmSize(pSharedMem, -1, &actualSize)==SQLITE_OK |
︙ | ︙ | |||
5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 | ** really want to release the lock, so in that case too, this routine ** is a no-op. */ static int unixShmRelease(sqlite3_shm *pSharedMem){ unixShm *p = (unixShm*)pSharedMem; if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){ unixShmFile *pFile = p->pFile; sqlite3_mutex_leave(pFile->mutexBuf); p->hasMutexBuf = 0; } return SQLITE_OK; } /* | > | 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 | ** really want to release the lock, so in that case too, this routine ** is a no-op. */ static int unixShmRelease(sqlite3_shm *pSharedMem){ unixShm *p = (unixShm*)pSharedMem; if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){ unixShmFile *pFile = p->pFile; assert( sqlite3_mutex_notheld(pFile->mutex) ); sqlite3_mutex_leave(pFile->mutexBuf); p->hasMutexBuf = 0; } return SQLITE_OK; } /* |
︙ | ︙ | |||
5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 | return SQLITE_OK; } OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n", p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock])); if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){ sqlite3_mutex_enter(pFile->mutexBuf); p->hasMutexBuf = 1; } sqlite3_mutex_enter(pFile->mutex); switch( desiredLock ){ case SQLITE_SHM_UNLOCK: { assert( p->lockState!=SQLITE_SHM_RECOVER ); | > | 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 | return SQLITE_OK; } OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n", p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock])); if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){ assert( sqlite3_mutex_notheld(pFile->mutex) ); sqlite3_mutex_enter(pFile->mutexBuf); p->hasMutexBuf = 1; } sqlite3_mutex_enter(pFile->mutex); switch( desiredLock ){ case SQLITE_SHM_UNLOCK: { assert( p->lockState!=SQLITE_SHM_RECOVER ); |
︙ | ︙ |