* Renamed get_team_death_entry() to team_get_death_entry() and make it available
to other kernel components. * wait_for_thread_etc() will now search the team's death entries in case the thread is already gone; also resume_thread() is now done later, and its return code will no longer matter (as we already have our death entry, no matter if the thread is gone now or not). * The fibo_load_image test now works as expected (only tested with low numbers yet, though - the mean testing comes later (first comes functionality) :-)) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19758 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
cbe5f24524
commit
cdcb059571
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Haiku Inc.
|
||||
* Copyright 2004-2007, Haiku Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _TEAM_H
|
||||
@ -28,6 +28,8 @@ team_id team_get_current_team_id(void);
|
||||
status_t team_get_address_space(team_id id, struct vm_address_space **_addressSpace);
|
||||
char **user_team_get_arguments(void);
|
||||
int user_team_get_arg_count(void);
|
||||
status_t team_get_death_entry(struct team *team, thread_id child,
|
||||
struct death_entry *death, struct death_entry **_freeDeath);
|
||||
bool team_is_valid(team_id id);
|
||||
struct team *team_get_team_struct_locked(team_id id);
|
||||
int32 team_max_teams(void);
|
||||
|
@ -1289,37 +1289,6 @@ register_wait_for_any(struct team *team, thread_id child)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
get_team_death_entry(struct team *team, thread_id child, struct death_entry *death,
|
||||
struct death_entry **_freeDeath)
|
||||
{
|
||||
struct death_entry *entry = NULL;
|
||||
|
||||
// find matching death entry structure
|
||||
|
||||
while ((entry = list_get_next_item(&team->dead_children.list, entry)) != NULL) {
|
||||
if (child != -1 && entry->thread != child)
|
||||
continue;
|
||||
|
||||
// we found one
|
||||
|
||||
*death = *entry;
|
||||
|
||||
// only remove the death entry if there aren't any other interested parties
|
||||
if ((child == -1 && atomic_add(&team->dead_children.wait_for_any, -1) == 1)
|
||||
|| (child != -1 && team->dead_children.wait_for_any == 0)) {
|
||||
list_remove_link(entry);
|
||||
team->dead_children.count--;
|
||||
*_freeDeath = entry;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return child > 0 ? B_BAD_THREAD_ID : B_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
/** Gets the next pending death entry, if any. Also fills in \a _waitSem
|
||||
* to the semaphore the caller have to wait for for other death entries.
|
||||
* Must be called with the team lock held.
|
||||
@ -1336,7 +1305,7 @@ get_death_entry(struct team *team, pid_t child, struct death_entry *death,
|
||||
// wait for any children or a specific child of this team to die
|
||||
*_waitSem = team->dead_children.sem;
|
||||
*_waitCount = &team->dead_children.waiters;
|
||||
return get_team_death_entry(team, child, death, _freeDeath);
|
||||
return team_get_death_entry(team, child, death, _freeDeath);
|
||||
} else if (child < 0) {
|
||||
// we wait for all children of the specified process group
|
||||
group = team_get_process_group_locked(team->group->session, -child);
|
||||
@ -1348,7 +1317,7 @@ get_death_entry(struct team *team, pid_t child, struct death_entry *death,
|
||||
}
|
||||
|
||||
for (team = group->teams; team; team = team->group_next) {
|
||||
status = get_team_death_entry(team, -1, death, _freeDeath);
|
||||
status = team_get_death_entry(team, -1, death, _freeDeath);
|
||||
if (status == B_OK) {
|
||||
atomic_add(&group->wait_for_any, -1);
|
||||
return B_OK;
|
||||
@ -1568,6 +1537,41 @@ team_used_teams(void)
|
||||
}
|
||||
|
||||
|
||||
/** Fills the provided death entry if it's in the team.
|
||||
* You need to have the team lock held when calling this function.
|
||||
*/
|
||||
|
||||
status_t
|
||||
team_get_death_entry(struct team *team, thread_id child, struct death_entry *death,
|
||||
struct death_entry **_freeDeath)
|
||||
{
|
||||
struct death_entry *entry = NULL;
|
||||
|
||||
// find matching death entry structure
|
||||
|
||||
while ((entry = list_get_next_item(&team->dead_children.list, entry)) != NULL) {
|
||||
if (child != -1 && entry->thread != child)
|
||||
continue;
|
||||
|
||||
// we found one
|
||||
|
||||
*death = *entry;
|
||||
|
||||
// only remove the death entry if there aren't any other interested parties
|
||||
if ((child == -1 && atomic_add(&team->dead_children.wait_for_any, -1) == 1)
|
||||
|| (child != -1 && team->dead_children.wait_for_any == 0)) {
|
||||
list_remove_link(entry);
|
||||
team->dead_children.count--;
|
||||
*_freeDeath = entry;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return child > 0 ? B_BAD_THREAD_ID : B_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
/** Quick check to see if we have a valid team ID.
|
||||
*/
|
||||
|
||||
|
@ -1300,15 +1300,15 @@ status_t
|
||||
wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, status_t *_returnCode)
|
||||
{
|
||||
sem_id sem = B_BAD_THREAD_ID;
|
||||
struct death_entry death;
|
||||
struct death_entry death, *freeDeath = NULL;
|
||||
struct thread *thread;
|
||||
cpu_status state;
|
||||
status_t status;
|
||||
status_t status = B_OK;
|
||||
|
||||
if (id < B_OK)
|
||||
return B_BAD_THREAD_ID;
|
||||
|
||||
// we need to resume the thread we're waiting for first
|
||||
status = resume_thread(id);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
state = disable_interrupts();
|
||||
GRAB_THREAD_LOCK();
|
||||
@ -1321,11 +1321,36 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, status_t *_re
|
||||
}
|
||||
|
||||
RELEASE_THREAD_LOCK();
|
||||
|
||||
if (thread == NULL) {
|
||||
// we couldn't find this thread - maybe it's already gone, and we'll
|
||||
// find its death entry
|
||||
GRAB_TEAM_LOCK();
|
||||
|
||||
status = team_get_death_entry(thread_get_current_thread()->team,
|
||||
id, &death, &freeDeath);
|
||||
|
||||
RELEASE_TEAM_LOCK();
|
||||
}
|
||||
|
||||
restore_interrupts(state);
|
||||
|
||||
if (thread == NULL && status == B_OK) {
|
||||
// we found the thread's death entry in our team
|
||||
if (_returnCode)
|
||||
*_returnCode = death.status;
|
||||
|
||||
free(freeDeath);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// we need to wait for the death of the thread
|
||||
|
||||
if (sem < B_OK)
|
||||
return B_BAD_THREAD_ID;
|
||||
|
||||
resume_thread(id);
|
||||
|
||||
status = acquire_sem_etc(sem, 1, flags, timeout);
|
||||
|
||||
if (status == B_OK) {
|
||||
|
Loading…
Reference in New Issue
Block a user