From 8ab820f076cad39859a9a674b44fd82f1abfb88b Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 7 Jan 2010 14:09:56 +0000 Subject: [PATCH] VMAddressSpace::Put() is too hot to always write lock the address spaces table. It is now inline and uses double-checked locking. This reduces the contention on the lock to insignificant. Total -j8 Haiku image build speedup is marginal, but the total kernel time drops 12%. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34934 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/vm/VMAddressSpace.h | 15 +++++++-- src/system/kernel/vm/VMAddressSpace.cpp | 36 ++++++++++++---------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/headers/private/kernel/vm/VMAddressSpace.h b/headers/private/kernel/vm/VMAddressSpace.h index 93b7b086ae..fd02bc6be6 100644 --- a/headers/private/kernel/vm/VMAddressSpace.h +++ b/headers/private/kernel/vm/VMAddressSpace.h @@ -49,8 +49,8 @@ public: int32 RefCount() const { return fRefCount; } - void Get() { atomic_add(&fRefCount, 1); } - void Put(); + inline void Get() { atomic_add(&fRefCount, 1); } + inline void Put(); void RemoveAndPut(); void IncrementFaultCount() @@ -107,6 +107,8 @@ public: static VMAddressSpace* Get(team_id teamID); protected: + static void _DeleteIfUnreferenced(team_id id); + static int _DumpCommand(int argc, char** argv); static int _DumpListCommand(int argc, char** argv); @@ -129,6 +131,15 @@ protected: }; +void +VMAddressSpace::Put() +{ + team_id id = fID; + if (atomic_add(&fRefCount, -1) == 1) + _DeleteIfUnreferenced(id); +} + + class VMAddressSpace::AreaIterator { public: AreaIterator() diff --git a/src/system/kernel/vm/VMAddressSpace.cpp b/src/system/kernel/vm/VMAddressSpace.cpp index 492ccf24d4..fcaccfaa8f 100644 --- a/src/system/kernel/vm/VMAddressSpace.cpp +++ b/src/system/kernel/vm/VMAddressSpace.cpp @@ -148,23 +148,6 @@ VMAddressSpace::InitPostSem() } -void -VMAddressSpace::Put() -{ - bool remove = false; - - rw_lock_write_lock(&sAddressSpaceTableLock); - if (atomic_add(&fRefCount, -1) == 1) { - sAddressSpaceTable.RemoveUnchecked(this); - remove = true; - } - rw_lock_write_unlock(&sAddressSpaceTableLock); - - if (remove) - delete this; -} - - /*! Deletes all areas in the specified address space, and the address space by decreasing all reference counters. It also marks the address space of being in deletion state, so that no more areas @@ -293,6 +276,25 @@ VMAddressSpace::Get(team_id teamID) } +/*static*/ void +VMAddressSpace::_DeleteIfUnreferenced(team_id id) +{ + rw_lock_write_lock(&sAddressSpaceTableLock); + + bool remove = false; + VMAddressSpace* addressSpace = sAddressSpaceTable.Lookup(id); + if (addressSpace != NULL && addressSpace->fRefCount == 0) { + sAddressSpaceTable.RemoveUnchecked(addressSpace); + remove = true; + } + + rw_lock_write_unlock(&sAddressSpaceTableLock); + + if (remove) + delete addressSpace; +} + + /*static*/ int VMAddressSpace::_DumpCommand(int argc, char** argv) {