suspend_thread() and resume_thread() no longer have the B_DO_NOT_RESCHEDULE

flag set.
Fixes _user_wait_for_thread() which returned an invalid return code in case
of error.
Some minor cosmetics.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9321 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-10-13 13:10:27 +00:00
parent 8880d1a7b4
commit 822e4e0b41
+37 -31
View File
@@ -648,7 +648,7 @@ put_death_stack_and_reschedule(uint32 index)
// used to pass messages between thread_exit and thread_exit2 // used to pass messages between thread_exit and thread_exit2
struct thread_exit_args { struct thread_exit_args {
struct thread *t; struct thread *thread;
region_id old_kernel_stack; region_id old_kernel_stack;
int int_state; int int_state;
uint32 death_stack; uint32 death_stack;
@@ -671,19 +671,19 @@ thread_exit2(void *_args)
// delete the old kernel stack region // delete the old kernel stack region
TRACE(("thread_exit2: deleting old kernel stack id 0x%lx for thread 0x%lx\n", TRACE(("thread_exit2: deleting old kernel stack id 0x%lx for thread 0x%lx\n",
args.old_kernel_stack, args.t->id)); args.old_kernel_stack, args.thread->id));
delete_area(args.old_kernel_stack); delete_area(args.old_kernel_stack);
// remove this thread from all of the global lists // remove this thread from all of the global lists
TRACE(("thread_exit2: removing thread 0x%lx from global lists\n", args.t->id)); TRACE(("thread_exit2: removing thread 0x%lx from global lists\n", args.thread->id));
disable_interrupts(); disable_interrupts();
GRAB_TEAM_LOCK(); GRAB_TEAM_LOCK();
remove_thread_from_team(team_get_kernel_team(), args.t); remove_thread_from_team(team_get_kernel_team(), args.thread);
RELEASE_TEAM_LOCK(); RELEASE_TEAM_LOCK();
GRAB_THREAD_LOCK(); GRAB_THREAD_LOCK();
hash_remove(sThreadHash, args.t); hash_remove(sThreadHash, args.thread);
RELEASE_THREAD_LOCK(); RELEASE_THREAD_LOCK();
// restore former thread interrupts (doesn't matter much at this point anyway) // restore former thread interrupts (doesn't matter much at this point anyway)
@@ -695,7 +695,7 @@ thread_exit2(void *_args)
release_sem_etc(args.death_sem, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(args.death_sem, 1, B_DO_NOT_RESCHEDULE);
// set the next state to be gone. Will return the thread structure to a ready pool upon reschedule // set the next state to be gone. Will return the thread structure to a ready pool upon reschedule
args.t->next_state = THREAD_STATE_FREE_ON_RESCHED; args.thread->next_state = THREAD_STATE_FREE_ON_RESCHED;
// return the death stack and reschedule one last time // return the death stack and reschedule one last time
put_death_stack_and_reschedule(args.death_stack); put_death_stack_and_reschedule(args.death_stack);
@@ -712,7 +712,7 @@ thread_exit(void)
struct thread *t = thread_get_current_thread(); struct thread *t = thread_get_current_thread();
struct team *team = t->team; struct team *team = t->team;
thread_id mainParentThread = -1; thread_id mainParentThread = -1;
bool delete_team = false; bool deleteTeam = false;
uint32 death_stack; uint32 death_stack;
sem_id cached_death_sem; sem_id cached_death_sem;
status_t status; status_t status;
@@ -747,7 +747,7 @@ thread_exit(void)
// Cancel previously installed alarm timer, if any // Cancel previously installed alarm timer, if any
cancel_timer(&t->alarm); cancel_timer(&t->alarm);
// delete the user stack region first // delete the user stack region first, we won't need it anymore
if (team->aspace != NULL && t->user_stack_region_id >= 0) { if (team->aspace != NULL && t->user_stack_region_id >= 0) {
region_id rid = t->user_stack_region_id; region_id rid = t->user_stack_region_id;
t->user_stack_region_id = -1; t->user_stack_region_id = -1;
@@ -765,7 +765,7 @@ thread_exit(void)
if (team->main_thread == t) { if (team->main_thread == t) {
// this was main thread in this team // this was main thread in this team
delete_team = true; deleteTeam = true;
// remember who our parent was so we can send a signal // remember who our parent was so we can send a signal
mainParentThread = team->parent->main_thread->id; mainParentThread = team->parent->main_thread->id;
@@ -781,7 +781,7 @@ thread_exit(void)
} }
// delete the team if we're its main thread // delete the team if we're its main thread
if (delete_team) { if (deleteTeam) {
team_delete_team(team); team_delete_team(team);
send_signal_etc(mainParentThread, SIGCHLD, B_DO_NOT_RESCHEDULE); send_signal_etc(mainParentThread, SIGCHLD, B_DO_NOT_RESCHEDULE);
@@ -803,7 +803,7 @@ thread_exit(void)
args.int_state = get_death_stack(&death_stack); args.int_state = get_death_stack(&death_stack);
// this disables interrups for us // this disables interrups for us
args.t = t; args.thread = t;
args.old_kernel_stack = t->kernel_stack_region_id; args.old_kernel_stack = t->kernel_stack_region_id;
args.death_stack = death_stack; args.death_stack = death_stack;
args.death_sem = cached_death_sem; args.death_sem = cached_death_sem;
@@ -1512,53 +1512,58 @@ snooze_until(bigtime_t timeout, int timebase)
status_t status_t
wait_for_thread(thread_id id, status_t *_returnCode) wait_for_thread(thread_id id, status_t *_returnCode)
{ {
sem_id sem; struct thread *thread;
cpu_status state; cpu_status state;
struct thread *t; status_t status;
int rc; sem_id sem;
// we need to resume the thread we're waiting for first
status = resume_thread(id);
if (status != B_OK)
return status;
rc = send_signal_etc(id, SIGCONT, 0);
if (rc != B_OK)
return rc;
state = disable_interrupts(); state = disable_interrupts();
GRAB_THREAD_LOCK(); GRAB_THREAD_LOCK();
t = thread_get_thread_struct_locked(id); thread = thread_get_thread_struct_locked(id);
sem = t != NULL ? t->return_code_sem : B_BAD_THREAD_ID; sem = thread != NULL ? thread->return_code_sem : B_BAD_THREAD_ID;
RELEASE_THREAD_LOCK(); RELEASE_THREAD_LOCK();
restore_interrupts(state); restore_interrupts(state);
rc = acquire_sem(sem); if (sem == B_BAD_THREAD_ID)
return B_BAD_THREAD_ID;
status = acquire_sem(sem);
/* This thread died the way it should, dont ripple a non-error up */ /* This thread died the way it should, dont ripple a non-error up */
if (rc == B_BAD_SEM_ID) { if (status == B_BAD_SEM_ID) {
rc = B_NO_ERROR; status = B_NO_ERROR;
if (_returnCode) { if (_returnCode) {
t = thread_get_current_thread(); thread = thread_get_current_thread();
TRACE(("wait_for_thread: thread %ld got return code 0x%x\n", TRACE(("wait_for_thread: thread %ld got return code 0x%x\n",
t->id, t->sem_deleted_retcode)); thread->id, thread->sem_deleted_retcode));
*_returnCode = t->sem_deleted_retcode; *_returnCode = thread->sem_deleted_retcode;
} }
} } else if (status == B_OK)
panic("could acquire return_code_sem for thread %lx\n", id);
return rc; return status;
} }
status_t status_t
suspend_thread(thread_id id) suspend_thread(thread_id id)
{ {
return send_signal_etc(id, SIGSTOP, B_DO_NOT_RESCHEDULE); return send_signal(id, SIGSTOP);
} }
status_t status_t
resume_thread(thread_id id) resume_thread(thread_id id)
{ {
return send_signal_etc(id, SIGCONT, B_DO_NOT_RESCHEDULE); return send_signal(id, SIGCONT);
} }
@@ -1748,7 +1753,8 @@ _user_wait_for_thread(thread_id id, status_t *userReturnCode)
status = wait_for_thread(id, &returnCode); status = wait_for_thread(id, &returnCode);
if (userReturnCode && user_memcpy(userReturnCode, &returnCode, sizeof(status_t)) < B_OK) if (status == B_OK && userReturnCode != NULL
&& user_memcpy(userReturnCode, &returnCode, sizeof(status_t)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
return status; return status;