kernel/thread: Make thread_death_entry use DoublyLinkedList.

This commit is contained in:
Augustin Cavalier
2025-03-03 14:08:02 -05:00
parent 61d76848f0
commit da6325cd03
3 changed files with 17 additions and 25 deletions
+5 -4
View File
@@ -79,12 +79,13 @@ namespace BKernel {
} }
struct thread_death_entry { struct thread_death_entry : DoublyLinkedListLinkImpl<thread_death_entry> {
struct list_link link;
thread_id thread; thread_id thread;
status_t status; status_t status;
}; };
typedef DoublyLinkedList<thread_death_entry> ThreadDeathEntryList;
struct team_loading_info { struct team_loading_info {
ConditionVariable condition; ConditionVariable condition;
status_t result; // the result of the loading status_t result; // the result of the loading
@@ -296,7 +297,7 @@ struct Thread : TeamThreadIteratorEntry<thread_id>, KernelReferenceable {
struct { struct {
sem_id sem; // immutable after thread creation sem_id sem; // immutable after thread creation
status_t status; // accessed only by this thread status_t status; // accessed only by this thread
struct list waiters; // protected by fLock ThreadDeathEntryList waiters; // protected by fLock
} exit; } exit;
struct select_info *select_infos; // protected by fLock struct select_info *select_infos; // protected by fLock
@@ -454,7 +455,7 @@ struct Team : TeamThreadIteratorEntry<team_id>, KernelReferenceable,
struct realtime_sem_context *realtime_sem_context; struct realtime_sem_context *realtime_sem_context;
struct xsi_sem_context *xsi_sem_context; struct xsi_sem_context *xsi_sem_context;
struct team_death_entry *death_entry; // protected by fLock struct team_death_entry *death_entry; // protected by fLock
struct list dead_threads; ThreadDeathEntryList dead_threads;
// protected by the team's fLock // protected by the team's fLock
team_dead_children dead_children; team_dead_children dead_children;
+1 -4
View File
@@ -445,7 +445,6 @@ Team::Team(team_id id, bool kernel)
realtime_sem_context = NULL; realtime_sem_context = NULL;
xsi_sem_context = NULL; xsi_sem_context = NULL;
death_entry = NULL; death_entry = NULL;
list_init(&dead_threads);
dead_children.condition_variable.Init(&dead_children, "team children"); dead_children.condition_variable.Init(&dead_children, "team children");
dead_children.count = 0; dead_children.count = 0;
@@ -528,10 +527,8 @@ Team::~Team()
if (fQueuedSignalsCounter != NULL) if (fQueuedSignalsCounter != NULL)
fQueuedSignalsCounter->ReleaseReference(); fQueuedSignalsCounter->ReleaseReference();
while (thread_death_entry* threadDeathEntry while (thread_death_entry* threadDeathEntry = dead_threads.RemoveHead())
= (thread_death_entry*)list_remove_head_item(&dead_threads)) {
free(threadDeathEntry); free(threadDeathEntry);
}
while (::job_control_entry* entry = dead_children.entries.RemoveHead()) while (::job_control_entry* entry = dead_children.entries.RemoveHead())
delete entry; delete entry;
+11 -17
View File
@@ -316,8 +316,6 @@ Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu)
exit.status = 0; exit.status = 0;
list_init(&exit.waiters);
exit.sem = -1; exit.sem = -1;
msg.write_sem = -1; msg.write_sem = -1;
msg.read_sem = -1; msg.read_sem = -1;
@@ -1852,8 +1850,6 @@ _dump_thread_info(Thread *thread, bool shortInfo)
// print the long info // print the long info
struct thread_death_entry *death = NULL;
kprintf("THREAD: %p\n", thread); kprintf("THREAD: %p\n", thread);
kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id, kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id,
thread->id); thread->id);
@@ -1936,8 +1932,8 @@ _dump_thread_info(Thread *thread, bool shortInfo)
kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status, kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status,
strerror(thread->exit.status)); strerror(thread->exit.status));
kprintf(" exit.waiters:\n"); kprintf(" exit.waiters:\n");
while ((death = (struct thread_death_entry*)list_get_next_item( for (thread_death_entry* death = thread->exit.waiters.First(); death != NULL;
&thread->exit.waiters, death)) != NULL) { death = thread->exit.waiters.GetNext(death)) {
kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread); kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread);
} }
@@ -2272,13 +2268,12 @@ thread_exit(void)
} else { } else {
// The thread is not the main thread. We store a thread death entry // The thread is not the main thread. We store a thread death entry
// for it, unless someone is already waiting for it. // for it, unless someone is already waiting for it.
if (threadDeathEntry != NULL if (threadDeathEntry != NULL && thread->exit.waiters.IsEmpty()) {
&& list_is_empty(&thread->exit.waiters)) {
threadDeathEntry->thread = thread->id; threadDeathEntry->thread = thread->id;
threadDeathEntry->status = thread->exit.status; threadDeathEntry->status = thread->exit.status;
// add entry to dead thread list // add entry to dead thread list
list_add_item(&team->dead_threads, threadDeathEntry); team->dead_threads.Add(threadDeathEntry);
} }
threadCreationLocker.Unlock(); threadCreationLocker.Unlock();
@@ -2371,9 +2366,8 @@ thread_exit(void)
thread->exit.sem = -1; thread->exit.sem = -1;
// fill all death entries // fill all death entries
thread_death_entry* entry = NULL; for (thread_death_entry* entry = thread->exit.waiters.First(); entry != NULL;
while ((entry = (thread_death_entry*)list_get_next_item( entry = thread->exit.waiters.GetNext(entry)) {
&thread->exit.waiters, entry)) != NULL) {
entry->status = thread->exit.status; entry->status = thread->exit.status;
} }
@@ -2611,7 +2605,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
// remember the semaphore we have to wait on and place our death entry // remember the semaphore we have to wait on and place our death entry
exitSem = thread->exit.sem; exitSem = thread->exit.sem;
if (exitSem >= 0) if (exitSem >= 0)
list_add_link_to_head(&thread->exit.waiters, &death); thread->exit.waiters.Add(&death, false);
thread->UnlockAndReleaseReference(); thread->UnlockAndReleaseReference();
@@ -2635,10 +2629,10 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
} else { } else {
// check the thread death entries of the team (non-main threads) // check the thread death entries of the team (non-main threads)
thread_death_entry* threadDeathEntry = NULL; thread_death_entry* threadDeathEntry = NULL;
while ((threadDeathEntry = (thread_death_entry*)list_get_next_item( for (threadDeathEntry = team->dead_threads.First(); threadDeathEntry != NULL;
&team->dead_threads, threadDeathEntry)) != NULL) { threadDeathEntry = team->dead_threads.GetNext(threadDeathEntry)) {
if (threadDeathEntry->thread == id) { if (threadDeathEntry->thread == id) {
list_remove_item(&team->dead_threads, threadDeathEntry); team->dead_threads.Remove(threadDeathEntry);
death.status = threadDeathEntry->status; death.status = threadDeathEntry->status;
free(threadDeathEntry); free(threadDeathEntry);
break; break;
@@ -2674,7 +2668,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
// remove our death entry now. // remove our death entry now.
thread = Thread::GetAndLock(id); thread = Thread::GetAndLock(id);
if (thread != NULL) { if (thread != NULL) {
list_remove_link(&death.link); thread->exit.waiters.Remove(&death);
thread->UnlockAndReleaseReference(); thread->UnlockAndReleaseReference();
} else { } else {
// The thread is already gone, so we need to wait uninterruptibly // The thread is already gone, so we need to wait uninterruptibly