mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[kernel] Add thread_join syscall
Thread joining is an important primitive that I seem to have totally forgotten to implement previously.
This commit is contained in:
@@ -3,6 +3,7 @@ object thread : object {
|
||||
|
||||
capabilities [
|
||||
kill
|
||||
join
|
||||
]
|
||||
|
||||
method create [constructor] {
|
||||
@@ -13,6 +14,8 @@ object thread : object {
|
||||
|
||||
method kill [destructor cap:kill]
|
||||
|
||||
method join [cap:join]
|
||||
|
||||
method exit [static]
|
||||
|
||||
method sleep [static] {
|
||||
|
||||
@@ -52,6 +52,20 @@ thread::block()
|
||||
return m_wake_value;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
thread::join()
|
||||
{
|
||||
if (has_state(state::exited))
|
||||
return j6_status_ok;
|
||||
|
||||
thread &caller = current();
|
||||
if (&caller == this)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
m_join_queue.add_thread(&caller);
|
||||
return caller.block();
|
||||
}
|
||||
|
||||
void
|
||||
thread::wake(uint64_t value)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <util/spinlock.h>
|
||||
|
||||
#include "objects/kobject.h"
|
||||
#include "wait_queue.h"
|
||||
|
||||
struct cpu_data;
|
||||
struct page_table;
|
||||
@@ -98,6 +99,9 @@ public:
|
||||
/// \returns The value passed to wake()
|
||||
uint64_t block();
|
||||
|
||||
/// Block the calling thread until this thread exits
|
||||
j6_status_t join();
|
||||
|
||||
/// Wake this thread, giving it a value
|
||||
/// \arg value The value that block() should return
|
||||
void wake(uint64_t value = 0);
|
||||
@@ -123,15 +127,16 @@ public:
|
||||
message_data & get_message_data() { return m_message_data; }
|
||||
|
||||
inline bool has_state(state s) const {
|
||||
return static_cast<uint8_t>(m_state) & static_cast<uint8_t>(s);
|
||||
return __atomic_load_n(reinterpret_cast<const uint8_t*>(&m_state), __ATOMIC_ACQUIRE) &
|
||||
static_cast<uint8_t>(s);
|
||||
}
|
||||
|
||||
inline void set_state(state s) {
|
||||
m_state = static_cast<state>(static_cast<uint8_t>(m_state) | static_cast<uint8_t>(s));
|
||||
__atomic_or_fetch(reinterpret_cast<uint8_t*>(&m_state), static_cast<uint8_t>(s), __ATOMIC_ACQ_REL);
|
||||
}
|
||||
|
||||
inline void clear_state(state s) {
|
||||
m_state = static_cast<state>(static_cast<uint8_t>(m_state) & ~static_cast<uint8_t>(s));
|
||||
__atomic_and_fetch(reinterpret_cast<uint8_t*>(&m_state), ~static_cast<uint8_t>(s), __ATOMIC_ACQ_REL);
|
||||
}
|
||||
|
||||
inline tcb_node * tcb() { return &m_tcb; }
|
||||
@@ -191,6 +196,7 @@ private:
|
||||
uint64_t m_wake_timeout;
|
||||
message_data m_message_data;
|
||||
|
||||
wait_queue m_join_queue;
|
||||
j6_handle_t m_self_handle;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,12 @@ thread_kill(thread *self)
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
thread_join(thread *self)
|
||||
{
|
||||
return self->join();
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
thread_exit()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user