* Reimplemented the insane _get_next_thread_info() which previously just
iterated over all known thread *IDs* with interrupts disabled. Now it iterates over the team's thread list (going from back to front, since new threads are added at the front of the singly linked queue). * Alexandre restarted Tracker quite a lot, and let the shell script run to reproduce a certain bug - and then wondered why ProcessController would take several seconds to open its windows until it passed through more than 8 million IDs... :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33737 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4f5d9ca63d
commit
3530c3eb6b
@ -6,6 +6,7 @@
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
/*! Threading routines */
|
||||
|
||||
|
||||
@ -2453,49 +2454,50 @@ err:
|
||||
|
||||
|
||||
status_t
|
||||
_get_next_thread_info(team_id team, int32 *_cookie, thread_info *info,
|
||||
_get_next_thread_info(team_id teamID, int32 *_cookie, thread_info *info,
|
||||
size_t size)
|
||||
{
|
||||
status_t status = B_BAD_VALUE;
|
||||
struct thread *thread = NULL;
|
||||
cpu_status state;
|
||||
int slot;
|
||||
thread_id lastThreadID;
|
||||
|
||||
if (info == NULL || size != sizeof(thread_info) || team < B_OK)
|
||||
if (info == NULL || size != sizeof(thread_info) || teamID < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (team == B_CURRENT_TEAM)
|
||||
team = team_get_current_team_id();
|
||||
else if (!team_is_valid(team))
|
||||
return B_BAD_VALUE;
|
||||
int32 lastID = *_cookie;
|
||||
|
||||
slot = *_cookie;
|
||||
InterruptsSpinLocker teamLocker(gTeamSpinlock);
|
||||
|
||||
state = disable_interrupts();
|
||||
GRAB_THREAD_LOCK();
|
||||
struct team* team;
|
||||
if (teamID == B_CURRENT_TEAM)
|
||||
team = thread_get_current_thread()->team;
|
||||
else
|
||||
team = team_get_team_struct_locked(teamID);
|
||||
|
||||
lastThreadID = peek_next_thread_id();
|
||||
if (slot >= lastThreadID)
|
||||
goto err;
|
||||
struct thread* thread = NULL;
|
||||
|
||||
while (slot < lastThreadID
|
||||
&& (!(thread = thread_get_thread_struct_locked(slot))
|
||||
|| thread->team->id != team))
|
||||
slot++;
|
||||
if (lastID == 0) {
|
||||
// We start with the main thread
|
||||
thread = team->main_thread;
|
||||
} else {
|
||||
// Find the one thread with an ID higher than ours
|
||||
// (as long as the IDs don't overlap they are always sorted from
|
||||
// highest to lowest).
|
||||
for (struct thread* next = team->thread_list; next != NULL;
|
||||
next = next->team_next) {
|
||||
if (next->id <= lastID)
|
||||
break;
|
||||
|
||||
if (thread != NULL && thread->team->id == team) {
|
||||
fill_thread_info(thread, info, size);
|
||||
|
||||
*_cookie = slot + 1;
|
||||
status = B_OK;
|
||||
thread = next;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
RELEASE_THREAD_LOCK();
|
||||
restore_interrupts(state);
|
||||
if (thread == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return status;
|
||||
lastID = thread->id;
|
||||
*_cookie = lastID;
|
||||
|
||||
SpinLocker threadLocker(gThreadSpinlock);
|
||||
fill_thread_info(thread, info, size);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user