kernel/thread: Use a rw_spinlock for the sThreadHashLock.
On a dual-core system with no other applications but the standard ones running, my standard "compile HaikuDepot with hot disk cache" benchmark shows a consistent ~5% improvement after this patch (~33.7s -> ~31.9s sys). On systems with higher core and thread counts, these numbers are probably very much larger (I'd imagine it could be up to even 10 or 15%.) Change-Id: I5df2a075bae7c71b84c6fcd33ead60df8e844757 Reviewed-on: https://review.haiku-os.org/c/861 Reviewed-by: Adrien Destugues <pulkomandy@gmail.com> Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
e6bb34532a
commit
568bb7eeab
@ -73,7 +73,7 @@ typedef BKernel::TeamThreadTable<Thread> ThreadHashTable;
|
||||
// thread list
|
||||
static Thread sIdleThreads[SMP_MAX_CPUS];
|
||||
static ThreadHashTable sThreadHash;
|
||||
static spinlock sThreadHashLock = B_SPINLOCK_INITIALIZER;
|
||||
static rw_spinlock sThreadHashLock = B_RW_SPINLOCK_INITIALIZER;
|
||||
static thread_id sNextThreadID = 2;
|
||||
// ID 1 is allocated for the kernel by Team::Team() behind our back
|
||||
|
||||
@ -227,7 +227,7 @@ Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu)
|
||||
msg.read_sem = -1;
|
||||
|
||||
// add to thread table -- yet invisible
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker threadHashLocker(sThreadHashLock);
|
||||
sThreadHash.Insert(this);
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ Thread::~Thread()
|
||||
mutex_destroy(&fLock);
|
||||
|
||||
// remove from thread table
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker threadHashLocker(sThreadHashLock);
|
||||
sThreadHash.Remove(this);
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ Thread::Create(const char* name, Thread*& _thread)
|
||||
/*static*/ Thread*
|
||||
Thread::Get(thread_id id)
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
Thread* thread = sThreadHash.Lookup(id);
|
||||
if (thread != NULL)
|
||||
thread->AcquireReference();
|
||||
@ -299,7 +299,7 @@ Thread::Get(thread_id id)
|
||||
Thread::GetAndLock(thread_id id)
|
||||
{
|
||||
// look it up and acquire a reference
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
Thread* thread = sThreadHash.Lookup(id);
|
||||
if (thread == NULL)
|
||||
return NULL;
|
||||
@ -333,7 +333,7 @@ Thread::GetDebug(thread_id id)
|
||||
/*static*/ bool
|
||||
Thread::IsAlive(thread_id id)
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
return sThreadHash.Lookup(id) != NULL;
|
||||
}
|
||||
|
||||
@ -395,7 +395,7 @@ Thread::Init(bool idleThread)
|
||||
bool
|
||||
Thread::IsAlive() const
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
|
||||
return sThreadHash.Lookup(id) != NULL;
|
||||
}
|
||||
@ -486,7 +486,7 @@ Thread::DeactivateCPUTimeUserTimers()
|
||||
ThreadListIterator::ThreadListIterator()
|
||||
{
|
||||
// queue the entry
|
||||
InterruptsSpinLocker locker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker locker(sThreadHashLock);
|
||||
sThreadHash.InsertIteratorEntry(&fEntry);
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ ThreadListIterator::ThreadListIterator()
|
||||
ThreadListIterator::~ThreadListIterator()
|
||||
{
|
||||
// remove the entry
|
||||
InterruptsSpinLocker locker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker locker(sThreadHashLock);
|
||||
sThreadHash.RemoveIteratorEntry(&fEntry);
|
||||
}
|
||||
|
||||
@ -503,7 +503,7 @@ Thread*
|
||||
ThreadListIterator::Next()
|
||||
{
|
||||
// get the next team -- if there is one, get reference for it
|
||||
InterruptsSpinLocker locker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker locker(sThreadHashLock);
|
||||
Thread* thread = sThreadHash.NextElement(&fEntry);
|
||||
if (thread != NULL)
|
||||
thread->AcquireReference();
|
||||
@ -1016,7 +1016,7 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel)
|
||||
ThreadLocker threadLocker(thread);
|
||||
|
||||
InterruptsSpinLocker threadCreationLocker(gThreadCreationLock);
|
||||
SpinLocker threadHashLocker(sThreadHashLock);
|
||||
WriteSpinLocker threadHashLocker(sThreadHashLock);
|
||||
|
||||
// check the thread limit
|
||||
if (sUsedThreads >= sMaxThreads) {
|
||||
@ -2164,7 +2164,7 @@ thread_exit(void)
|
||||
SpinLocker threadCreationLocker(gThreadCreationLock);
|
||||
|
||||
// mark invisible in global hash/list, so it's no longer accessible
|
||||
SpinLocker threadHashLocker(sThreadHashLock);
|
||||
WriteSpinLocker threadHashLocker(sThreadHashLock);
|
||||
thread->visible = false;
|
||||
sUsedThreads--;
|
||||
threadHashLocker.Unlock();
|
||||
@ -2375,7 +2375,7 @@ thread_reset_for_exec(void)
|
||||
thread_id
|
||||
allocate_thread_id()
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker threadHashLocker(sThreadHashLock);
|
||||
|
||||
// find the next unused ID
|
||||
thread_id id;
|
||||
@ -2396,7 +2396,7 @@ allocate_thread_id()
|
||||
thread_id
|
||||
peek_next_thread_id()
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
return sNextThreadID;
|
||||
}
|
||||
|
||||
@ -2423,7 +2423,7 @@ thread_yield(void)
|
||||
void
|
||||
thread_map(void (*function)(Thread* thread, void* data), void* data)
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsWriteSpinLocker threadHashLocker(sThreadHashLock);
|
||||
|
||||
for (ThreadHashTable::Iterator it = sThreadHash.GetIterator();
|
||||
Thread* thread = it.Next();) {
|
||||
@ -2609,7 +2609,7 @@ thread_max_threads(void)
|
||||
int32
|
||||
thread_used_threads(void)
|
||||
{
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
return sUsedThreads;
|
||||
}
|
||||
|
||||
@ -3153,10 +3153,11 @@ find_thread(const char* name)
|
||||
if (name == NULL)
|
||||
return thread_get_current_thread_id();
|
||||
|
||||
InterruptsSpinLocker threadHashLocker(sThreadHashLock);
|
||||
InterruptsReadSpinLocker threadHashLocker(sThreadHashLock);
|
||||
|
||||
// TODO: Scanning the whole hash with the thread hash lock held isn't
|
||||
// exactly cheap -- although this function is probably used very rarely.
|
||||
// Scanning the whole hash with the thread hash lock held isn't exactly
|
||||
// cheap, but since this function is probably used very rarely, and we
|
||||
// only need a read lock, it's probably acceptable.
|
||||
|
||||
for (ThreadHashTable::Iterator it = sThreadHash.GetIterator();
|
||||
Thread* thread = it.Next();) {
|
||||
|
Loading…
Reference in New Issue
Block a user