diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 90b2ae84..6cea93c7 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -214,6 +214,7 @@ namespace Kernel BAN::ErrorOr sys_pthread_join(pthread_t thread, void** value); BAN::ErrorOr sys_pthread_self(); BAN::ErrorOr sys_pthread_kill(pthread_t thread, int signal); + BAN::ErrorOr sys_pthread_detach(pthread_t thread); BAN::ErrorOr sys_clock_gettime(clockid_t, timespec*); diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index 845ebe03..35bb1189 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -117,6 +117,9 @@ namespace Kernel const Process& process() const; bool has_process() const { return m_process; } + void detach() { m_is_detached = true; } + bool is_detached() const { return m_is_detached; } + bool is_userspace() const { return m_is_userspace; } uint64_t cpu_time_ns() const; @@ -176,6 +179,7 @@ namespace Kernel State m_state { State::NotStarted }; Process* m_process { nullptr }; bool m_is_userspace { false }; + BAN::Atomic m_is_detached { false }; bool m_delete_process { false }; vaddr_t m_fsbase { 0 }; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index d2ff1f6e..5a67dded 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -3334,20 +3334,24 @@ namespace Kernel if (m_threads.size() == 1) return sys_exit(0); - TRY(m_exited_pthreads.emplace_back(Thread::current().tid(), value)); + auto& thread = Thread::current(); + if (!thread.is_detached()) + { + TRY(m_exited_pthreads.emplace_back(thread.tid(), value)); + m_pthread_exit_blocker.unblock(); + } - m_pthread_exit_blocker.unblock(); m_process_lock.unlock(); - Thread::current().on_exit(); + thread.on_exit(); ASSERT_NOT_REACHED(); } - BAN::ErrorOr Process::sys_pthread_join(pthread_t thread, void** user_value) + BAN::ErrorOr Process::sys_pthread_join(pthread_t tid, void** user_value) { LockGuard _(m_process_lock); - if (thread == Thread::current().tid()) + if (tid == Thread::current().tid()) return BAN::Error::from_errno(EINVAL); const auto check_thread = @@ -3355,13 +3359,10 @@ namespace Kernel { for (size_t i = 0; i < m_exited_pthreads.size(); i++) { - if (m_exited_pthreads[i].thread != thread) + if (m_exited_pthreads[i].thread != tid) continue; - void* ret = m_exited_pthreads[i].value; - m_exited_pthreads.remove(i); - return ret; } @@ -3379,10 +3380,18 @@ namespace Kernel { bool found = false; - for (auto* _thread : m_threads) - if (_thread->tid() == thread) - found = true; + bool joinable = false; + for (auto* thread : m_threads) + { + if (thread->tid() != tid) + continue; + found = true; + joinable = !thread->is_detached(); + break; + } if (!found) + return BAN::Error::from_errno(ESRCH); + if (!joinable) return BAN::Error::from_errno(EINVAL); } @@ -3425,6 +3434,24 @@ namespace Kernel return BAN::Error::from_errno(ESRCH); } + BAN::ErrorOr Process::sys_pthread_detach(pthread_t tid) + { + LockGuard _(m_process_lock); + + for (auto* thread : m_threads) + { + if (thread->tid() != tid) + continue; + if (thread->is_detached()) + return BAN::Error::from_errno(EINVAL); + thread->detach(); + m_pthread_exit_blocker.unblock(); + return 0; + } + + return BAN::Error::from_errno(ESRCH); + } + BAN::ErrorOr Process::sys_setuid(uid_t uid) { if (uid < 0 || uid >= 1'000'000'000) diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index be6c98d6..6b0906a0 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -105,6 +105,7 @@ __BEGIN_DECLS O(SYS_PTHREAD_JOIN, pthread_join) \ O(SYS_PTHREAD_SELF, pthread_self) \ O(SYS_PTHREAD_KILL, pthread_kill) \ + O(SYS_PTHREAD_DETACH, pthread_detach) \ O(SYS_EPOLL_CREATE1, epoll_create1) \ O(SYS_EPOLL_CTL, epoll_ctl) \ O(SYS_EPOLL_PWAIT2, epoll_pwait2) \ diff --git a/userspace/libraries/LibC/pthread.cpp b/userspace/libraries/LibC/pthread.cpp index 18db748e..8596d23a 100644 --- a/userspace/libraries/LibC/pthread.cpp +++ b/userspace/libraries/LibC/pthread.cpp @@ -18,6 +18,7 @@ struct pthread_trampoline_info_t { struct uthread* uthread; + bool detached; void* (*start_routine)(void*); void* arg; }; @@ -71,6 +72,8 @@ extern "C" void _pthread_trampoline_cpp(void* arg) #endif free(arg); signal(SIGCANCEL, &_pthread_cancel_handler); + if (info.detached) + pthread_detach(info.uthread->id); pthread_exit(info.start_routine(info.arg)); ASSERT_NOT_REACHED(); } @@ -257,8 +260,6 @@ int pthread_attr_setdetachstate(pthread_attr_t* attr, int detachstate) switch (detachstate) { case PTHREAD_CREATE_DETACHED: - dwarnln("TODO: pthread_attr_setdetachstate"); - return ENOTSUP; case PTHREAD_CREATE_JOINABLE: attr->detachstate = detachstate; return 0; @@ -386,6 +387,7 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest *info = { .uthread = nullptr, + .detached = attr ? (attr->detachstate == PTHREAD_CREATE_DETACHED) : false, .start_routine = start_routine, .arg = arg, }; @@ -448,9 +450,7 @@ pthread_create_error: int pthread_detach(pthread_t thread) { - (void)thread; - dwarnln("TODO: pthread_detach"); - return ENOTSUP; + return syscall(SYS_PTHREAD_DETACH, thread); } void pthread_exit(void* value_ptr)