| 224 | } |
| 225 | |
| 226 | bool GlobalRWLock::lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump) |
| 227 | { |
| 228 | SET_TDBB(tdbb); |
| 229 | |
| 230 | bool needFetch; |
| 231 | |
| 232 | { // scope 1 |
| 233 | CheckoutLockGuard counterGuard(tdbb, counterMutex, FB_FUNCTION, true); |
| 234 | |
| 235 | COS_TRACE(("(%p)->lockRead stage 1 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", |
| 236 | this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); |
| 237 | |
| 238 | while (true) |
| 239 | { |
| 240 | if (readers > 0 && queueJump) |
| 241 | { |
| 242 | COS_TRACE(("(%p)->lockRead queueJump", this)); |
| 243 | readers++; |
| 244 | return true; |
| 245 | } |
| 246 | |
| 247 | while (pendingWriters > 0 || currentWriter) |
| 248 | { |
| 249 | EngineCheckout cout(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY); |
| 250 | writerFinished.wait(counterMutex); |
| 251 | } |
| 252 | |
| 253 | COS_TRACE(("(%p)->lockRead stage 3 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", |
| 254 | this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); |
| 255 | |
| 256 | if (!pendingLock) |
| 257 | break; |
| 258 | |
| 259 | MutexUnlockGuard cout(counterMutex, FB_FUNCTION); |
| 260 | EngineCheckout cout2(tdbb, FB_FUNCTION, EngineCheckout::UNNECESSARY); |
| 261 | Thread::yield(); |
| 262 | } |
| 263 | |
| 264 | needFetch = cachedLock->lck_physical < LCK_read; |
| 265 | if (!needFetch) |
| 266 | { |
| 267 | ++readers; |
| 268 | return true; |
| 269 | } |
| 270 | |
| 271 | ++pendingLock; |
| 272 | |
| 273 | fb_assert(cachedLock->lck_physical == LCK_none); |
| 274 | } |
| 275 | |
| 276 | if (!LCK_lock(tdbb, cachedLock, LCK_read, wait)) |
| 277 | { |
| 278 | FbStatusVector* const vector = tdbb->tdbb_status_vector; |
| 279 | const ISC_STATUS* status = vector->getErrors(); |
| 280 | if ((wait == LCK_NO_WAIT) || ((wait < 0) && (status[1] == isc_lock_timeout))) |
| 281 | vector->init(); |
| 282 | |
| 283 | CheckoutLockGuard counterGuard(tdbb, counterMutex, FB_FUNCTION, true); |