[kernel] Delete processes & threads only via refcounts

Previously processes and threads would be deleted by the scheduler. Now,
only delete them based on refcounts - this allows joining an
already-exited thread, for instance.
This commit is contained in:
Justin C. Miller
2023-02-19 14:37:31 -08:00
parent 274891854f
commit 723f7d0330
6 changed files with 25 additions and 28 deletions

View File

@@ -60,8 +60,9 @@ process::exit(int32_t code)
util::scoped_lock lock {m_threads_lock};
for (auto *thread : m_threads) {
if (thread != &current)
if (thread != &current) {
thread->exit();
}
}
lock.release();
@@ -82,6 +83,7 @@ process::create_thread(uintptr_t rsp3, uint8_t priority)
thread *th = new thread(*this, priority);
kassert(th, "Failed to create thread!");
th->handle_retain();
if (rsp3)
th->tcb()->rsp3 = rsp3;
@@ -91,23 +93,25 @@ process::create_thread(uintptr_t rsp3, uint8_t priority)
return th;
}
bool
void
process::thread_exited(thread *th)
{
util::scoped_lock lock {m_threads_lock};
kassert(&th->m_parent == this, "Process got thread_exited for non-child!");
m_threads.remove_swap(th);
remove_handle(th->self_handle());
delete th;
// TODO: delete the thread's stack VMA
if (m_threads.empty() && m_state != state::exited) {
exit(-1);
return true;
if (m_state != state::exited) {
// if we're already going away, just release
// the thread's handle and skip all this
util::scoped_lock lock {m_threads_lock};
m_threads.remove_swap(th);
// TODO: delete the thread's stack VMA
if (m_threads.empty()) {
lock.release();
exit(-1);
}
}
return false;
th->handle_release();
}
void

View File

@@ -75,11 +75,7 @@ public:
/// Inform the process of an exited thread
/// \args th The thread which has exited
/// \returns True if this thread ending has ended the process
bool thread_exited(thread *th);
/// Get the handle for this process to refer to itself
inline j6_handle_t self_handle() const { return m_self_handle; }
void thread_exited(thread *th);
/// Get the process object that owns kernel threads and the
/// kernel address space

View File

@@ -22,6 +22,7 @@ thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) :
m_wake_value {0},
m_wake_timeout {0}
{
parent.handle_retain();
parent.space().initialize_tcb(m_tcb);
m_tcb.priority = pri;
m_tcb.thread = this;
@@ -37,6 +38,7 @@ thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) :
thread::~thread()
{
g_kernel_stacks.return_section(m_tcb.kernel_stack);
m_parent.handle_release();
}
thread & thread::current() { return *current_cpu().thread; }
@@ -99,6 +101,7 @@ thread::exit()
{
m_wake_timeout = 0;
set_state(state::exited);
m_parent.thread_exited(this);
m_join_queue.clear();
block();
}

View File

@@ -170,11 +170,6 @@ public:
/// \arg rsp The existing stack for the idle thread
static thread * create_idle_thread(process &kernel, uintptr_t rsp);
protected:
/// Don't delete a thread on no handles, the scheduler takes
/// care of that.
virtual void on_no_handles() override {}
private:
thread() = delete;
thread(const thread &other) = delete;