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 list_link link;
struct thread_death_entry : DoublyLinkedListLinkImpl<thread_death_entry> {
thread_id thread;
status_t status;
};
typedef DoublyLinkedList<thread_death_entry> ThreadDeathEntryList;
struct team_loading_info {
ConditionVariable condition;
status_t result; // the result of the loading
@@ -296,7 +297,7 @@ struct Thread : TeamThreadIteratorEntry<thread_id>, KernelReferenceable {
struct {
sem_id sem; // immutable after thread creation
status_t status; // accessed only by this thread
struct list waiters; // protected by fLock
ThreadDeathEntryList waiters; // protected by fLock
} exit;
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 xsi_sem_context *xsi_sem_context;
struct team_death_entry *death_entry; // protected by fLock
struct list dead_threads;
ThreadDeathEntryList dead_threads;
// protected by the team's fLock
team_dead_children dead_children;
+1 -4
View File
@@ -445,7 +445,6 @@ Team::Team(team_id id, bool kernel)
realtime_sem_context = NULL;
xsi_sem_context = NULL;
death_entry = NULL;
list_init(&dead_threads);
dead_children.condition_variable.Init(&dead_children, "team children");
dead_children.count = 0;
@@ -528,10 +527,8 @@ Team::~Team()
if (fQueuedSignalsCounter != NULL)
fQueuedSignalsCounter->ReleaseReference();
while (thread_death_entry* threadDeathEntry
= (thread_death_entry*)list_remove_head_item(&dead_threads)) {
while (thread_death_entry* threadDeathEntry = dead_threads.RemoveHead())
free(threadDeathEntry);
}
while (::job_control_entry* entry = dead_children.entries.RemoveHead())
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;
list_init(&exit.waiters);
exit.sem = -1;
msg.write_sem = -1;
msg.read_sem = -1;
@@ -1852,8 +1850,6 @@ _dump_thread_info(Thread *thread, bool shortInfo)
// print the long info
struct thread_death_entry *death = NULL;
kprintf("THREAD: %p\n", thread);
kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", 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,
strerror(thread->exit.status));
kprintf(" exit.waiters:\n");
while ((death = (struct thread_death_entry*)list_get_next_item(
&thread->exit.waiters, death)) != NULL) {
for (thread_death_entry* death = thread->exit.waiters.First(); death != NULL;
death = thread->exit.waiters.GetNext(death)) {
kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread);
}
@@ -2272,13 +2268,12 @@ thread_exit(void)
} else {
// The thread is not the main thread. We store a thread death entry
// for it, unless someone is already waiting for it.
if (threadDeathEntry != NULL
&& list_is_empty(&thread->exit.waiters)) {
if (threadDeathEntry != NULL && thread->exit.waiters.IsEmpty()) {
threadDeathEntry->thread = thread->id;
threadDeathEntry->status = thread->exit.status;
// add entry to dead thread list
list_add_item(&team->dead_threads, threadDeathEntry);
team->dead_threads.Add(threadDeathEntry);
}
threadCreationLocker.Unlock();
@@ -2371,9 +2366,8 @@ thread_exit(void)
thread->exit.sem = -1;
// fill all death entries
thread_death_entry* entry = NULL;
while ((entry = (thread_death_entry*)list_get_next_item(
&thread->exit.waiters, entry)) != NULL) {
for (thread_death_entry* entry = thread->exit.waiters.First(); entry != NULL;
entry = thread->exit.waiters.GetNext(entry)) {
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
exitSem = thread->exit.sem;
if (exitSem >= 0)
list_add_link_to_head(&thread->exit.waiters, &death);
thread->exit.waiters.Add(&death, false);
thread->UnlockAndReleaseReference();
@@ -2635,10 +2629,10 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
} else {
// check the thread death entries of the team (non-main threads)
thread_death_entry* threadDeathEntry = NULL;
while ((threadDeathEntry = (thread_death_entry*)list_get_next_item(
&team->dead_threads, threadDeathEntry)) != NULL) {
for (threadDeathEntry = team->dead_threads.First(); threadDeathEntry != NULL;
threadDeathEntry = team->dead_threads.GetNext(threadDeathEntry)) {
if (threadDeathEntry->thread == id) {
list_remove_item(&team->dead_threads, threadDeathEntry);
team->dead_threads.Remove(threadDeathEntry);
death.status = threadDeathEntry->status;
free(threadDeathEntry);
break;
@@ -2674,7 +2668,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
// remove our death entry now.
thread = Thread::GetAndLock(id);
if (thread != NULL) {
list_remove_link(&death.link);
thread->exit.waiters.Remove(&death);
thread->UnlockAndReleaseReference();
} else {
// The thread is already gone, so we need to wait uninterruptibly