status_t rw_lock_write_lock(rw_lock *lock) { MutexLocker locker(lock->lock); if (lock->reader_count == 0 && lock->writer_count == 0) { lock->writer_count++; lock->holder = find_thread(NULL); lock->owner_count = 1; return B_OK; } if (lock->holder == find_thread(NULL)) { lock->owner_count++; return B_OK; } lock->writer_count++; status_t result = rw_lock_wait(lock, true); if (result != B_OK) return result; if (lock->holder != find_thread(NULL)) { debugger("write locked but holder not set"); return B_ERROR; } lock->owner_count = 1; return B_OK; }
status_t _rw_lock_read_lock(rw_lock* lock) { InterruptsSpinLocker locker(lock->lock); // We might be the writer ourselves. if (lock->holder == thread_get_current_thread_id()) { lock->owner_count++; return B_OK; } // The writer that originally had the lock when we called atomic_add() might // already have gone and another writer could have overtaken us. In this // case the original writer set pending_readers, so we know that we don't // have to wait. if (lock->pending_readers > 0) { lock->pending_readers--; if (lock->count >= RW_LOCK_WRITER_COUNT_BASE) lock->active_readers++; return B_OK; } ASSERT(lock->count >= RW_LOCK_WRITER_COUNT_BASE); // we need to wait return rw_lock_wait(lock, false, locker); }
status_t rw_lock_read_lock(rw_lock *lock) { MutexLocker locker(lock->lock); if (lock->writer_count == 0) { lock->reader_count++; return B_OK; } if (lock->holder == find_thread(NULL)) { lock->owner_count++; return B_OK; } return rw_lock_wait(lock, false); }
status_t rw_lock_write_lock(rw_lock* lock) { InterruptsSpinLocker locker(lock->lock); // If we're already the lock holder, we just need to increment the owner // count. thread_id thread = thread_get_current_thread_id(); if (lock->holder == thread) { lock->owner_count += RW_LOCK_WRITER_COUNT_BASE; return B_OK; } // announce our claim int32 oldCount = atomic_add(&lock->count, RW_LOCK_WRITER_COUNT_BASE); if (oldCount == 0) { // No-one else held a read or write lock, so it's ours now. lock->holder = thread; lock->owner_count = RW_LOCK_WRITER_COUNT_BASE; return B_OK; } // We have to wait. If we're the first writer, note the current reader // count. if (oldCount < RW_LOCK_WRITER_COUNT_BASE) lock->active_readers = oldCount - lock->pending_readers; status_t status = rw_lock_wait(lock, true, locker); if (status == B_OK) { lock->holder = thread; lock->owner_count = RW_LOCK_WRITER_COUNT_BASE; } return status; }