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