load_team_etc() now optionally waits for the new team to be loaded

(new `flags' parameter, flag B_WAIT_TILL_LOADED). This is the default
behaviour for load_image(), so it behaves like R5's implementation now,
i.e. errors while loading are reported to the caller.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11696 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2005-03-12 15:13:51 +00:00
parent 0dd3a50bb3
commit 4d5289b7f0
1 changed files with 75 additions and 4 deletions

View File

@ -666,6 +666,7 @@ create_team_struct(const char *name, bool kernel)
vm_put_aspace(team->kaspace);
team->thread_list = NULL;
team->main_thread = NULL;
team->loading_info = NULL;
team->state = TEAM_STATE_BIRTH;
team->pending_signals = 0;
team->death_sem = -1;
@ -782,6 +783,30 @@ team_delete_team(struct team *team)
send_signal_etc(temp_thread->id, SIGKILLTHR, B_DO_NOT_RESCHEDULE);
temp_thread = next;
}
// If someone is waiting for this team to be loaded, but it dies
// unexpectedly before being done, we need to notify the waiting
// thread now.
if (team->loading_info) {
// there's indeed someone waiting
struct team_loading_info *loadingInfo = team->loading_info;
team->loading_info = NULL;
loadingInfo->result = B_ERROR;
loadingInfo->done = true;
GRAB_THREAD_LOCK();
// wake up the waiting thread
if (loadingInfo->thread->state == B_THREAD_SUSPENDED) {
loadingInfo->thread->state = B_THREAD_READY;
loadingInfo->thread->next_state = B_THREAD_READY;
scheduler_enqueue_in_run_queue(loadingInfo->thread);
}
RELEASE_THREAD_LOCK();
}
RELEASE_TEAM_LOCK();
restore_interrupts(state);
@ -978,7 +1003,8 @@ team_create_thread_start(void *args)
*/
static thread_id
load_image_etc(int32 argCount, char **args, int32 envCount, char **env, int32 priority)
load_image_etc(int32 argCount, char **args, int32 envCount, char **env,
int32 priority, uint32 flags)
{
struct process_group *group;
struct team *team, *parent;
@ -987,6 +1013,7 @@ load_image_etc(int32 argCount, char **args, int32 envCount, char **env, int32 pr
int err;
cpu_status state;
struct team_arg *teamArgs;
struct team_loading_info loadingInfo;
if (args == NULL || argCount == 0)
return B_BAD_VALUE;
@ -1000,6 +1027,13 @@ load_image_etc(int32 argCount, char **args, int32 envCount, char **env, int32 pr
parent = thread_get_current_thread()->team;
if (flags & B_WAIT_TILL_LOADED) {
loadingInfo.thread = thread_get_current_thread();
loadingInfo.result = B_ERROR;
loadingInfo.done = false;
team->loading_info = &loadingInfo;
}
state = disable_interrupts();
GRAB_TEAM_LOCK();
@ -1047,6 +1081,42 @@ load_image_etc(int32 argCount, char **args, int32 envCount, char **env, int32 pr
goto err4;
}
// wait for the loader of the new team to finish its work
if (flags & B_WAIT_TILL_LOADED) {
struct thread *mainThread;
state = disable_interrupts();
GRAB_THREAD_LOCK();
mainThread = thread_get_thread_struct_locked(thread);
if (mainThread) {
// resume the team's main thread
if (mainThread->state == B_THREAD_SUSPENDED) {
mainThread->state = mainThread->next_state = B_THREAD_READY;
scheduler_enqueue_in_run_queue(mainThread);
}
// Now suspend ourselves until loading is finished.
// We will be woken either be the thread, when it finished or
// aborted loading, or when the team is going to die (e.g. is
// killed). In either case the one setting `loadingInfo.done' is
// responsible for removing the info from the team structure.
while (!loadingInfo.done) {
thread_get_current_thread()->next_state = B_THREAD_SUSPENDED;
scheduler_reschedule();
}
} else {
// Impressive! Someone managed to kill the thread in this short
// time.
}
RELEASE_THREAD_LOCK();
restore_interrupts(state);
if (loadingInfo.result < B_OK)
return loadingInfo.result;
}
// notify the debugger
user_debug_team_created(team->id);
@ -1549,7 +1619,8 @@ load_image(int32 argCount, const char **args, const char **env)
return B_NO_MEMORY;
}
return load_image_etc(argCount, argsCopy, envCount, envCopy, B_NORMAL_PRIORITY);
return load_image_etc(argCount, argsCopy, envCount, envCopy,
B_NORMAL_PRIORITY, B_WAIT_TILL_LOADED);
}
@ -2125,7 +2196,7 @@ _user_wait_for_team(team_id id, status_t *_userReturnCode)
team_id
_user_load_image(int32 argCount, const char **userArgs, int32 envCount,
const char **userEnv, int32 priority)
const char **userEnv, int32 priority, uint32 flags)
{
char **args = NULL;
char **env = NULL;
@ -2144,7 +2215,7 @@ _user_load_image(int32 argCount, const char **userArgs, int32 envCount,
return B_BAD_ADDRESS;
}
return load_image_etc(argCount, args, envCount, env, priority);
return load_image_etc(argCount, args, envCount, env, priority, flags);
}