Kernel/LibC: Implement pthread_join

This commit is contained in:
Bananymous 2025-04-02 12:50:56 +03:00
parent e85b18e206
commit be786be67d
4 changed files with 63 additions and 2 deletions

View File

@ -185,6 +185,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_yield(); BAN::ErrorOr<long> sys_yield();
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* __restrict attr, void (*entry)(void*), void* arg); BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* __restrict attr, void (*entry)(void*), void* arg);
BAN::ErrorOr<long> sys_pthread_exit(void* value); BAN::ErrorOr<long> sys_pthread_exit(void* value);
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
BAN::ErrorOr<long> sys_pthread_self(); BAN::ErrorOr<long> sys_pthread_self();
BAN::ErrorOr<long> sys_tcgetpgrp(int fd); BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
@ -297,10 +298,11 @@ namespace Kernel
struct pthread_info_t struct pthread_info_t
{ {
Thread* thread; pthread_t thread;
void* value; void* value;
}; };
BAN::Vector<pthread_info_t> m_exited_pthreads; BAN::Vector<pthread_info_t> m_exited_pthreads;
ThreadBlocker m_pthread_exit_blocker;
uint64_t m_alarm_interval_ns { 0 }; uint64_t m_alarm_interval_ns { 0 };
uint64_t m_alarm_wake_time_ns { 0 }; uint64_t m_alarm_wake_time_ns { 0 };

View File

@ -2115,11 +2115,12 @@ namespace Kernel
if (&Thread::current() == m_threads.front()) if (&Thread::current() == m_threads.front())
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
TRY(m_exited_pthreads.emplace_back(&Thread::current(), value)); TRY(m_exited_pthreads.emplace_back(Thread::current().tid(), value));
for (auto* thread : m_threads) for (auto* thread : m_threads)
{ {
if (thread != &Thread::current()) if (thread != &Thread::current())
continue; continue;
m_pthread_exit_blocker.unblock();
m_process_lock.unlock(); m_process_lock.unlock();
thread->on_exit(); thread->on_exit();
} }
@ -2127,6 +2128,58 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
BAN::ErrorOr<long> Process::sys_pthread_join(pthread_t thread, void** value)
{
LockGuard _(m_process_lock);
if (value)
TRY(validate_pointer_access(value, sizeof(void*), true));
if (thread == Thread::current().tid())
return BAN::Error::from_errno(EINVAL);
const auto wait_thread =
[&]() -> bool
{
for (size_t i = 0; i < m_exited_pthreads.size(); i++)
{
if (m_exited_pthreads[i].thread != thread)
continue;
if (value)
*value = m_exited_pthreads[i].value;
m_exited_pthreads.remove(i);
return true;
}
return false;
};
if (wait_thread())
return 0;
{
bool found = false;
for (auto* _thread : m_threads)
if (_thread->tid() == thread)
found = true;
if (!found)
return BAN::Error::from_errno(EINVAL);
}
for (;;)
{
{
LockFreeGuard _(m_process_lock);
m_pthread_exit_blocker.block_with_timeout_ms(100);
}
if (wait_thread())
return 0;
}
}
BAN::ErrorOr<long> Process::sys_pthread_self() BAN::ErrorOr<long> Process::sys_pthread_self()
{ {
return Thread::current().tid(); return Thread::current().tid();

View File

@ -93,6 +93,7 @@ __BEGIN_DECLS
O(SYS_YIELD, yield) \ O(SYS_YIELD, yield) \
O(SYS_PTHREAD_CREATE, pthread_create) \ O(SYS_PTHREAD_CREATE, pthread_create) \
O(SYS_PTHREAD_EXIT, pthread_exit) \ O(SYS_PTHREAD_EXIT, pthread_exit) \
O(SYS_PTHREAD_JOIN, pthread_join) \
O(SYS_PTHREAD_SELF, pthread_self) \ O(SYS_PTHREAD_SELF, pthread_self) \
enum Syscall enum Syscall

View File

@ -55,6 +55,11 @@ void pthread_exit(void* value_ptr)
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
int pthread_join(pthread_t thread, void** value_ptr)
{
return syscall(SYS_PTHREAD_JOIN, thread, value_ptr);
}
pthread_t pthread_self(void) pthread_t pthread_self(void)
{ {
return syscall(SYS_PTHREAD_SELF); return syscall(SYS_PTHREAD_SELF);