From e6ea0eae656c022d7878ffabc4e016b3e6f0c536 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Wed, 19 Dec 2018 19:33:36 -0500 Subject: [PATCH] Protect potential multithreaded code path with mutex Note that the semaphore part is going to change again, so this is a temporary solution --- src/apbp.cpp | 8 ++++++++ src/icu.h | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/apbp.cpp b/src/apbp.cpp index 379b2fc..173b262 100644 --- a/src/apbp.cpp +++ b/src/apbp.cpp @@ -49,6 +49,7 @@ class Apbp::Impl { u16 semaphore = 0; u16 semaphore_mask = 0; bool semaphore_master_signal = false; + mutable std::recursive_mutex semaphore_mutex; std::function semaphore_handler; void Reset() { @@ -88,6 +89,7 @@ void Apbp::SetDataHandler(unsigned channel, std::function handler) { } void Apbp::SetSemaphore(u16 bits) { + std::lock_guard lock(impl->semaphore_mutex); impl->semaphore |= bits; bool new_signal = (impl->semaphore & ~impl->semaphore_mask) != 0; if (new_signal && impl->semaphore_handler) { @@ -97,27 +99,33 @@ void Apbp::SetSemaphore(u16 bits) { } void Apbp::ClearSemaphore(u16 bits) { + std::lock_guard lock(impl->semaphore_mutex); impl->semaphore &= ~bits; impl->semaphore_master_signal = (impl->semaphore & ~impl->semaphore_mask) != 0; } u16 Apbp::GetSemaphore() const { + std::lock_guard lock(impl->semaphore_mutex); return impl->semaphore; } void Apbp::MaskSemaphore(u16 bits) { + std::lock_guard lock(impl->semaphore_mutex); impl->semaphore_mask = bits; } u16 Apbp::GetSemaphoreMask() const { + std::lock_guard lock(impl->semaphore_mutex); return impl->semaphore_mask; } void Apbp::SetSemaphoreHandler(std::function handler) { + std::lock_guard lock(impl->semaphore_mutex); impl->semaphore_handler = std::move(handler); } bool Apbp::IsSemaphoreSignaled() const { + std::lock_guard lock(impl->semaphore_mutex); return impl->semaphore_master_signal; } } // namespace Teakra diff --git a/src/icu.h b/src/icu.h index 2a3563e..c764582 100644 --- a/src/icu.h +++ b/src/icu.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "common_types.h" @@ -12,15 +13,18 @@ class ICU { public: using IrqBits = std::bitset<16>; u16 GetRequest() const { + std::lock_guard lock(mutex); return (u16)request.to_ulong(); } void Acknowledge(u16 irq_bits) { + std::lock_guard lock(mutex); request &= ~IrqBits(irq_bits); } u16 GetAcknowledge() { return 0; } void Trigger(u16 irq_bits) { + std::lock_guard lock(mutex); IrqBits bits(irq_bits); request |= bits; for (u32 irq = 0; irq < 16; ++irq) { @@ -43,15 +47,19 @@ class ICU { Trigger(1 << irq); } void SetEnable(u32 interrupt_index, u16 irq_bits) { + std::lock_guard lock(mutex); enabled[interrupt_index] = IrqBits(irq_bits); } void SetEnableVectored(u16 irq_bits) { + std::lock_guard lock(mutex); vectored_enabled = IrqBits(irq_bits); } u16 GetEnable(u32 interrupt_index) const { + std::lock_guard lock(mutex); return (u16)enabled[interrupt_index].to_ulong(); } u16 GetEnableVectored() const { + std::lock_guard lock(mutex); return (u16)vectored_enabled.to_ulong(); } @@ -74,6 +82,7 @@ class ICU { IrqBits request; std::array enabled; IrqBits vectored_enabled; + mutable std::mutex mutex; }; } // namespace Teakra