* 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:
@@ -6,6 +6,7 @@
|
|||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*! Threading routines */
|
/*! Threading routines */
|
||||||
|
|
||||||
|
|
||||||
@@ -2453,49 +2454,50 @@ err:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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)
|
size_t size)
|
||||||
{
|
{
|
||||||
status_t status = B_BAD_VALUE;
|
if (info == NULL || size != sizeof(thread_info) || teamID < 0)
|
||||||
struct thread *thread = NULL;
|
|
||||||
cpu_status state;
|
|
||||||
int slot;
|
|
||||||
thread_id lastThreadID;
|
|
||||||
|
|
||||||
if (info == NULL || size != sizeof(thread_info) || team < B_OK)
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
if (team == B_CURRENT_TEAM)
|
int32 lastID = *_cookie;
|
||||||
team = team_get_current_team_id();
|
|
||||||
else if (!team_is_valid(team))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
slot = *_cookie;
|
InterruptsSpinLocker teamLocker(gTeamSpinlock);
|
||||||
|
|
||||||
state = disable_interrupts();
|
struct team* team;
|
||||||
GRAB_THREAD_LOCK();
|
if (teamID == B_CURRENT_TEAM)
|
||||||
|
team = thread_get_current_thread()->team;
|
||||||
|
else
|
||||||
|
team = team_get_team_struct_locked(teamID);
|
||||||
|
|
||||||
lastThreadID = peek_next_thread_id();
|
struct thread* thread = NULL;
|
||||||
if (slot >= lastThreadID)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
while (slot < lastThreadID
|
if (lastID == 0) {
|
||||||
&& (!(thread = thread_get_thread_struct_locked(slot))
|
// We start with the main thread
|
||||||
|| thread->team->id != team))
|
thread = team->main_thread;
|
||||||
slot++;
|
} 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) {
|
thread = next;
|
||||||
fill_thread_info(thread, info, size);
|
}
|
||||||
|
|
||||||
*_cookie = slot + 1;
|
|
||||||
status = B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
if (thread == NULL)
|
||||||
RELEASE_THREAD_LOCK();
|
return B_BAD_VALUE;
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
return status;
|
lastID = thread->id;
|
||||||
|
*_cookie = lastID;
|
||||||
|
|
||||||
|
SpinLocker threadLocker(gThreadSpinlock);
|
||||||
|
fill_thread_info(thread, info, size);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user