Restructure wait_for_thread_etc() to make it easier to follow.
* Avoid needless adding of the death entry if the sem is gone already. * Delete objects as soon as they aren't needed anymore and return early where possible. * Contain the thread == NULL case in its block and return from there as well instead of non-obviously figuring out what happened later. * Pull out the return code asignment. * Minor cleanup.
This commit is contained in:
@@ -2465,10 +2465,7 @@ status_t
|
|||||||
wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
||||||
status_t *_returnCode)
|
status_t *_returnCode)
|
||||||
{
|
{
|
||||||
job_control_entry* freeDeath = NULL;
|
if (id < 0)
|
||||||
status_t status = B_OK;
|
|
||||||
|
|
||||||
if (id < B_OK)
|
|
||||||
return B_BAD_THREAD_ID;
|
return B_BAD_THREAD_ID;
|
||||||
|
|
||||||
// get the thread, queue our death entry, and fetch the semaphore we have to
|
// get the thread, queue our death entry, and fetch the semaphore we have to
|
||||||
@@ -2480,16 +2477,14 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
|||||||
if (thread != NULL) {
|
if (thread != NULL) {
|
||||||
// remember the semaphore we have to wait on and place our death entry
|
// remember the semaphore we have to wait on and place our death entry
|
||||||
exitSem = thread->exit.sem;
|
exitSem = thread->exit.sem;
|
||||||
list_add_link_to_head(&thread->exit.waiters, &death);
|
if (exitSem >= 0)
|
||||||
|
list_add_link_to_head(&thread->exit.waiters, &death);
|
||||||
|
|
||||||
thread->UnlockAndReleaseReference();
|
thread->UnlockAndReleaseReference();
|
||||||
// Note: We mustn't dereference the pointer afterwards, only check
|
|
||||||
// it.
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_death_entry* threadDeathEntry = NULL;
|
if (exitSem < 0)
|
||||||
|
return B_BAD_THREAD_ID;
|
||||||
if (thread == NULL) {
|
} else {
|
||||||
// we couldn't find this thread -- maybe it's already gone, and we'll
|
// we couldn't find this thread -- maybe it's already gone, and we'll
|
||||||
// find its death entry in our team
|
// find its death entry in our team
|
||||||
Team* team = thread_get_current_thread()->team;
|
Team* team = thread_get_current_thread()->team;
|
||||||
@@ -2498,47 +2493,43 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
|||||||
// check the child death entries first (i.e. main threads of child
|
// check the child death entries first (i.e. main threads of child
|
||||||
// teams)
|
// teams)
|
||||||
bool deleteEntry;
|
bool deleteEntry;
|
||||||
freeDeath = team_get_death_entry(team, id, &deleteEntry);
|
job_control_entry* freeDeath
|
||||||
|
= team_get_death_entry(team, id, &deleteEntry);
|
||||||
if (freeDeath != NULL) {
|
if (freeDeath != NULL) {
|
||||||
death.status = freeDeath->status;
|
death.status = freeDeath->status;
|
||||||
if (!deleteEntry)
|
if (deleteEntry)
|
||||||
freeDeath = NULL;
|
delete freeDeath;
|
||||||
} else {
|
} else {
|
||||||
// check the thread death entries of the team (non-main threads)
|
// check the thread death entries of the team (non-main threads)
|
||||||
|
thread_death_entry* threadDeathEntry = NULL;
|
||||||
while ((threadDeathEntry = (thread_death_entry*)list_get_next_item(
|
while ((threadDeathEntry = (thread_death_entry*)list_get_next_item(
|
||||||
&team->dead_threads, threadDeathEntry)) != NULL) {
|
&team->dead_threads, threadDeathEntry)) != NULL) {
|
||||||
if (threadDeathEntry->thread == id) {
|
if (threadDeathEntry->thread == id) {
|
||||||
list_remove_item(&team->dead_threads, threadDeathEntry);
|
list_remove_item(&team->dead_threads, threadDeathEntry);
|
||||||
team->dead_threads_count--;
|
team->dead_threads_count--;
|
||||||
death.status = threadDeathEntry->status;
|
death.status = threadDeathEntry->status;
|
||||||
|
free(threadDeathEntry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadDeathEntry == NULL)
|
if (threadDeathEntry == NULL)
|
||||||
status = B_BAD_THREAD_ID;
|
return B_BAD_THREAD_ID;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (thread == NULL && status == B_OK) {
|
|
||||||
// we found the thread's death entry in our team
|
// we found the thread's death entry in our team
|
||||||
if (_returnCode)
|
if (_returnCode)
|
||||||
*_returnCode = death.status;
|
*_returnCode = death.status;
|
||||||
|
|
||||||
delete freeDeath;
|
|
||||||
free(threadDeathEntry);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to wait for the death of the thread
|
// we need to wait for the death of the thread
|
||||||
|
|
||||||
if (exitSem < 0)
|
|
||||||
return B_BAD_THREAD_ID;
|
|
||||||
|
|
||||||
resume_thread(id);
|
resume_thread(id);
|
||||||
// make sure we don't wait forever on a suspended thread
|
// make sure we don't wait forever on a suspended thread
|
||||||
|
|
||||||
status = acquire_sem_etc(exitSem, 1, flags, timeout);
|
status_t status = acquire_sem_etc(exitSem, 1, flags, timeout);
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
// this should never happen as the thread deletes the semaphore on exit
|
// this should never happen as the thread deletes the semaphore on exit
|
||||||
@@ -2546,9 +2537,6 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
|||||||
} else if (status == B_BAD_SEM_ID) {
|
} else if (status == B_BAD_SEM_ID) {
|
||||||
// this is the way the thread normally exits
|
// this is the way the thread normally exits
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
|
|
||||||
if (_returnCode)
|
|
||||||
*_returnCode = death.status;
|
|
||||||
} else {
|
} else {
|
||||||
// We were probably interrupted or the timeout occurred; we need to
|
// We were probably interrupted or the timeout occurred; we need to
|
||||||
// remove our death entry now.
|
// remove our death entry now.
|
||||||
@@ -2563,12 +2551,12 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
|||||||
// middle of the cleanup.
|
// middle of the cleanup.
|
||||||
acquire_sem(exitSem);
|
acquire_sem(exitSem);
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
|
|
||||||
if (_returnCode != NULL)
|
|
||||||
*_returnCode = death.status;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status == B_OK && _returnCode != NULL)
|
||||||
|
*_returnCode = death.status;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user