LibC/Kernel: Add support for detached pthreads
This commit is contained in:
@@ -214,6 +214,7 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, 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_pthread_kill(pthread_t thread, int signal);
|
BAN::ErrorOr<long> sys_pthread_kill(pthread_t thread, int signal);
|
||||||
|
BAN::ErrorOr<long> sys_pthread_detach(pthread_t thread);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
||||||
|
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ namespace Kernel
|
|||||||
const Process& process() const;
|
const Process& process() const;
|
||||||
bool has_process() const { return m_process; }
|
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; }
|
bool is_userspace() const { return m_is_userspace; }
|
||||||
|
|
||||||
uint64_t cpu_time_ns() const;
|
uint64_t cpu_time_ns() const;
|
||||||
@@ -176,6 +179,7 @@ namespace Kernel
|
|||||||
State m_state { State::NotStarted };
|
State m_state { State::NotStarted };
|
||||||
Process* m_process { nullptr };
|
Process* m_process { nullptr };
|
||||||
bool m_is_userspace { false };
|
bool m_is_userspace { false };
|
||||||
|
BAN::Atomic<bool> m_is_detached { false };
|
||||||
bool m_delete_process { false };
|
bool m_delete_process { false };
|
||||||
|
|
||||||
vaddr_t m_fsbase { 0 };
|
vaddr_t m_fsbase { 0 };
|
||||||
|
|||||||
@@ -3334,20 +3334,24 @@ namespace Kernel
|
|||||||
if (m_threads.size() == 1)
|
if (m_threads.size() == 1)
|
||||||
return sys_exit(0);
|
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();
|
m_process_lock.unlock();
|
||||||
Thread::current().on_exit();
|
thread.on_exit();
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_pthread_join(pthread_t thread, void** user_value)
|
BAN::ErrorOr<long> Process::sys_pthread_join(pthread_t tid, void** user_value)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
if (thread == Thread::current().tid())
|
if (tid == Thread::current().tid())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
const auto check_thread =
|
const auto check_thread =
|
||||||
@@ -3355,13 +3359,10 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_exited_pthreads.size(); i++)
|
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;
|
continue;
|
||||||
|
|
||||||
void* ret = m_exited_pthreads[i].value;
|
void* ret = m_exited_pthreads[i].value;
|
||||||
|
|
||||||
m_exited_pthreads.remove(i);
|
m_exited_pthreads.remove(i);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3379,10 +3380,18 @@ namespace Kernel
|
|||||||
|
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto* _thread : m_threads)
|
bool joinable = false;
|
||||||
if (_thread->tid() == thread)
|
for (auto* thread : m_threads)
|
||||||
|
{
|
||||||
|
if (thread->tid() != tid)
|
||||||
|
continue;
|
||||||
found = true;
|
found = true;
|
||||||
|
joinable = !thread->is_detached();
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
|
return BAN::Error::from_errno(ESRCH);
|
||||||
|
if (!joinable)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3425,6 +3434,24 @@ namespace Kernel
|
|||||||
return BAN::Error::from_errno(ESRCH);
|
return BAN::Error::from_errno(ESRCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> 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<long> Process::sys_setuid(uid_t uid)
|
BAN::ErrorOr<long> Process::sys_setuid(uid_t uid)
|
||||||
{
|
{
|
||||||
if (uid < 0 || uid >= 1'000'000'000)
|
if (uid < 0 || uid >= 1'000'000'000)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ __BEGIN_DECLS
|
|||||||
O(SYS_PTHREAD_JOIN, pthread_join) \
|
O(SYS_PTHREAD_JOIN, pthread_join) \
|
||||||
O(SYS_PTHREAD_SELF, pthread_self) \
|
O(SYS_PTHREAD_SELF, pthread_self) \
|
||||||
O(SYS_PTHREAD_KILL, pthread_kill) \
|
O(SYS_PTHREAD_KILL, pthread_kill) \
|
||||||
|
O(SYS_PTHREAD_DETACH, pthread_detach) \
|
||||||
O(SYS_EPOLL_CREATE1, epoll_create1) \
|
O(SYS_EPOLL_CREATE1, epoll_create1) \
|
||||||
O(SYS_EPOLL_CTL, epoll_ctl) \
|
O(SYS_EPOLL_CTL, epoll_ctl) \
|
||||||
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
struct pthread_trampoline_info_t
|
struct pthread_trampoline_info_t
|
||||||
{
|
{
|
||||||
struct uthread* uthread;
|
struct uthread* uthread;
|
||||||
|
bool detached;
|
||||||
void* (*start_routine)(void*);
|
void* (*start_routine)(void*);
|
||||||
void* arg;
|
void* arg;
|
||||||
};
|
};
|
||||||
@@ -71,6 +72,8 @@ extern "C" void _pthread_trampoline_cpp(void* arg)
|
|||||||
#endif
|
#endif
|
||||||
free(arg);
|
free(arg);
|
||||||
signal(SIGCANCEL, &_pthread_cancel_handler);
|
signal(SIGCANCEL, &_pthread_cancel_handler);
|
||||||
|
if (info.detached)
|
||||||
|
pthread_detach(info.uthread->id);
|
||||||
pthread_exit(info.start_routine(info.arg));
|
pthread_exit(info.start_routine(info.arg));
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -257,8 +260,6 @@ int pthread_attr_setdetachstate(pthread_attr_t* attr, int detachstate)
|
|||||||
switch (detachstate)
|
switch (detachstate)
|
||||||
{
|
{
|
||||||
case PTHREAD_CREATE_DETACHED:
|
case PTHREAD_CREATE_DETACHED:
|
||||||
dwarnln("TODO: pthread_attr_setdetachstate");
|
|
||||||
return ENOTSUP;
|
|
||||||
case PTHREAD_CREATE_JOINABLE:
|
case PTHREAD_CREATE_JOINABLE:
|
||||||
attr->detachstate = detachstate;
|
attr->detachstate = detachstate;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -386,6 +387,7 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
|||||||
|
|
||||||
*info = {
|
*info = {
|
||||||
.uthread = nullptr,
|
.uthread = nullptr,
|
||||||
|
.detached = attr ? (attr->detachstate == PTHREAD_CREATE_DETACHED) : false,
|
||||||
.start_routine = start_routine,
|
.start_routine = start_routine,
|
||||||
.arg = arg,
|
.arg = arg,
|
||||||
};
|
};
|
||||||
@@ -448,9 +450,7 @@ pthread_create_error:
|
|||||||
|
|
||||||
int pthread_detach(pthread_t thread)
|
int pthread_detach(pthread_t thread)
|
||||||
{
|
{
|
||||||
(void)thread;
|
return syscall(SYS_PTHREAD_DETACH, thread);
|
||||||
dwarnln("TODO: pthread_detach");
|
|
||||||
return ENOTSUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pthread_exit(void* value_ptr)
|
void pthread_exit(void* value_ptr)
|
||||||
|
|||||||
Reference in New Issue
Block a user