kernel/block_cache: Change the mutex to an rwlock.

No behavioral change yet; all uses are changed to just write-lock it.

Change-Id: I8b155251c04eeef67a657ad614fc3959011b8455
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9530
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Augustin Cavalier
2025-08-05 16:28:21 +00:00
committed by waddlesplash
parent 75fbc948c9
commit 24226f94c7
+43 -43
View File
@@ -216,7 +216,7 @@ typedef BOpenHashTable<TransactionHash> TransactionTable;
struct block_cache : DoublyLinkedListLinkImpl<block_cache> {
mutex lock;
rw_lock lock;
BlockTable hash;
const int fd;
off_t max_blocks;
@@ -339,7 +339,7 @@ public:
~BlockPrefetcher();
status_t Allocate();
status_t ReadAsync(MutexLocker& cacheLocker);
status_t ReadAsync(WriteLocker& cacheLocker);
size_t NumAllocated() { return fNumAllocated; }
@@ -366,7 +366,7 @@ class TransactionLocking {
public:
inline bool Lock(block_cache* cache)
{
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
while (cache->busy_writing_count != 0) {
// wait for all blocks to be written
@@ -374,11 +374,11 @@ public:
cache->busy_writing_condition.Add(&entry);
cache->busy_writing_waiters = true;
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
entry.Wait();
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
}
return true;
@@ -386,7 +386,7 @@ public:
inline void Unlock(block_cache* cache)
{
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
}
};
@@ -1244,7 +1244,7 @@ BlockWriter::Write(cache_transaction* transaction, bool canUnlock)
return B_OK;
if (canUnlock)
mutex_unlock(&fCache->lock);
rw_lock_write_unlock(&fCache->lock);
// Sort blocks in their on-disk order, so we can merge consecutive writes.
qsort(fBlocks, fCount, sizeof(void*), &_CompareBlocks);
@@ -1279,7 +1279,7 @@ BlockWriter::Write(cache_transaction* transaction, bool canUnlock)
bigtime_t finish = system_time();
if (canUnlock)
mutex_lock(&fCache->lock);
rw_lock_write_lock(&fCache->lock);
if (fStatus == B_OK && fCount >= 8) {
fCache->last_block_write = finish;
@@ -1533,7 +1533,7 @@ BlockPrefetcher::Allocate()
\post The calling object will eventually be deleted by IOFinishedCallback.
*/
status_t
BlockPrefetcher::ReadAsync(MutexLocker& cacheLocker)
BlockPrefetcher::ReadAsync(WriteLocker& cacheLocker)
{
TRACE(("BlockPrefetcher::Read: reading %" B_PRIuSIZE " blocks\n", fNumAllocated));
@@ -1581,7 +1581,7 @@ BlockPrefetcher::_IOFinishedCallback(void* cookie, io_request* request, status_t
void
BlockPrefetcher::_IOFinished(status_t status, generic_size_t bytesTransferred)
{
MutexLocker locker(&fCache->lock);
WriteLocker locker(&fCache->lock);
if (bytesTransferred < (fNumAllocated * fCache->block_size)) {
_RemoveAllocated(fNumAllocated, fNumAllocated);
@@ -1665,14 +1665,14 @@ block_cache::~block_cache()
delete_object_cache(buffer_cache);
mutex_destroy(&lock);
rw_lock_destroy(&lock);
}
status_t
block_cache::Init()
{
mutex_init(&lock, "block cache");
rw_lock_init(&lock, "block cache");
busy_reading_condition.Init(this, "cache block busy_reading");
busy_writing_condition.Init(this, "cache block busy writing");
@@ -1899,7 +1899,7 @@ block_cache::_LowMemoryHandler(void* data, uint32 resources, int32 level)
break;
}
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
if (!locker.IsLocked()) {
// If our block_cache were deleted, it could be that we had
@@ -1992,9 +1992,9 @@ wait_for_busy_reading_block(block_cache* cache, cached_block* block)
cache->busy_reading_condition.Add(&entry);
block->busy_reading_waiters = true;
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
entry.Wait();
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
}
}
@@ -2010,9 +2010,9 @@ wait_for_busy_reading_blocks(block_cache* cache)
cache->busy_reading_condition.Add(&entry);
cache->busy_reading_waiters = true;
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
entry.Wait();
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
}
}
@@ -2028,9 +2028,9 @@ wait_for_busy_writing_block(block_cache* cache, cached_block* block)
cache->busy_writing_condition.Add(&entry);
block->busy_writing_waiters = true;
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
entry.Wait();
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
}
}
@@ -2046,9 +2046,9 @@ wait_for_busy_writing_blocks(block_cache* cache)
cache->busy_writing_condition.Add(&entry);
cache->busy_writing_waiters = true;
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
entry.Wait();
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
}
}
@@ -2175,12 +2175,12 @@ retry:
int32 blockSize = cache->block_size;
mark_block_busy_reading(cache, block);
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
ssize_t bytesRead = read_pos(cache->fd, blockNumber * blockSize,
block->current_data, blockSize);
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
if (bytesRead < blockSize) {
cache->RemoveBlock(block);
TB(Error(cache, blockNumber, "read failed", bytesRead));
@@ -2241,11 +2241,11 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber,
if (transactionID == -1) {
if (cleared) {
mark_block_busy_reading(cache, block);
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
memset(block->current_data, 0, cache->block_size);
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
mark_block_unbusy_reading(cache, block);
}
@@ -2311,11 +2311,11 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber,
}
mark_block_busy_reading(cache, block);
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
memcpy(block->original_data, block->current_data, cache->block_size);
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
mark_block_unbusy_reading(cache, block);
}
if (block->parent_data == block->current_data) {
@@ -2331,11 +2331,11 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber,
}
mark_block_busy_reading(cache, block);
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
memcpy(block->parent_data, block->current_data, cache->block_size);
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
mark_block_unbusy_reading(cache, block);
transaction->sub_num_blocks++;
@@ -2345,11 +2345,11 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber,
if (cleared) {
mark_block_busy_reading(cache, block);
mutex_unlock(&cache->lock);
rw_lock_write_unlock(&cache->lock);
memset(block->current_data, 0, cache->block_size);
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
mark_block_unbusy_reading(cache, block);
}
@@ -2774,7 +2774,7 @@ get_next_locked_block_cache(block_cache* last)
block_cache* cache;
if (last != NULL) {
mutex_unlock(&last->lock);
rw_lock_write_unlock(&last->lock);
cache = sCaches.GetNext((block_cache*)&sMarkCache);
sCaches.Remove((block_cache*)&sMarkCache);
@@ -2782,7 +2782,7 @@ get_next_locked_block_cache(block_cache* last)
cache = sCaches.Head();
if (cache != NULL) {
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
sCaches.InsertBefore(sCaches.GetNext(cache), (block_cache*)&sMarkCache);
}
@@ -3650,7 +3650,7 @@ block_cache_delete(void* _cache, bool allowWrites)
sCaches.Remove(cache);
mutex_unlock(&sCachesLock);
mutex_lock(&cache->lock);
rw_lock_write_lock(&cache->lock);
// wait for all blocks to become unbusy
wait_for_busy_reading_blocks(cache);
@@ -3706,7 +3706,7 @@ block_cache_sync(void* _cache)
// We will sync all dirty blocks to disk that have a completed
// transaction or no transaction only
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
BlockWriter writer(cache);
BlockTable::Iterator iterator(&cache->hash);
@@ -3743,7 +3743,7 @@ block_cache_sync_etc(void* _cache, off_t blockNumber, size_t numBlocks)
return B_BAD_VALUE;
}
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
BlockWriter writer(cache);
for (; numBlocks > 0; numBlocks--, blockNumber++) {
@@ -3821,7 +3821,7 @@ status_t
block_cache_make_writable(void* _cache, off_t blockNumber, int32 transaction)
{
block_cache* cache = (block_cache*)_cache;
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
if (cache->read_only) {
panic("tried to make block writable on a read-only cache!");
@@ -3846,7 +3846,7 @@ block_cache_get_writable_etc(void* _cache, off_t blockNumber,
int32 transaction, void** _block)
{
block_cache* cache = (block_cache*)_cache;
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
TRACE(("block_cache_get_writable_etc(block = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n",
blockNumber, transaction));
@@ -3874,7 +3874,7 @@ void*
block_cache_get_empty(void* _cache, off_t blockNumber, int32 transaction)
{
block_cache* cache = (block_cache*)_cache;
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
TRACE(("block_cache_get_empty(block = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n",
blockNumber, transaction));
@@ -3894,7 +3894,7 @@ status_t
block_cache_get_etc(void* _cache, off_t blockNumber, const void** _block)
{
block_cache* cache = (block_cache*)_cache;
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
bool allocated;
cached_block* block;
@@ -3939,7 +3939,7 @@ block_cache_set_dirty(void* _cache, off_t blockNumber, bool dirty,
int32 transaction)
{
block_cache* cache = (block_cache*)_cache;
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
cached_block* block = cache->hash.Lookup(blockNumber);
if (block == NULL)
@@ -3961,7 +3961,7 @@ void
block_cache_put(void* _cache, off_t blockNumber)
{
block_cache* cache = (block_cache*)_cache;
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
put_cached_block(cache, blockNumber);
}
@@ -3982,7 +3982,7 @@ block_cache_prefetch(void* _cache, off_t blockNumber, size_t* _numBlocks)
*_numBlocks, blockNumber));
block_cache* cache = reinterpret_cast<block_cache*>(_cache);
MutexLocker locker(&cache->lock);
WriteLocker locker(&cache->lock);
size_t numBlocks = *_numBlocks;
*_numBlocks = 0;