1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 08:25:07 +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:
Andreas Kling 2019-11-14 20:58:23 +01:00
parent c6a8b95643
commit 69efa3f630
9 changed files with 117 additions and 5 deletions

View file

@ -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 (&current->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();