Added a team watching mechanism in the kernel, not yet tested (but at least doesn't cause any harm yet :-)).

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13888 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-08-03 12:00:42 +00:00
parent 9ecb61a8f6
commit 99c566f6c9
3 changed files with 106 additions and 4 deletions

View File

@ -32,6 +32,9 @@ struct team *team_get_team_struct_locked(team_id id);
int32 team_max_teams(void);
int32 team_used_teams(void);
status_t start_watching_team(team_id team, void (*hook)(team_id, void *), void *data);
status_t stop_watching_team(team_id team, void (*hook)(team_id, void *), void *data);
// used in syscalls.c
thread_id _user_load_image(int32 argCount, const char **args, int32 envCount,
const char **envp, int32 priority, uint32 flags);

View File

@ -78,6 +78,12 @@ struct team_loading_info {
bool done; // set when loading is done/aborted
};
struct team_watcher {
struct list_link link;
void (*hook)(team_id team, void *data);
void *data;
};
#define MAX_DEAD_CHILDREN 32
// this is a soft limit for the number of dead entries in a team
@ -111,6 +117,7 @@ struct team {
struct thread *thread_list;
struct team_loading_info *loading_info;
struct list image_list;
struct list watcher_list;
struct arch_team arch_info;
struct team_debug_info debug_info;

View File

@ -689,6 +689,7 @@ create_team_struct(const char *name, bool kernel)
goto error1;
list_init(&team->image_list);
list_init(&team->watcher_list);
clear_team_debug_info(&team->debug_info, true);
@ -761,10 +762,10 @@ team_delete_team(struct team *team)
sem_id deathSem;
int32 threadCount;
sprintf(death_sem_name, "team %ld death sem", team->id);
sprintf(death_sem_name, "team %ld death sem", teamID);
deathSem = create_sem(0, death_sem_name);
if (deathSem < 0)
panic("thread_exit: cannot init death sem for team %ld\n", team->id);
panic("thread_exit: cannot init death sem for team %ld\n", teamID);
state = disable_interrupts();
GRAB_TEAM_LOCK();
@ -828,11 +829,24 @@ team_delete_team(struct team *team)
// free team resources
vm_delete_aspace(team->aspace);
delete_owned_ports(team->id);
sem_delete_owned_sems(team->id);
delete_owned_ports(teamID);
sem_delete_owned_sems(teamID);
remove_images(team);
vfs_free_io_context(team->io_context);
// notify team watchers
{
// we're not reachable from anyone anymore at this point, so we
// can safely access the list without any locking
struct team_watcher *watcher;
while ((watcher = list_remove_head_item(&team->watcher_list)) != NULL) {
watcher->hook(teamID, watcher->data);
free(watcher);
}
}
// ToDo: what about the dead_children.sem? shouldn't we call delete_team_struct() here?
free(team);
// notify the debugger, that the team is gone
@ -1634,6 +1648,84 @@ err:
}
/** Adds a hook to the team that is called as soon as this
* team goes away.
* This call might get public in the future.
*/
status_t
start_watching_team(team_id teamID, void (*hook)(team_id, void *), void *data)
{
struct team_watcher *watcher;
struct team *team;
cpu_status state;
if (hook == NULL || teamID < B_OK)
return B_BAD_VALUE;
watcher = malloc(sizeof(struct team_watcher));
if (watcher == NULL)
return B_NO_MEMORY;
// find team and add watcher
state = disable_interrupts();
GRAB_TEAM_LOCK();
team = team_get_team_struct_locked(teamID);
if (team != NULL)
list_add_item(&team->watcher_list, watcher);
RELEASE_TEAM_LOCK();
restore_interrupts(state);
if (team == NULL) {
free(watcher);
return B_BAD_TEAM_ID;
}
return B_OK;
}
status_t
stop_watching_team(team_id teamID, void (*hook)(team_id, void *), void *data)
{
struct team_watcher *watcher = NULL;
struct team *team;
cpu_status state;
if (hook == NULL || teamID < B_OK)
return B_BAD_VALUE;
// find team and remove watcher (if present)
state = disable_interrupts();
GRAB_TEAM_LOCK();
team = team_get_team_struct_locked(teamID);
if (team != NULL) {
// search for watcher
while ((watcher = list_get_next_item(&team->watcher_list, watcher)) != NULL) {
if (watcher->hook == hook && watcher->data == data) {
// got it!
list_remove_item(&team->watcher_list, watcher);
break;
}
}
}
RELEASE_TEAM_LOCK();
restore_interrupts(state);
if (watcher == NULL)
return B_ENTRY_NOT_FOUND;
free(watcher);
return B_OK;
}
// #pragma mark -
// public team API