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:
parent
9ecb61a8f6
commit
99c566f6c9
|
@ -32,6 +32,9 @@ struct team *team_get_team_struct_locked(team_id id);
|
||||||
int32 team_max_teams(void);
|
int32 team_max_teams(void);
|
||||||
int32 team_used_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
|
// used in syscalls.c
|
||||||
thread_id _user_load_image(int32 argCount, const char **args, int32 envCount,
|
thread_id _user_load_image(int32 argCount, const char **args, int32 envCount,
|
||||||
const char **envp, int32 priority, uint32 flags);
|
const char **envp, int32 priority, uint32 flags);
|
||||||
|
|
|
@ -78,6 +78,12 @@ struct team_loading_info {
|
||||||
bool done; // set when loading is done/aborted
|
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
|
#define MAX_DEAD_CHILDREN 32
|
||||||
// this is a soft limit for the number of dead entries in a team
|
// 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 thread *thread_list;
|
||||||
struct team_loading_info *loading_info;
|
struct team_loading_info *loading_info;
|
||||||
struct list image_list;
|
struct list image_list;
|
||||||
|
struct list watcher_list;
|
||||||
struct arch_team arch_info;
|
struct arch_team arch_info;
|
||||||
|
|
||||||
struct team_debug_info debug_info;
|
struct team_debug_info debug_info;
|
||||||
|
|
|
@ -689,6 +689,7 @@ create_team_struct(const char *name, bool kernel)
|
||||||
goto error1;
|
goto error1;
|
||||||
|
|
||||||
list_init(&team->image_list);
|
list_init(&team->image_list);
|
||||||
|
list_init(&team->watcher_list);
|
||||||
|
|
||||||
clear_team_debug_info(&team->debug_info, true);
|
clear_team_debug_info(&team->debug_info, true);
|
||||||
|
|
||||||
|
@ -761,10 +762,10 @@ team_delete_team(struct team *team)
|
||||||
sem_id deathSem;
|
sem_id deathSem;
|
||||||
int32 threadCount;
|
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);
|
deathSem = create_sem(0, death_sem_name);
|
||||||
if (deathSem < 0)
|
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();
|
state = disable_interrupts();
|
||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
|
@ -828,11 +829,24 @@ team_delete_team(struct team *team)
|
||||||
// free team resources
|
// free team resources
|
||||||
|
|
||||||
vm_delete_aspace(team->aspace);
|
vm_delete_aspace(team->aspace);
|
||||||
delete_owned_ports(team->id);
|
delete_owned_ports(teamID);
|
||||||
sem_delete_owned_sems(team->id);
|
sem_delete_owned_sems(teamID);
|
||||||
remove_images(team);
|
remove_images(team);
|
||||||
vfs_free_io_context(team->io_context);
|
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);
|
free(team);
|
||||||
|
|
||||||
// notify the debugger, that the team is gone
|
// 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 -
|
// #pragma mark -
|
||||||
// public team API
|
// public team API
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue