kernel/thread: Make thread_death_entry use DoublyLinkedList.
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user