There was a race condition between removing the thread from the hash and putting
its death entry into the parent team's queue - we need to do this atomically. As an effect, wait_for_thread() sometimes failed with B_BAD_THREAD_ID. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19808 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
7383c05e71
commit
6f19c1db2d
|
@ -925,15 +925,12 @@ thread_exit(void)
|
||||||
// boost our priority to get this over with
|
// boost our priority to get this over with
|
||||||
thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY;
|
thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY;
|
||||||
|
|
||||||
// Stop debugging for this thread, and remove it from the hashtable, so it
|
// Stop debugging for this thread
|
||||||
// cannot be found afterwards anymore
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
debugInfo = thread->debug_info;
|
debugInfo = thread->debug_info;
|
||||||
clear_thread_debug_info(&thread->debug_info, true);
|
clear_thread_debug_info(&thread->debug_info, true);
|
||||||
hash_remove(sThreadHash, thread);
|
|
||||||
sUsedThreads--;
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
@ -987,6 +984,9 @@ thread_exit(void)
|
||||||
// put the thread into the kernel team until it dies
|
// put the thread into the kernel team until it dies
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
// removing the thread and putting its death entry to the parent
|
||||||
|
// team needs to be an atomic operation
|
||||||
|
|
||||||
// remember how long this thread lasted
|
// remember how long this thread lasted
|
||||||
team->dead_threads_kernel_time += thread->kernel_time;
|
team->dead_threads_kernel_time += thread->kernel_time;
|
||||||
|
@ -997,6 +997,10 @@ thread_exit(void)
|
||||||
|
|
||||||
cachedDeathSem = team->death_sem;
|
cachedDeathSem = team->death_sem;
|
||||||
|
|
||||||
|
// remove thread from hash, so it's no longer accessible
|
||||||
|
hash_remove(sThreadHash, thread);
|
||||||
|
sUsedThreads--;
|
||||||
|
|
||||||
if (deleteTeam) {
|
if (deleteTeam) {
|
||||||
struct team *parent = team->parent;
|
struct team *parent = team->parent;
|
||||||
|
|
||||||
|
@ -1013,6 +1017,8 @@ thread_exit(void)
|
||||||
} else
|
} else
|
||||||
death = NULL;
|
death = NULL;
|
||||||
|
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
|
||||||
// notify listeners that a new death entry is available
|
// notify listeners that a new death entry is available
|
||||||
// TODO: should that be moved to handle_signal() (for SIGCHLD)?
|
// TODO: should that be moved to handle_signal() (for SIGCHLD)?
|
||||||
release_sem_etc(parent->dead_children.sem,
|
release_sem_etc(parent->dead_children.sem,
|
||||||
|
@ -1022,16 +1028,30 @@ thread_exit(void)
|
||||||
|
|
||||||
parent->dead_children.waiters = 0;
|
parent->dead_children.waiters = 0;
|
||||||
team->group->dead_child_waiters = 0;
|
team->group->dead_child_waiters = 0;
|
||||||
}
|
} else
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
|
||||||
team_remove_team(team, &freeGroup);
|
team_remove_team(team, &freeGroup);
|
||||||
}
|
} else
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
|
||||||
RELEASE_TEAM_LOCK();
|
RELEASE_TEAM_LOCK();
|
||||||
|
|
||||||
// swap address spaces, to make sure we're running on the kernel's pgdir
|
// swap address spaces, to make sure we're running on the kernel's pgdir
|
||||||
vm_swap_address_space(vm_kernel_address_space());
|
vm_swap_address_space(vm_kernel_address_space());
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
TRACE(("thread_exit: thread 0x%lx now a kernel thread!\n", thread->id));
|
TRACE(("thread_exit: thread 0x%lx now a kernel thread!\n", thread->id));
|
||||||
|
} else {
|
||||||
|
// for kernel threads, we don't need to care about their death entries
|
||||||
|
state = disable_interrupts();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
|
hash_remove(sThreadHash, thread);
|
||||||
|
sUsedThreads--;
|
||||||
|
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the team if we're its main thread
|
// delete the team if we're its main thread
|
||||||
|
|
Loading…
Reference in New Issue