From 822e4e0b4115378a4c5f175fd651a67bd35186bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 13 Oct 2004 13:10:27 +0000 Subject: [PATCH] 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 --- src/kernel/core/thread.c | 68 ++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 114591ab4a..92eca20e6b 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -648,7 +648,7 @@ put_death_stack_and_reschedule(uint32 index) // used to pass messages between thread_exit and thread_exit2 struct thread_exit_args { - struct thread *t; + struct thread *thread; region_id old_kernel_stack; int int_state; uint32 death_stack; @@ -671,19 +671,19 @@ thread_exit2(void *_args) // delete the old kernel stack region 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); // 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(); 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(); GRAB_THREAD_LOCK(); - hash_remove(sThreadHash, args.t); + hash_remove(sThreadHash, args.thread); RELEASE_THREAD_LOCK(); // 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); // 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 put_death_stack_and_reschedule(args.death_stack); @@ -712,7 +712,7 @@ thread_exit(void) struct thread *t = thread_get_current_thread(); struct team *team = t->team; thread_id mainParentThread = -1; - bool delete_team = false; + bool deleteTeam = false; uint32 death_stack; sem_id cached_death_sem; status_t status; @@ -747,7 +747,7 @@ thread_exit(void) // Cancel previously installed alarm timer, if any 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) { region_id rid = t->user_stack_region_id; t->user_stack_region_id = -1; @@ -765,7 +765,7 @@ thread_exit(void) if (team->main_thread == t) { // this was main thread in this team - delete_team = true; + deleteTeam = true; // remember who our parent was so we can send a signal mainParentThread = team->parent->main_thread->id; @@ -781,7 +781,7 @@ thread_exit(void) } // delete the team if we're its main thread - if (delete_team) { + if (deleteTeam) { team_delete_team(team); send_signal_etc(mainParentThread, SIGCHLD, B_DO_NOT_RESCHEDULE); @@ -803,7 +803,7 @@ thread_exit(void) args.int_state = get_death_stack(&death_stack); // this disables interrups for us - args.t = t; + args.thread = t; args.old_kernel_stack = t->kernel_stack_region_id; args.death_stack = death_stack; args.death_sem = cached_death_sem; @@ -1512,53 +1512,58 @@ snooze_until(bigtime_t timeout, int timebase) status_t wait_for_thread(thread_id id, status_t *_returnCode) { - sem_id sem; + struct thread *thread; cpu_status state; - struct thread *t; - int rc; + status_t status; + 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(); GRAB_THREAD_LOCK(); - t = thread_get_thread_struct_locked(id); - sem = t != NULL ? t->return_code_sem : B_BAD_THREAD_ID; + thread = thread_get_thread_struct_locked(id); + sem = thread != NULL ? thread->return_code_sem : B_BAD_THREAD_ID; RELEASE_THREAD_LOCK(); 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 */ - if (rc == B_BAD_SEM_ID) { - rc = B_NO_ERROR; + if (status == B_BAD_SEM_ID) { + status = B_NO_ERROR; if (_returnCode) { - t = thread_get_current_thread(); + thread = thread_get_current_thread(); TRACE(("wait_for_thread: thread %ld got return code 0x%x\n", - t->id, t->sem_deleted_retcode)); - *_returnCode = t->sem_deleted_retcode; + thread->id, thread->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 suspend_thread(thread_id id) { - return send_signal_etc(id, SIGSTOP, B_DO_NOT_RESCHEDULE); + return send_signal(id, SIGSTOP); } status_t 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); - 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 status;