mirror of
https://github.com/RGBCube/serenity
synced 2025-05-29 17:45:11 +00:00
Kernel+LibPthread: Implement pthread_join()
It's now possible to block until another thread in the same process has exited. We can also retrieve its exit value, which is whatever value it passed to pthread_exit(). :^)
This commit is contained in:
parent
c6a8b95643
commit
69efa3f630
9 changed files with 117 additions and 5 deletions
|
@ -2862,9 +2862,9 @@ int Process::sys$create_thread(void* (*entry)(void*), void* argument)
|
|||
return thread->tid();
|
||||
}
|
||||
|
||||
void Process::sys$exit_thread(void* code)
|
||||
void Process::sys$exit_thread(void* exit_value)
|
||||
{
|
||||
UNUSED_PARAM(code);
|
||||
current->m_exit_value = exit_value;
|
||||
cli();
|
||||
if (¤t->process().main_thread() == current) {
|
||||
// FIXME: For POSIXy reasons, we should only sys$exit once *all* threads have exited.
|
||||
|
@ -2877,6 +2877,47 @@ void Process::sys$exit_thread(void* code)
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
int Process::sys$join_thread(int tid, void** exit_value)
|
||||
{
|
||||
if (exit_value && !validate_write_typed(exit_value))
|
||||
return -EFAULT;
|
||||
|
||||
Thread* thread = nullptr;
|
||||
for_each_thread([&](auto& child_thread) {
|
||||
if (child_thread.tid() == tid) {
|
||||
thread = &child_thread;
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
if (!thread)
|
||||
return -ESRCH;
|
||||
|
||||
if (thread == current)
|
||||
return -EDEADLK;
|
||||
|
||||
if (thread->m_joinee == current)
|
||||
return -EDEADLK;
|
||||
|
||||
ASSERT(thread->m_joiner != current);
|
||||
if (thread->m_joiner)
|
||||
return -EINVAL;
|
||||
|
||||
// FIXME: EINVAL: 'thread' is not a joinable thread
|
||||
|
||||
// FIXME: pthread_join() should not be interruptable. Enforce this somehow?
|
||||
auto result = current->block<Thread::JoinBlocker>(*thread);
|
||||
(void)result;
|
||||
|
||||
// NOTE: 'thread' is very possibly deleted at this point. Clear it just to be safe.
|
||||
thread = nullptr;
|
||||
|
||||
if (exit_value)
|
||||
*exit_value = current->m_joinee_exit_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Process::sys$gettid()
|
||||
{
|
||||
return current->tid();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue