diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 0a74a380..b483023e 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -61,7 +61,7 @@ namespace Kernel BAN::Vector m_open_files; - mutable SpinLock m_lock; + mutable RecursiveSpinLock m_lock; pid_t m_pid = 0; BAN::String m_working_directory; diff --git a/kernel/include/kernel/SpinLock.h b/kernel/include/kernel/SpinLock.h index ebf79df9..d3d2471a 100644 --- a/kernel/include/kernel/SpinLock.h +++ b/kernel/include/kernel/SpinLock.h @@ -2,6 +2,8 @@ #include +#include + namespace Kernel { @@ -20,4 +22,21 @@ namespace Kernel int m_lock = 0; }; + class RecursiveSpinLock + { + BAN_NON_COPYABLE(RecursiveSpinLock); + BAN_NON_MOVABLE(RecursiveSpinLock); + + public: + RecursiveSpinLock() = default; + void lock(); + void unlock(); + bool is_locked() const; + + private: + pid_t m_locker = 0; + uint32_t m_lock_depth = 0; + SpinLock m_lock; + }; + } \ No newline at end of file diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 8b3e6fc7..4649aa44 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -20,6 +20,8 @@ namespace Kernel BAN::ErrorOr Process::add_thread(entry_t entry, void* data) { + LockGuard _(m_lock); + 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()) @@ -33,6 +35,7 @@ namespace Kernel void Process::on_thread_exit(Thread& thread) { + LockGuard _(m_lock); (void)thread; } @@ -118,6 +121,8 @@ namespace Kernel BAN::ErrorOr Process::absolute_path_of(BAN::StringView path) const { + LockGuard _(m_lock); + if (path.empty()) return m_working_directory; BAN::String absolute_path; @@ -142,6 +147,8 @@ namespace Kernel BAN::ErrorOr Process::validate_fd(int fd) { + LockGuard _(m_lock); + if (fd < 0 || m_open_files.size() <= (size_t)fd || !m_open_files[fd].inode) return BAN::Error::from_errno(EBADF); return {}; @@ -149,12 +156,16 @@ namespace Kernel Process::OpenFileDescription& Process::open_file_description(int fd) { + LockGuard _(m_lock); + MUST(validate_fd(fd)); return m_open_files[fd]; } BAN::ErrorOr Process::get_free_fd() { + LockGuard _(m_lock); + for (size_t fd = 0; fd < m_open_files.size(); fd++) if (!m_open_files[fd].inode) return fd; diff --git a/kernel/kernel/SpinLock.cpp b/kernel/kernel/SpinLock.cpp index 5f32ce2d..9ddffa98 100644 --- a/kernel/kernel/SpinLock.cpp +++ b/kernel/kernel/SpinLock.cpp @@ -1,4 +1,5 @@ #include +#include namespace Kernel { @@ -21,4 +22,35 @@ namespace Kernel return m_lock; } + void RecursiveSpinLock::lock() + { + // FIXME: is this thread safe? + if (m_locker == Thread::current()->tid()) + { + m_lock_depth++; + } + else + { + m_lock.lock(); + ASSERT(m_locker == 0); + m_locker = Thread::current()->tid(); + m_lock_depth = 1; + } + } + + void RecursiveSpinLock::unlock() + { + m_lock_depth--; + if (m_lock_depth == 0) + { + m_locker = 0; + m_lock.unlock(); + } + } + + bool RecursiveSpinLock::is_locked() const + { + return m_lock.is_locked(); + } + } \ No newline at end of file