Kernel/LibC: Implement pthread_join
This commit is contained in:
parent
e85b18e206
commit
be786be67d
|
@ -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 };
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue