Compare commits

...

3 Commits

Author SHA1 Message Date
7b4cfd52cd
Scheduler: Don't search threads spawned before the current thread to find children
All checks were successful
continuous-integration/drone/push Build is passing
Children will always be spawned later (and thus have a higher PID) than their parent.
2023-04-28 15:19:01 +02:00
bcdec62f51
kernel: Allow returning early from Scheduler::for_each_child 2023-04-28 15:13:53 +02:00
f3ffdd32d4
libluna: Add support for range-based iteration to LinkedList 2023-04-28 15:12:21 +02:00
5 changed files with 83 additions and 26 deletions

View File

@ -7,7 +7,10 @@ Result<u64> sys_exit(Registers*, SyscallArgs args)
Thread* current = Scheduler::current(); Thread* current = Scheduler::current();
Scheduler::for_each_child((pid_t)current->id, [](Thread* child) { child->parent_id = 1; }); Scheduler::for_each_child(current, [](Thread* child) {
child->parent_id = 1;
return true;
});
current->status = status; current->status = status;
current->state = ThreadState::Exited; current->state = ThreadState::Exited;

View File

@ -27,11 +27,11 @@ Result<u64> sys_waitpid(Registers*, SyscallArgs args)
} }
else if (pid == -1) else if (pid == -1)
{ {
if (!Scheduler::has_children((pid_t)current->id)) return err(ECHILD); if (!Scheduler::has_children(current)) return err(ECHILD);
Option<Thread*> child; Option<Thread*> child;
while (child = Scheduler::find_exited_child((pid_t)current->id), !child.has_value()) while (child = Scheduler::find_exited_child(current), !child.has_value())
{ {
if (options & WNOHANG) return err(EAGAIN); if (options & WNOHANG) return err(EAGAIN);
kernel_sleep(10); kernel_sleep(10);

View File

@ -249,12 +249,13 @@ namespace Scheduler
g_current->ticks_left--; g_current->ticks_left--;
g_threads.for_each([](Thread* thread) { for (auto* const thread : g_threads)
{
if (thread->state == ThreadState::Sleeping) if (thread->state == ThreadState::Sleeping)
{ {
if (--thread->sleep_ticks_left == 0) thread->state = ThreadState::Runnable; if (--thread->sleep_ticks_left == 0) thread->state = ThreadState::Runnable;
} }
}); }
if (!g_current->ticks_left) switch_task(regs); if (!g_current->ticks_left) switch_task(regs);
} }
@ -276,30 +277,37 @@ namespace Scheduler
Option<Thread*> find_by_pid(pid_t pid) Option<Thread*> find_by_pid(pid_t pid)
{ {
Option<Thread*> result; for (auto* const thread : g_threads)
{
if (thread->id == (u64)pid && thread->state != ThreadState::Dying) return thread;
}
g_threads.for_each([&](Thread* thread) { return {};
if (thread->id == (u64)pid && thread->state != ThreadState::Dying) result = thread; }
bool has_children(Thread* thread)
{
bool result { false };
for_each_child(thread, [&](Thread*) {
result = true;
return false;
}); });
return result; return result;
} }
bool has_children(pid_t pid) Option<Thread*> find_exited_child(Thread* thread)
{
bool result { false };
for_each_child(pid, [&](Thread*) { result = true; });
return result;
}
Option<Thread*> find_exited_child(pid_t pid)
{ {
Option<Thread*> result; Option<Thread*> result;
for_each_child(pid, [&](Thread* child) { for_each_child(thread, [&](Thread* child) {
if (!result.has_value() && child->state == ThreadState::Exited) result = child; if (!result.has_value() && child->state == ThreadState::Exited)
{
result = child;
return false;
}
return true;
}); });
return result; return result;

View File

@ -29,16 +29,21 @@ namespace Scheduler
Option<Thread*> find_by_pid(pid_t pid); Option<Thread*> find_by_pid(pid_t pid);
template <typename Callback> void for_each_child(pid_t pid, Callback callback) template <typename Callback> void for_each_child(Thread* thread, Callback callback)
{ {
g_threads.for_each([&](Thread* thread) { for (Thread* current = thread; current; current = g_threads.next(current).value_or(nullptr))
if (thread->parent_id == (u64)pid) callback(thread); {
}); if (current && current->parent_id == thread->id)
{
bool should_continue = callback(current);
if (!should_continue) return;
}
}
} }
bool has_children(pid_t pid); bool has_children(Thread* thread);
Option<Thread*> find_exited_child(pid_t pid); Option<Thread*> find_exited_child(Thread* thread);
} }
extern "C" void kernel_yield(); extern "C" void kernel_yield();

View File

@ -210,6 +210,47 @@ template <typename T> class LinkedList
return m_count; return m_count;
} }
struct LinkedListIterator
{
typedef T* PtrT;
private:
LinkedListIterator(PtrT ptr, LinkedList<T>& list) : m_ptr(ptr), m_list(list)
{
}
PtrT m_ptr;
LinkedList<T>& m_list;
public:
PtrT& operator*()
{
return m_ptr;
}
void operator++()
{
m_ptr = m_list.next(m_ptr).value_or(nullptr);
}
bool operator!=(LinkedListIterator& other)
{
return m_ptr != other.m_ptr || &m_list != &other.m_list;
}
friend class LinkedList<T>;
};
LinkedListIterator begin()
{
return { (T*)m_start_node, *this };
}
LinkedListIterator end()
{
return { nullptr, *this };
}
private: private:
Node* m_start_node = nullptr; Node* m_start_node = nullptr;
Node* m_end_node = nullptr; Node* m_end_node = nullptr;