From 6986f534f8135d8b068debe50036e1745d2241dd Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Mon, 12 Jun 2023 20:56:25 -0700 Subject: [PATCH] Add a method for blocking threads on ports. Additionally add the first lock class since we are becoming more concurrent. --- sys/denali/ahci/ahci_device.cpp | 1 + sys/denali/ahci/ahci_driver.cpp | 3 --- zion/CMakeLists.txt | 1 + zion/debug/debug.cpp | 4 ++-- zion/lib/mutex.cpp | 11 +++++++++++ zion/lib/mutex.h | 29 +++++++++++++++++++++++++++++ zion/object/port.cpp | 18 +++++++++++++++--- zion/object/port.h | 6 ++++++ zion/object/process.cpp | 13 +++++++++++++ zion/object/process.h | 4 ++++ zion/object/thread.cpp | 2 +- zion/scheduler/scheduler.h | 2 +- zion/syscall/syscall.cpp | 8 ++++---- 13 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 zion/lib/mutex.cpp create mode 100644 zion/lib/mutex.h diff --git a/sys/denali/ahci/ahci_device.cpp b/sys/denali/ahci/ahci_device.cpp index d39e695..6b0a2b7 100644 --- a/sys/denali/ahci/ahci_device.cpp +++ b/sys/denali/ahci/ahci_device.cpp @@ -31,6 +31,7 @@ AhciDevice::AhciDevice(AhciPort* port) : port_struct_(port) { command_list_->command_headers[0].command_table_base_addr & 0xFFF; command_table_ = reinterpret_cast(vaddr + ct_off); + port_struct_->interrupt_status = 0; port_struct_->interrupt_enable = 0xFFFFFFFF; } diff --git a/sys/denali/ahci/ahci_driver.cpp b/sys/denali/ahci/ahci_driver.cpp index 1cebb0e..96f7f9a 100644 --- a/sys/denali/ahci/ahci_driver.cpp +++ b/sys/denali/ahci/ahci_driver.cpp @@ -13,7 +13,6 @@ const uint64_t kGhc_InteruptEnable = 0x2; void interrupt_thread(void* void_driver) { AhciDriver* driver = static_cast(void_driver); - dbgln("this %lx", driver); driver->InterruptLoop(); @@ -132,7 +131,6 @@ void AhciDriver::DumpPorts() { } void AhciDriver::InterruptLoop() { - dbgln("this %lx", this); while (true) { uint64_t type, bytes, caps; check(ZPortRecv(irq_port_cap_, 0, 0, 0, 0, &type, &bytes, &caps)); @@ -189,7 +187,6 @@ z_err_t AhciDriver::RegisterIrq() { } uint64_t irq_num = Z_IRQ_PCI_BASE + pci_device_header_->interrupt_pin - 1; RET_ERR(ZIrqRegister(irq_num, &irq_port_cap_)); - dbgln("this %lx", this); irq_thread_ = Thread(interrupt_thread, this); return Z_OK; } diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index f81685d..5fad7bf 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(zion interrupt/interrupt.cpp interrupt/interrupt_enter.s interrupt/timer.cpp + lib/mutex.cpp loader/init_loader.cpp memory/kernel_heap.cpp memory/kernel_stack_manager.cpp diff --git a/zion/debug/debug.cpp b/zion/debug/debug.cpp index f81dc73..44188fa 100644 --- a/zion/debug/debug.cpp +++ b/zion/debug/debug.cpp @@ -76,8 +76,8 @@ void MemToStr(uint64_t u, char* str) { void AddProcPrefix() { if (gScheduler != nullptr) { - auto& t = gScheduler->CurrentThread(); - dbg("[%u.%u] ", t.pid(), t.tid()); + auto t = gScheduler->CurrentThread(); + dbg("[%u.%u] ", t->pid(), t->tid()); } } diff --git a/zion/lib/mutex.cpp b/zion/lib/mutex.cpp new file mode 100644 index 0000000..3cfd323 --- /dev/null +++ b/zion/lib/mutex.cpp @@ -0,0 +1,11 @@ +#include "lib/mutex.h" + +#include "debug/debug.h" +#include "scheduler/scheduler.h" + +void Mutex::Lock() { + while (__atomic_fetch_or(&lock_, 0x1, __ATOMIC_SEQ_CST) == 0x1) { + dbgln("Lock sleep: %s", name_); + gScheduler->Preempt(); + } +} diff --git a/zion/lib/mutex.h b/zion/lib/mutex.h new file mode 100644 index 0000000..a3a4ea3 --- /dev/null +++ b/zion/lib/mutex.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +class Mutex { + public: + Mutex(const char* name) : name_(name) {} + + void Lock(); + void Unlock() { lock_ = false; } + + private: + const char* name_; + + uint8_t lock_ = 0; +}; + +class MutexHolder { + public: + MutexHolder(Mutex& mutex) : mutex_(mutex) { mutex_.Lock(); } + + ~MutexHolder() { mutex_.Unlock(); } + + MutexHolder(MutexHolder&) = delete; + MutexHolder(MutexHolder&&) = delete; + + private: + Mutex& mutex_; +}; diff --git a/zion/object/port.cpp b/zion/object/port.cpp index a733c9d..52e0cf1 100644 --- a/zion/object/port.cpp +++ b/zion/object/port.cpp @@ -1,5 +1,7 @@ #include "object/port.h" +#include "scheduler/scheduler.h" + Port::Port() {} z_err_t Port::Write(const ZMessage& msg) { @@ -21,16 +23,26 @@ z_err_t Port::Write(const ZMessage& msg) { for (uint64_t i = 0; i < msg.num_bytes; i++) { message.bytes[i] = msg.bytes[i]; } + + MutexHolder lock(mutex_); pending_messages_.PushBack(message); + if (blocked_threads_.size() > 0) { + gScheduler->Enqueue(blocked_threads_.PopFront()); + } return Z_OK; } z_err_t Port::Read(ZMessage& msg) { - if (pending_messages_.size() < 1) { - dbgln("Implement blocking"); - return Z_ERR_UNIMPLEMENTED; + mutex_.Lock(); + while (pending_messages_.size() < 1) { + blocked_threads_.PushBack(gScheduler->CurrentThread()); + mutex_.Unlock(); + gScheduler->Yield(); + mutex_.Lock(); } + mutex_.Unlock(); + MutexHolder lock(mutex_); Message next_msg = pending_messages_.PeekFront(); if (next_msg.num_bytes > msg.num_bytes) { return Z_ERR_BUFF_SIZE; diff --git a/zion/object/port.h b/zion/object/port.h index ed0d9c7..9e948b8 100644 --- a/zion/object/port.h +++ b/zion/object/port.h @@ -1,7 +1,9 @@ #pragma once #include "lib/linked_list.h" +#include "lib/mutex.h" #include "object/kernel_object.h" +#include "object/thread.h" #include "usr/zcall_internal.h" class Port : public KernelObject { @@ -19,4 +21,8 @@ class Port : public KernelObject { }; LinkedList pending_messages_; + + LinkedList> blocked_threads_; + + Mutex mutex_{"Port"}; }; diff --git a/zion/object/process.cpp b/zion/object/process.cpp index 751f546..6218856 100644 --- a/zion/object/process.cpp +++ b/zion/object/process.cpp @@ -34,12 +34,14 @@ Process::Process() : id_(gNextId++), vmas_(MakeRefCounted()), state_(RUNNING) {} RefPtr Process::CreateThread() { + MutexHolder lock(mutex_); RefPtr thread = MakeRefCounted(*this, next_thread_id_++); threads_.PushBack(thread); return thread; } RefPtr Process::GetThread(uint64_t tid) { + MutexHolder lock(mutex_); auto iter = threads_.begin(); while (iter != threads_.end()) { if (iter->tid() == tid) { @@ -52,6 +54,7 @@ RefPtr Process::GetThread(uint64_t tid) { } void Process::CheckState() { + MutexHolder lock(mutex_); auto iter = threads_.begin(); while (iter != threads_.end()) { if (iter->GetState() != Thread::FINISHED) { @@ -63,6 +66,7 @@ void Process::CheckState() { } RefPtr Process::ReleaseCapability(uint64_t cid) { + MutexHolder lock(mutex_); auto iter = caps_.begin(); while (iter != caps_.end()) { if (*iter && iter->id() == cid) { @@ -78,6 +82,7 @@ RefPtr Process::ReleaseCapability(uint64_t cid) { } RefPtr Process::GetCapability(uint64_t cid) { + MutexHolder lock(mutex_); auto iter = caps_.begin(); while (iter != caps_.end()) { if (*iter && iter->id() == cid) { @@ -91,11 +96,13 @@ RefPtr Process::GetCapability(uint64_t cid) { } uint64_t Process::AddCapability(const RefPtr& cap) { + MutexHolder lock(mutex_); cap->set_id(next_cap_id_++); caps_.PushBack(cap); return cap->id(); } uint64_t Process::AddCapability(const RefPtr& thread) { + MutexHolder lock(mutex_); uint64_t cap_id = next_cap_id_++; caps_.PushBack( MakeRefCounted(thread, Capability::THREAD, cap_id, ZC_WRITE)); @@ -103,24 +110,28 @@ uint64_t Process::AddCapability(const RefPtr& thread) { } uint64_t Process::AddCapability(const RefPtr& p) { + MutexHolder lock(mutex_); uint64_t cap_id = next_cap_id_++; caps_.PushBack(MakeRefCounted(p, Capability::PROCESS, cap_id, ZC_WRITE | ZC_PROC_SPAWN_THREAD)); return cap_id; } uint64_t Process::AddCapability(const RefPtr& vmas) { + MutexHolder lock(mutex_); uint64_t cap_id = next_cap_id_++; caps_.PushBack(MakeRefCounted(vmas, Capability::ADDRESS_SPACE, cap_id, ZC_WRITE)); return cap_id; } uint64_t Process::AddCapability(const RefPtr& vmmo) { + MutexHolder lock(mutex_); uint64_t cap_id = next_cap_id_++; caps_.PushBack(MakeRefCounted(vmmo, Capability::MEMORY_OBJECT, cap_id, ZC_WRITE)); return cap_id; } uint64_t Process::AddCapability(const RefPtr& chan) { + MutexHolder lock(mutex_); uint64_t cap_id = next_cap_id_++; caps_.PushBack(MakeRefCounted(chan, Capability::CHANNEL, cap_id, ZC_WRITE | ZC_READ)); @@ -128,6 +139,7 @@ uint64_t Process::AddCapability(const RefPtr& chan) { } uint64_t Process::AddCapability(const RefPtr& port) { + MutexHolder lock(mutex_); uint64_t cap_id = next_cap_id_++; caps_.PushBack(MakeRefCounted(port, Capability::PORT, cap_id, ZC_WRITE | ZC_READ)); @@ -135,6 +147,7 @@ uint64_t Process::AddCapability(const RefPtr& port) { } void Process::AddCapability(uint64_t cap_id, const RefPtr& vmmo) { + MutexHolder lock(mutex_); caps_.PushBack(MakeRefCounted(vmmo, Capability::MEMORY_OBJECT, cap_id, ZC_WRITE)); } diff --git a/zion/object/process.h b/zion/object/process.h index 301680b..f6ea681 100644 --- a/zion/object/process.h +++ b/zion/object/process.h @@ -4,6 +4,7 @@ #include "capability/capability.h" #include "lib/linked_list.h" +#include "lib/mutex.h" #include "lib/ref_ptr.h" #include "object/address_space.h" #include "object/channel.h" @@ -51,6 +52,9 @@ class Process : public KernelObject { friend class MakeRefCountedFriend; Process(); Process(uint64_t id) : id_(id), vmas_(AddressSpace::ForRoot()) {} + + Mutex mutex_{"Process"}; + uint64_t id_; RefPtr vmas_; State state_; diff --git a/zion/object/thread.cpp b/zion/object/thread.cpp index 74241fb..6930374 100644 --- a/zion/object/thread.cpp +++ b/zion/object/thread.cpp @@ -15,7 +15,7 @@ extern "C" void jump_user_space(uint64_t rip, uint64_t rsp, uint64_t arg1, extern "C" void thread_init() { asm("sti"); - gScheduler->CurrentThread().Init(); + gScheduler->CurrentThread()->Init(); panic("Reached end of thread."); } diff --git a/zion/scheduler/scheduler.h b/zion/scheduler/scheduler.h index 2502277..c522480 100644 --- a/zion/scheduler/scheduler.h +++ b/zion/scheduler/scheduler.h @@ -13,7 +13,7 @@ class Scheduler { void Enable() { enabled_ = true; } Process& CurrentProcess() { return current_thread_->process(); } - Thread& CurrentThread() { return *current_thread_; } + RefPtr CurrentThread() { return current_thread_; } void Enqueue(const RefPtr& thread) { runnable_threads_.PushBack(thread); diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 66e10a0..313095f 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -24,7 +24,7 @@ extern "C" void syscall_enter(); // Used by syscall_enter.s extern "C" uint64_t GetKernelRsp() { - return gScheduler->CurrentThread().Rsp0Start(); + return gScheduler->CurrentThread()->Rsp0Start(); } void InitSyscall() { @@ -210,12 +210,12 @@ z_err_t IrqRegister(ZIrqRegisterReq* req, ZIrqRegisterResp* resp) { } extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) { - Thread& thread = gScheduler->CurrentThread(); + RefPtr thread = gScheduler->CurrentThread(); switch (call_id) { case Z_PROCESS_EXIT: // FIXME: kill process here. dbgln("Exit code: %u", req); - thread.Exit(); + thread->Exit(); panic("Returned from thread exit"); break; case Z_PROCESS_SPAWN: @@ -227,7 +227,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) { case Z_THREAD_START: return ThreadStart(reinterpret_cast(req)); case Z_THREAD_EXIT: - thread.Exit(); + thread->Exit(); panic("Returned from thread exit"); break;