status_t rw_lock_read_unlock(rw_lock *lock) { MutexLocker locker(lock->lock); if (lock->holder == find_thread(NULL)) { if (--lock->owner_count > 0) return B_OK; // this originally has been a write lock lock->writer_count--; lock->holder = -1; rw_lock_unblock(lock); return B_OK; } if (lock->reader_count <= 0) { debugger("rw_lock not read locked"); return B_ERROR; } lock->reader_count--; rw_lock_unblock(lock); return B_OK; }
void _rw_lock_write_unlock(rw_lock* lock) { InterruptsSpinLocker locker(lock->lock); if (thread_get_current_thread_id() != lock->holder) { panic("rw_lock_write_unlock(): lock %p not write-locked by this thread", lock); return; } ASSERT(lock->owner_count >= RW_LOCK_WRITER_COUNT_BASE); lock->owner_count -= RW_LOCK_WRITER_COUNT_BASE; if (lock->owner_count >= RW_LOCK_WRITER_COUNT_BASE) return; // We gave up our last write lock -- clean up and unblock waiters. int32 readerCount = lock->owner_count; lock->holder = -1; lock->owner_count = 0; int32 oldCount = atomic_add(&lock->count, -RW_LOCK_WRITER_COUNT_BASE); oldCount -= RW_LOCK_WRITER_COUNT_BASE; if (oldCount != 0) { // If writers are waiting, take over our reader count. if (oldCount >= RW_LOCK_WRITER_COUNT_BASE) { lock->active_readers = readerCount; rw_lock_unblock(lock); } else { // No waiting writer, but there are one or more readers. We will // unblock all waiting readers -- that's the easy part -- and must // also make sure that all readers that haven't entered the critical // section yet, won't start to wait. Otherwise a writer overtaking // such a reader will correctly start to wait, but the reader, // seeing the writer count > 0, would also start to wait. We set // pending_readers to the number of readers that are still expected // to enter the critical section. lock->pending_readers = oldCount - readerCount - rw_lock_unblock(lock); } } }
status_t rw_lock_write_unlock(rw_lock *lock) { MutexLocker locker(lock->lock); if (lock->holder != find_thread(NULL)) { debugger("rw_lock not write locked"); return B_ERROR; } if (--lock->owner_count > 0) return B_OK; lock->writer_count--; lock->holder = -1; rw_lock_unblock(lock); return B_OK; }
void _rw_lock_read_unlock(rw_lock* lock) { InterruptsSpinLocker locker(lock->lock); // If we're still holding the write lock or if there are other readers, // no-one can be woken up. if (lock->holder == thread_get_current_thread_id()) { ASSERT(lock->owner_count % RW_LOCK_WRITER_COUNT_BASE > 0); lock->owner_count--; return; } if (--lock->active_readers > 0) return; if (lock->active_readers < 0) { panic("rw_lock_read_unlock(): lock %p not read-locked", lock); lock->active_readers = 0; return; } rw_lock_unblock(lock); }