Use Thread Safety Analysis annotations throughout SwiftShader. Switch from std::mutex and std::unique_lock to marl::mutex and marl::lock. The marl versions are TSA-friendly replacements, and do not involve the marl scheduler. Bug: b/153194656 Change-Id: Ief3758fb0d52b8fcdaa4208d2c25ad04c2d40108 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43436 Reviewed-by: Nicolas Capens <nicolascapens@google.com> Tested-by: Ben Clayton <bclayton@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt index e5ce24f..792ac8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -582,6 +582,10 @@ add_subdirectory(${THIRD_PARTY_DIR}/marl) endif() +if(MARL_THREAD_SAFETY_ANALYSIS_SUPPORTED) + list(APPEND SWIFTSHADER_COMPILE_OPTIONS "-Wthread-safety") +endif() + ########################################################### # cppdap ###########################################################
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp index ccdfc91..a7d1256 100644 --- a/src/Device/Blitter.cpp +++ b/src/Device/Blitter.cpp
@@ -1683,7 +1683,7 @@ Blitter::BlitRoutineType Blitter::getBlitRoutine(const State &state) { - std::unique_lock<std::mutex> lock(blitMutex); + marl::lock lock(blitMutex); auto blitRoutine = blitCache.lookup(state); if(!blitRoutine) @@ -1697,7 +1697,7 @@ Blitter::CornerUpdateRoutineType Blitter::getCornerUpdateRoutine(const State &state) { - std::unique_lock<std::mutex> lock(cornerUpdateMutex); + marl::lock lock(cornerUpdateMutex); auto cornerUpdateRoutine = cornerUpdateCache.lookup(state); if(!cornerUpdateRoutine)
diff --git a/src/Device/Blitter.hpp b/src/Device/Blitter.hpp index 8735feb..c7687d2 100644 --- a/src/Device/Blitter.hpp +++ b/src/Device/Blitter.hpp
@@ -20,8 +20,10 @@ #include "Reactor/Reactor.hpp" #include "Vulkan/VkFormat.h" +#include "marl/mutex.h" +#include "marl/tsa.h" + #include <cstring> -#include <mutex> namespace vk { @@ -186,10 +188,11 @@ const VkImageSubresourceLayers &dstSubresourceLayers, Edge dstEdge, const VkImageSubresourceLayers &srcSubresourceLayers, Edge srcEdge); - std::mutex blitMutex; - RoutineCache<State, BlitFunction::CFunctionType> blitCache; // guarded by blitMutex - std::mutex cornerUpdateMutex; - RoutineCache<State, CornerUpdateFunction::CFunctionType> cornerUpdateCache; // guarded by cornerUpdateMutex + marl::mutex blitMutex; + RoutineCache<State, BlitFunction::CFunctionType> blitCache GUARDED_BY(blitMutex); + + marl::mutex cornerUpdateMutex; + RoutineCache<State, CornerUpdateFunction::CFunctionType> cornerUpdateCache GUARDED_BY(cornerUpdateMutex); }; } // namespace sw
diff --git a/src/System/Synchronization.hpp b/src/System/Synchronization.hpp index 0a5068d..81794ab 100644 --- a/src/System/Synchronization.hpp +++ b/src/System/Synchronization.hpp
@@ -25,9 +25,10 @@ #include <assert.h> #include <chrono> #include <condition_variable> -#include <mutex> #include <queue> +#include "marl/mutex.h" + namespace sw { // TaskEvents is an interface for notifying when tasks begin and end. @@ -64,7 +65,7 @@ // add() begins a new task. void add() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); ++count_; } @@ -73,7 +74,7 @@ // WaitGroup. bool done() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); assert(count_ > 0); --count_; if(count_ == 0) @@ -86,8 +87,8 @@ // wait() blocks until all the tasks have been finished. void wait() { - std::unique_lock<std::mutex> lock(mutex); - condition.wait(lock, [this] { return count_ == 0; }); + marl::lock lock(mutex); + lock.wait(condition, [this]() REQUIRES(mutex) { return count_ == 0; }); } // wait() blocks until all the tasks have been finished or the timeout @@ -96,8 +97,8 @@ template<class CLOCK, class DURATION> bool wait(const std::chrono::time_point<CLOCK, DURATION> &timeout) { - std::unique_lock<std::mutex> lock(mutex); - return condition.wait_until(lock, timeout, [this] { return count_ == 0; }); + marl::lock lock(mutex); + return condition.wait_until(lock, timeout, [this]() REQUIRES(mutex) { return count_ == 0; }); } // count() returns the number of times add() has been called without a call @@ -106,7 +107,7 @@ // change after returning. int32_t count() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); return count_; } @@ -115,8 +116,8 @@ void finish() override { done(); } private: - int32_t count_ = 0; // guarded by mutex - std::mutex mutex; + marl::mutex mutex; + int32_t count_ GUARDED_BY(mutex) = 0; std::condition_variable condition; }; @@ -147,8 +148,8 @@ size_t count(); private: - std::queue<T> queue; - std::mutex mutex; + marl::mutex mutex; + std::queue<T> queue GUARDED_BY(mutex); std::condition_variable added; }; @@ -159,9 +160,9 @@ template<typename T> T Chan<T>::take() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); // Wait for item to be added. - added.wait(lock, [this] { return queue.size() > 0; }); + lock.wait(added, [this]() REQUIRES(mutex) { return queue.size() > 0; }); T out = queue.front(); queue.pop(); return out; @@ -170,7 +171,7 @@ template<typename T> std::pair<T, bool> Chan<T>::tryTake() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); if(queue.size() == 0) { return std::make_pair(T{}, false); @@ -183,7 +184,7 @@ template<typename T> void Chan<T>::put(const T &item) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); queue.push(item); added.notify_one(); } @@ -191,7 +192,7 @@ template<typename T> size_t Chan<T>::count() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); return queue.size(); }
diff --git a/src/Vulkan/Debug/Context.cpp b/src/Vulkan/Debug/Context.cpp index 1f51617..f79d345 100644 --- a/src/Vulkan/Debug/Context.cpp +++ b/src/Vulkan/Debug/Context.cpp
@@ -130,7 +130,6 @@ Broadcaster broadcaster; std::mutex mutex; - std::vector<EventListener *> eventListeners; std::unordered_map<std::thread::id, std::shared_ptr<Thread>> threadsByStdId; std::unordered_set<std::string> functionBreakpoints; std::unordered_map<std::string, std::vector<int>> pendingBreakpoints;
diff --git a/src/Vulkan/Debug/File.cpp b/src/Vulkan/Debug/File.cpp index 9a3094e..b14c0e5 100644 --- a/src/Vulkan/Debug/File.cpp +++ b/src/Vulkan/Debug/File.cpp
@@ -14,7 +14,8 @@ #include "File.hpp" -#include <mutex> +#include "marl/mutex.h" + #include <unordered_set> namespace { @@ -33,8 +34,8 @@ FileBase(ID id, std::string dir, std::string name, std::string source); private: - mutable std::mutex breakpointMutex; - std::unordered_set<int> breakpoints; // guarded by breakpointMutex + mutable marl::mutex breakpointMutex; + std::unordered_set<int> breakpoints GUARDED_BY(breakpointMutex); }; FileBase::FileBase(ID id, std::string dir, std::string name, std::string source) @@ -43,19 +44,19 @@ void FileBase::clearBreakpoints() { - std::unique_lock<std::mutex> lock(breakpointMutex); + marl::lock lock(breakpointMutex); breakpoints.clear(); } void FileBase::addBreakpoint(int line) { - std::unique_lock<std::mutex> lock(breakpointMutex); + marl::lock lock(breakpointMutex); breakpoints.emplace(line); } bool FileBase::hasBreakpoint(int line) const { - std::unique_lock<std::mutex> lock(breakpointMutex); + marl::lock lock(breakpointMutex); return breakpoints.count(line) > 0; }
diff --git a/src/Vulkan/Debug/Thread.cpp b/src/Vulkan/Debug/Thread.cpp index 753b7db..6b4fa96 100644 --- a/src/Vulkan/Debug/Thread.cpp +++ b/src/Vulkan/Debug/Thread.cpp
@@ -28,17 +28,17 @@ void Thread::setName(const std::string &name) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); name_ = name; } std::string Thread::name() const { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); return name_; } -void Thread::onLocationUpdate(std::unique_lock<std::mutex> &lock) +void Thread::onLocationUpdate(marl::lock &lock) { auto location = frames.back()->location; @@ -55,7 +55,7 @@ { case State::Paused: { - stateCV.wait(lock, [this] { return state_ != State::Paused; }); + lock.wait(stateCV, [this]() REQUIRES(mutex) { return state_ != State::Paused; }); break; } @@ -65,7 +65,7 @@ { broadcast->onThreadStepped(id); state_ = State::Paused; - stateCV.wait(lock, [this] { return state_ != State::Paused; }); + lock.wait(stateCV, [this]() REQUIRES(mutex) { return state_ != State::Paused; }); pauseAtFrame = 0; } break; @@ -81,7 +81,7 @@ auto frame = ctxlck.createFrame(file, function); auto isFunctionBreakpoint = ctxlck.isFunctionBreakpoint(function); - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); frames.push_back(frame); if(isFunctionBreakpoint) { @@ -92,13 +92,13 @@ void Thread::exit() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); frames.pop_back(); } void Thread::update(std::function<void(Frame &)> f) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); auto &frame = *frames.back(); auto oldLocation = frame.location; f(frame); @@ -110,13 +110,13 @@ Frame Thread::frame() const { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); return *frames.back(); } std::vector<Frame> Thread::stack() const { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); std::vector<Frame> out; out.reserve(frames.size()); for(auto frame : frames) @@ -128,27 +128,28 @@ Thread::State Thread::state() const { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); return state_; } void Thread::resume() { - std::unique_lock<std::mutex> lock(mutex); - state_ = State::Running; - lock.unlock(); + { + marl::lock lock(mutex); + state_ = State::Running; + } stateCV.notify_all(); } void Thread::pause() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); state_ = State::Paused; } void Thread::stepIn() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); state_ = State::Stepping; pauseAtFrame.reset(); stateCV.notify_all(); @@ -156,7 +157,7 @@ void Thread::stepOver() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); state_ = State::Stepping; pauseAtFrame = frames.back(); stateCV.notify_all(); @@ -164,7 +165,7 @@ void Thread::stepOut() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); state_ = State::Stepping; pauseAtFrame = (frames.size() > 1) ? frames[frames.size() - 1] : nullptr; stateCV.notify_all();
diff --git a/src/Vulkan/Debug/Thread.hpp b/src/Vulkan/Debug/Thread.hpp index a59f47f..4c719f2 100644 --- a/src/Vulkan/Debug/Thread.hpp +++ b/src/Vulkan/Debug/Thread.hpp
@@ -19,9 +19,11 @@ #include "ID.hpp" #include "Location.hpp" +#include "marl/mutex.h" +#include "marl/tsa.h" + #include <condition_variable> #include <memory> -#include <mutex> #include <string> #include <vector> @@ -173,14 +175,15 @@ private: EventListener *const broadcast; - void onLocationUpdate(std::unique_lock<std::mutex> &lock); + void onLocationUpdate(marl::lock &lock) REQUIRES(mutex); - mutable std::mutex mutex; - std::string name_; - std::vector<std::shared_ptr<Frame>> frames; + mutable marl::mutex mutex; + std::string name_ GUARDED_BY(mutex); + std::vector<std::shared_ptr<Frame>> frames GUARDED_BY(mutex); + State state_ GUARDED_BY(mutex) = State::Running; + std::shared_ptr<Frame> pauseAtFrame GUARDED_BY(mutex); + std::condition_variable stateCV; - State state_ = State::Running; - std::shared_ptr<Frame> pauseAtFrame; }; } // namespace dbg
diff --git a/src/Vulkan/Debug/Variable.hpp b/src/Vulkan/Debug/Variable.hpp index 4b76c7a..c916d75 100644 --- a/src/Vulkan/Debug/Variable.hpp +++ b/src/Vulkan/Debug/Variable.hpp
@@ -19,9 +19,11 @@ #include "Type.hpp" #include "Value.hpp" +#include "marl/mutex.h" +#include "marl/tsa.h" + #include <algorithm> #include <memory> -#include <mutex> #include <string> #include <unordered_map> #include <vector> @@ -81,10 +83,10 @@ inline std::shared_ptr<Type> type() const override; inline const void *get() const override; - mutable std::mutex mutex; - std::vector<Variable> variables; - std::unordered_map<std::string, int> indices; - std::vector<std::shared_ptr<VariableContainer>> extends; + mutable marl::mutex mutex; + std::vector<Variable> variables GUARDED_BY(mutex); + std::unordered_map<std::string, int> indices GUARDED_BY(mutex); + std::vector<std::shared_ptr<VariableContainer>> extends GUARDED_BY(mutex); }; VariableContainer::VariableContainer(ID id) @@ -101,7 +103,7 @@ template<typename F> void VariableContainer::foreach(ForeachIndex &index, const F &cb) const { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); for(size_t i = index.start; i < variables.size() && i < index.count; i++) { cb(variables[i]); @@ -119,7 +121,7 @@ template<typename F> bool VariableContainer::find(const std::string &name, const F &cb) const { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); for(auto const &var : variables) { if(var.name == name) @@ -140,7 +142,7 @@ void VariableContainer::put(const Variable &var) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); auto it = indices.find(var.name); if(it == indices.end()) { @@ -161,7 +163,7 @@ void VariableContainer::extend(const std::shared_ptr<VariableContainer> &base) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); extends.emplace_back(base); }
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp index 0961243..389348b 100644 --- a/src/Vulkan/VkDevice.cpp +++ b/src/Vulkan/VkDevice.cpp
@@ -40,7 +40,7 @@ void Device::SamplingRoutineCache::updateSnapshot() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); if(snapshotNeedsUpdate) { @@ -62,7 +62,7 @@ uint32_t Device::SamplerIndexer::index(const SamplerState &samplerState) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); auto it = map.find(samplerState); @@ -81,7 +81,7 @@ void Device::SamplerIndexer::remove(const SamplerState &samplerState) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); auto it = map.find(samplerState); ASSERT(it != map.end());
diff --git a/src/Vulkan/VkDevice.hpp b/src/Vulkan/VkDevice.hpp index abf1191..8d41499 100644 --- a/src/Vulkan/VkDevice.hpp +++ b/src/Vulkan/VkDevice.hpp
@@ -20,9 +20,11 @@ #include "Reactor/Routine.hpp" #include "System/LRUCache.hpp" +#include "marl/mutex.h" +#include "marl/tsa.h" + #include <map> #include <memory> -#include <mutex> #include <unordered_map> namespace marl { @@ -99,7 +101,7 @@ auto it = snapshot.find(key); if(it != snapshot.end()) { return it->second; } - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); if(auto existingRoutine = cache.lookup(key)) { return existingRoutine; @@ -118,8 +120,8 @@ bool snapshotNeedsUpdate = false; std::unordered_map<Key, std::shared_ptr<rr::Routine>, Key::Hash> snapshot; - sw::LRUCache<Key, std::shared_ptr<rr::Routine>, Key::Hash> cache; // guarded by mutex - std::mutex mutex; + marl::mutex mutex; + sw::LRUCache<Key, std::shared_ptr<rr::Routine>, Key::Hash> cache GUARDED_BY(mutex); }; SamplingRoutineCache *getSamplingRoutineCache() const; @@ -140,8 +142,8 @@ uint32_t count; // Number of samplers sharing this state identifier. }; - std::map<SamplerState, Identifier> map; // guarded by mutex - std::mutex mutex; + marl::mutex mutex; + std::map<SamplerState, Identifier> map GUARDED_BY(mutex); uint32_t nextID = 0; };
diff --git a/src/Vulkan/VkEvent.hpp b/src/Vulkan/VkEvent.hpp index 1ec9f26..9e33ba4 100644 --- a/src/Vulkan/VkEvent.hpp +++ b/src/Vulkan/VkEvent.hpp
@@ -16,8 +16,11 @@ #define VK_EVENT_HPP_ #include "VkObject.hpp" + +#include "marl/mutex.h" +#include "marl/tsa.h" + #include <condition_variable> -#include <mutex> namespace vk { @@ -35,35 +38,35 @@ void signal() { - std::unique_lock<std::mutex> lock(mutex); - status = VK_EVENT_SET; - lock.unlock(); + { + marl::lock lock(mutex); + status = VK_EVENT_SET; + } condition.notify_all(); } void reset() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); status = VK_EVENT_RESET; } VkResult getStatus() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); auto result = status; - lock.unlock(); return result; } void wait() { - std::unique_lock<std::mutex> lock(mutex); - condition.wait(lock, [this] { return status == VK_EVENT_SET; }); + marl::lock lock(mutex); + lock.wait(condition, [this]() REQUIRES(mutex) { return status == VK_EVENT_SET; }); } private: - VkResult status = VK_EVENT_RESET; // guarded by mutex - std::mutex mutex; + marl::mutex mutex; + VkResult status GUARDED_BY(mutex) = VK_EVENT_RESET; std::condition_variable condition; };
diff --git a/src/Vulkan/VkPipelineCache.cpp b/src/Vulkan/VkPipelineCache.cpp index 8c4c894..375334f 100644 --- a/src/Vulkan/VkPipelineCache.cpp +++ b/src/Vulkan/VkPipelineCache.cpp
@@ -136,14 +136,14 @@ PipelineCache *srcCache = Cast(pSrcCaches[i]); { - std::unique_lock<std::mutex> thisLock(spirvShadersMutex); - std::unique_lock<std::mutex> srcLock(srcCache->spirvShadersMutex); + marl::lock thisLock(spirvShadersMutex); + marl::lock srcLock(srcCache->spirvShadersMutex); spirvShaders.insert(srcCache->spirvShaders.begin(), srcCache->spirvShaders.end()); } { - std::unique_lock<std::mutex> thisLock(computeProgramsMutex); - std::unique_lock<std::mutex> srcLock(srcCache->computeProgramsMutex); + marl::lock thisLock(computeProgramsMutex); + marl::lock srcLock(srcCache->computeProgramsMutex); computePrograms.insert(srcCache->computePrograms.begin(), srcCache->computePrograms.end()); } }
diff --git a/src/Vulkan/VkPipelineCache.hpp b/src/Vulkan/VkPipelineCache.hpp index 5e89e60..83664b6 100644 --- a/src/Vulkan/VkPipelineCache.hpp +++ b/src/Vulkan/VkPipelineCache.hpp
@@ -18,11 +18,13 @@ #include "VkObject.hpp" #include "VkSpecializationInfo.hpp" +#include "marl/mutex.h" +#include "marl/tsa.h" + #include <cstring> #include <functional> #include <map> #include <memory> -#include <mutex> #include <string> #include <vector> @@ -127,11 +129,11 @@ size_t dataSize = 0; uint8_t *data = nullptr; - std::mutex spirvShadersMutex; - std::map<SpirvShaderKey, std::shared_ptr<sw::SpirvShader>> spirvShaders; // guarded by spirvShadersMutex + marl::mutex spirvShadersMutex; + std::map<SpirvShaderKey, std::shared_ptr<sw::SpirvShader>> spirvShaders GUARDED_BY(spirvShadersMutex); - std::mutex computeProgramsMutex; - std::map<ComputeProgramKey, std::shared_ptr<sw::ComputeProgram>> computePrograms; // guarded by computeProgramsMutex + marl::mutex computeProgramsMutex; + std::map<ComputeProgramKey, std::shared_ptr<sw::ComputeProgram>> computePrograms GUARDED_BY(computeProgramsMutex); }; static inline PipelineCache *Cast(VkPipelineCache object) @@ -142,7 +144,7 @@ template<typename Function> std::shared_ptr<sw::ComputeProgram> PipelineCache::getOrCreateComputeProgram(const PipelineCache::ComputeProgramKey &key, Function &&create) { - std::unique_lock<std::mutex> lock(computeProgramsMutex); + marl::lock lock(computeProgramsMutex); auto it = computePrograms.find(key); if(it != computePrograms.end()) { return it->second; } @@ -155,7 +157,7 @@ template<typename Function> std::shared_ptr<sw::SpirvShader> PipelineCache::getOrCreateShader(const PipelineCache::SpirvShaderKey &key, Function &&create) { - std::unique_lock<std::mutex> lock(spirvShadersMutex); + marl::lock lock(spirvShadersMutex); auto it = spirvShaders.find(key); if(it != spirvShaders.end()) { return it->second; }
diff --git a/src/Vulkan/VkSemaphore.cpp b/src/Vulkan/VkSemaphore.cpp index df9f72c..21a05f9 100644 --- a/src/Vulkan/VkSemaphore.cpp +++ b/src/Vulkan/VkSemaphore.cpp
@@ -130,7 +130,7 @@ void Semaphore::wait() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); External *ext = tempExternal ? tempExternal : external; if(ext) { @@ -141,11 +141,11 @@ // call, it is assumed that this is negligible // compared with the actual semaphore wait() // operation. - lock.unlock(); + lock.unlock_no_tsa(); marl::blocking_call([ext]() { ext->wait(); }); - lock.lock(); + lock.lock_no_tsa(); } // If the import was temporary, reset the semaphore to its previous state. @@ -164,7 +164,7 @@ void Semaphore::signal() { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); External *ext = tempExternal ? tempExternal : external; if(ext) { @@ -187,7 +187,7 @@ void Semaphore::destroy(const VkAllocationCallbacks *pAllocator) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); while(tempExternal) { External *ext = tempExternal; @@ -227,7 +227,7 @@ ALLOC_FUNC alloc_func, IMPORT_FUNC import_func) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); // Create new External instance if needed. External *ext = external; @@ -260,7 +260,7 @@ template<typename ALLOC_FUNC, typename EXPORT_FUNC> VkResult Semaphore::exportPayload(ALLOC_FUNC alloc_func, EXPORT_FUNC export_func) { - std::unique_lock<std::mutex> lock(mutex); + marl::lock lock(mutex); // Sanity check, do not try to export a semaphore that has a temporary import. if(tempExternal != nullptr) {
diff --git a/src/Vulkan/VkSemaphore.hpp b/src/Vulkan/VkSemaphore.hpp index b67d4d9..652389b 100644 --- a/src/Vulkan/VkSemaphore.hpp +++ b/src/Vulkan/VkSemaphore.hpp
@@ -19,7 +19,8 @@ #include "VkObject.hpp" #include "marl/event.h" -#include <mutex> +#include "marl/mutex.h" +#include "marl/tsa.h" #if VK_USE_PLATFORM_FUCHSIA # include <zircon/types.h> @@ -147,10 +148,10 @@ const VkAllocationCallbacks *allocator = nullptr; VkExternalSemaphoreHandleTypeFlags exportableHandleTypes = (VkExternalSemaphoreHandleTypeFlags)0; - std::mutex mutex; marl::Event internal; - External *external = nullptr; - External *tempExternal = nullptr; + marl::mutex mutex; + External *external GUARDED_BY(mutex) = nullptr; + External *tempExternal GUARDED_BY(mutex) = nullptr; }; static inline Semaphore *Cast(VkSemaphore object)
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index 07d2889..54273a6 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -71,8 +71,10 @@ #include "Reactor/Nucleus.hpp" +#include "marl/mutex.h" #include "marl/scheduler.h" #include "marl/thread.h" +#include "marl/tsa.h" #include "System/CPUID.hpp" @@ -133,21 +135,27 @@ std::shared_ptr<marl::Scheduler> getOrCreateScheduler() { - static std::mutex mutex; - static std::weak_ptr<marl::Scheduler> schedulerWeak; - std::unique_lock<std::mutex> lock(mutex); - auto scheduler = schedulerWeak.lock(); - if(!scheduler) + struct Scheduler { - scheduler = std::make_shared<marl::Scheduler>(); - scheduler->setThreadInitializer([] { + marl::mutex mutex; + std::weak_ptr<marl::Scheduler> weakptr GUARDED_BY(mutex); + }; + + static Scheduler scheduler; + + marl::lock lock(scheduler.mutex); + auto sptr = scheduler.weakptr.lock(); + if(!sptr) + { + sptr = std::make_shared<marl::Scheduler>(); + sptr->setThreadInitializer([] { sw::CPUID::setFlushToZero(true); sw::CPUID::setDenormalsAreZero(true); }); - scheduler->setWorkerThreadCount(std::min<size_t>(marl::Thread::numLogicalCPUs(), 16)); - schedulerWeak = scheduler; + sptr->setWorkerThreadCount(std::min<size_t>(marl::Thread::numLogicalCPUs(), 16)); + scheduler.weakptr = sptr; } - return scheduler; + return sptr; } // initializeLibrary() is called by vkCreateInstance() to perform one-off global