Skip to content
Permalink
Browse files

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>
  • Loading branch information...
waddlesplash committed Jan 9, 2019
1 parent e6bb345 commit 568bb7eeab4b485d19492b8415d858cf6297fb11
Showing with 20 additions and 19 deletions.
  1. +20 −19 src/system/kernel/thread.cpp
@@ -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,15 +486,15 @@ Thread::DeactivateCPUTimeUserTimers()
ThreadListIterator::ThreadListIterator()
{
// queue the entry
InterruptsSpinLocker locker(sThreadHashLock);
InterruptsWriteSpinLocker locker(sThreadHashLock);
sThreadHash.InsertIteratorEntry(&fEntry);
}


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();) {

0 comments on commit 568bb7e

Please sign in to comment.
You can’t perform that action at this time.