From 1b7625581d87ee0601c007b63518a064c4c4ab44 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 16 Mar 2023 12:17:04 +0200 Subject: [PATCH] Kernel: Add basic concept of Processes We now create Shell as a process that has its own threads --- BAN/include/BAN/Memory.h | 18 ++++++----- kernel/Makefile | 1 + kernel/include/kernel/Process.h | 40 ++++++++++++++++++++++++ kernel/include/kernel/Scheduler.h | 4 +-- kernel/include/kernel/Thread.h | 27 ++++++++++------ kernel/kernel/Process.cpp | 37 ++++++++++++++++++++++ kernel/kernel/Scheduler.cpp | 1 + kernel/kernel/Shell.cpp | 4 +-- kernel/kernel/Thread.cpp | 25 ++++++++++----- kernel/kernel/kernel.cpp | 51 ++++++++++++++++++------------- libc/include/sys/types.h | 10 ++++++ 11 files changed, 170 insertions(+), 48 deletions(-) create mode 100644 kernel/include/kernel/Process.h create mode 100644 kernel/kernel/Process.cpp create mode 100644 libc/include/sys/types.h diff --git a/BAN/include/BAN/Memory.h b/BAN/include/BAN/Memory.h index b9cb44ab7..0d9c1f221 100644 --- a/BAN/include/BAN/Memory.h +++ b/BAN/include/BAN/Memory.h @@ -62,12 +62,21 @@ namespace BAN { public: RefPtr() = default; + RefPtr(T* pointer) + { + m_pointer = pointer; + if (m_pointer) + m_pointer->ref(); + } + ~RefPtr() { clear(); } template static RefPtr adopt(U* pointer) { - return RefPtr(pointer); + RefPtr ptr; + ptr.m_pointer = pointer; + return ptr; } template @@ -76,7 +85,7 @@ namespace BAN T* pointer = new T(forward(args)...); if (pointer == nullptr) return Error::from_errno(ENOMEM); - return RefPtr(pointer); + return adopt(pointer); } RefPtr(const RefPtr& other) { *this = other; } @@ -118,11 +127,6 @@ namespace BAN m_pointer = nullptr; } - private: - RefPtr(T* pointer) - : m_pointer(pointer) - {} - private: T* m_pointer = nullptr; }; diff --git a/kernel/Makefile b/kernel/Makefile index 74cbfc133..c3169a56d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -50,6 +50,7 @@ kernel/kmalloc.o \ kernel/PCI.o \ kernel/PIC.o \ kernel/PIT.o \ +kernel/Process.o \ kernel/RTC.o \ kernel/Scheduler.o \ kernel/Serial.o \ diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h new file mode 100644 index 000000000..fa45ae2ce --- /dev/null +++ b/kernel/include/kernel/Process.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include + +namespace Kernel +{ + + class Process : BAN::RefCounted + { + BAN_NON_COPYABLE(Process); + BAN_NON_MOVABLE(Process); + + public: + using entry_t = Thread::entry_t; + + public: + static BAN::ErrorOr> create_kernel(entry_t, void*); + ~Process() {} + + BAN::ErrorOr add_thread(entry_t, void*); + void on_thread_exit(Thread&); + + pid_t pid() const { return m_pid; } + + static BAN::RefPtr current() { return Thread::current()->process(); } + + private: + Process(pid_t pid) : m_pid(pid) {} + + private: + pid_t m_pid = 0; + BAN::String m_working_directory; + BAN::Vector> m_threads; + + friend class BAN::RefPtr; + }; + +} \ No newline at end of file diff --git a/kernel/include/kernel/Scheduler.h b/kernel/include/kernel/Scheduler.h index 3a4bf7014..f0ee003c1 100644 --- a/kernel/include/kernel/Scheduler.h +++ b/kernel/include/kernel/Scheduler.h @@ -21,11 +21,11 @@ namespace Kernel void set_current_thread_sleeping(uint64_t); [[noreturn]] void set_current_thread_done(); + BAN::RefPtr current_thread(); + private: Scheduler() = default; - BAN::RefPtr current_thread(); - void wake_threads(); [[nodiscard]] bool save_current_thread(); void remove_and_advance_current_thread(); diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index dd4399bcf..a2eebc09d 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -3,19 +3,23 @@ #include #include +#include + namespace Kernel { + class Process; + class Thread : public BAN::RefCounted { public: using entry_t = void(*)(void*); public: - static BAN::ErrorOr> create(entry_t, void* = nullptr); + static BAN::ErrorOr> create(entry_t, void* = nullptr, BAN::RefPtr = nullptr); ~Thread(); - uint32_t tid() const { return m_tid; } + pid_t tid() const { return m_tid; } void set_rsp(uintptr_t rsp) { m_rsp = rsp; } void set_rip(uintptr_t rip) { m_rip = rip; } @@ -25,19 +29,24 @@ namespace Kernel void set_started() { m_started = true; } bool started() const { return m_started; } + static BAN::RefPtr current() ; + BAN::RefPtr process(); + private: - Thread(); + Thread(pid_t tid, BAN::RefPtr); + BAN::ErrorOr initialize(entry_t, void*); void on_exit(); private: - void* m_stack_base = nullptr; - uintptr_t m_rip = 0; - uintptr_t m_rsp = 0; - const uint32_t m_tid = 0; - bool m_started = false; + void* m_stack_base = nullptr; + uintptr_t m_rip = 0; + uintptr_t m_rsp = 0; + const pid_t m_tid = 0; + bool m_started = false; + BAN::RefPtr m_process; friend class BAN::RefPtr; }; - + } \ No newline at end of file diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp new file mode 100644 index 000000000..ce540232c --- /dev/null +++ b/kernel/kernel/Process.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +namespace Kernel +{ + + BAN::ErrorOr> Process::create_kernel(entry_t entry, void* data) + { + static pid_t next_pid = 1; + auto process = TRY(BAN::RefPtr::create(next_pid++)); + TRY(process->add_thread(entry, data)); + TRY(process->m_working_directory.append("/"sv)); + return process; + } + + BAN::ErrorOr Process::add_thread(entry_t entry, void* data) + { + auto thread = TRY(Thread::create(entry, data, this)); + TRY(m_threads.push_back(thread)); + if (auto res = Scheduler::get().add_thread(thread); res.is_error()) + { + m_threads.pop_back(); + return res; + } + + dprintln("add thread {} to process {}", thread->tid(), pid()); + + return {}; + } + + void Process::on_thread_exit(Thread& thread) + { + dprintln("thread {} exited from process", thread.tid(), pid()); + } + +} \ No newline at end of file diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index df9fd4c3a..522b9b5af 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #if 1 diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 4ab52a10d..69005d2f8 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include #include #include @@ -202,7 +202,7 @@ argument_done: SpinLock spinlock; thread_data_t thread_data = { this, spinlock, arguments }; spinlock.lock(); - TRY(Scheduler::get().add_thread(TRY(Thread::create(function, &thread_data)))); + TRY(Process::current()->add_thread(function, &thread_data)); while (spinlock.is_locked()); } else if (arguments.front() == "memory") diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 55a73c003..2107a6c01 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -1,7 +1,7 @@ #include -#include #include #include +#include #include #include @@ -10,8 +10,6 @@ namespace Kernel { - static uint32_t s_next_tid = 0; - static constexpr size_t thread_stack_size = 16384; template @@ -21,17 +19,28 @@ namespace Kernel memcpy((void*)rsp, (void*)&value, size); } - BAN::ErrorOr> Thread::create(entry_t entry, void* data) + BAN::ErrorOr> Thread::create(entry_t entry, void* data, BAN::RefPtr process) { - auto thread = TRY(BAN::RefPtr::create()); + static pid_t next_tid = 1; + auto thread = TRY(BAN::RefPtr::create(next_tid++, process)); TRY(thread->initialize(entry, data)); return thread; } - Thread::Thread() - : m_tid(s_next_tid++) + Thread::Thread(pid_t tid, BAN::RefPtr process) + : m_tid(tid), m_process(process) {} + BAN::RefPtr Thread::current() + { + return Scheduler::get().current_thread(); + } + + BAN::RefPtr Thread::process() + { + return m_process; + } + BAN::ErrorOr Thread::initialize(entry_t entry, void* data) { m_stack_base = kmalloc(thread_stack_size, PAGE_SIZE); @@ -54,6 +63,8 @@ namespace Kernel void Thread::on_exit() { + if (m_process) + m_process->on_thread_exit(*this); Scheduler::get().set_current_thread_done(); ASSERT_NOT_REACHED(); } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 3c5cfdf34..499afdc2e 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,8 @@ extern "C" uintptr_t g_userspace_end; extern void userspace_entry(); +void init2(void*); + extern "C" void kernel_main() { using namespace Kernel; @@ -121,6 +124,7 @@ extern "C" void kernel_main() ASSERT(terminal_driver); dprintln("VESA initialized"); TTY* tty1 = new TTY(terminal_driver); + ASSERT(tty1); InterruptController::initialize(cmdline.force_pic); dprintln("Interrupt controller initialized"); @@ -134,7 +138,7 @@ extern "C" void kernel_main() MUST(Scheduler::initialize()); Scheduler& scheduler = Scheduler::get(); -#if 1 +#if 0 MUST(scheduler.add_thread(MUST(Thread::create( [] (void*) { @@ -178,27 +182,32 @@ extern "C" void kernel_main() } )))); #else - MUST(scheduler.add_thread(MUST(Thread::create( - [](void* terminal_driver) - { - MUST(VirtualFileSystem::initialize()); - - auto font_or_error = Font::load("/usr/share/fonts/zap-ext-vga16.psf"); - if (font_or_error.is_error()) - dprintln("{}", font_or_error.error()); - else - ((TerminalDriver*)terminal_driver)->set_font(font_or_error.release_value()); - }, terminal_driver - )))); - MUST(scheduler.add_thread(MUST(Thread::create( - [](void* tty) - { - Shell* shell = new Shell((TTY*)tty); - ASSERT(shell); - shell->run(); - }, tty1 - )))); + MUST(scheduler.add_thread(MUST(Thread::create(init2, tty1, nullptr)))); #endif scheduler.start(); ASSERT(false); +} + +void init2(void* tty1_ptr) +{ + using namespace Kernel; + + TTY* tty1 = (TTY*)tty1_ptr; + + MUST(VirtualFileSystem::initialize()); + + auto font_or_error = Font::load("/usr/share/fonts/zap-ext-vga16.psf"); + if (font_or_error.is_error()) + dprintln("{}", font_or_error.error()); + else + tty1->set_font(font_or_error.release_value()); + + MUST(Process::create_kernel( + [](void* tty1) + { + Shell* shell = new Shell((TTY*)tty1); + ASSERT(shell); + shell->run(); + }, tty1 + )); } \ No newline at end of file diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h new file mode 100644 index 000000000..be9970ba0 --- /dev/null +++ b/libc/include/sys/types.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +__BEGIN_DECLS + +typedef int32_t pid_t; + +__END_DECLS \ No newline at end of file