kernel/thread: Fix a TODO in get_next_thread_info().

Just find the previous thread and then get the one after it in
the general case. This avoids problems with "unsorted" thread lists
as found in the kernel team or when IDs wrap, with the previous
logic only kept as a fallback if the last-fetched thread
does not exist anymore.
This commit is contained in:
Augustin Cavalier
2025-03-03 14:36:01 -05:00
parent 0c76e02c58
commit 752c6e8b9e
+23 -9
View File
@@ -3317,19 +3317,33 @@ _get_next_thread_info(team_id teamID, int32 *_cookie, thread_info *info,
Thread* thread = NULL;
if (lastID == 0) {
// We start with the main thread
// We start with the main thread.
thread = team->main_thread;
} else {
// Find the one thread with an ID greater than ours (as long as the IDs
// don't wrap they are always sorted from highest to lowest).
// TODO: That is broken not only when the IDs wrap, but also for the
// kernel team, to which threads are added when they are dying.
for (Thread* next = team->thread_list.First(); next != NULL;
next = team->thread_list.GetNext(next)) {
if (next->id <= lastID)
// Find the previous thread after the one with the last ID.
bool found = false;
for (Thread* previous = team->thread_list.Last(); previous != NULL;
previous = team->thread_list.GetPrevious(previous)) {
if (previous->id == lastID) {
found = true;
thread = team->thread_list.GetPrevious(previous);
break;
}
}
thread = next;
if (!found) {
// Fall back to finding the thread with the next greatest ID (as long
// as IDs don't wrap, they are always sorted from highest to lowest).
// This won't work properly if IDs wrap, or for the kernel team (to
// which threads are added when they are dying), but this is only a
// fallback for when the previous thread wasn't found, anyway.
for (Thread* next = team->thread_list.First(); next != NULL;
next = team->thread_list.GetNext(next)) {
if (next->id <= lastID)
break;
thread = next;
}
}
}