Skip to content

Commit 859d316

Browse files
Add locking to protect against multithreaded conformance test usage.
1 parent f667247 commit 859d316

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

src/loader/loader_core.cpp

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,12 @@
3232
#include <utility>
3333
#include <vector>
3434

35-
// Global lock to prevent reading JSON manifest files at the same time.
36-
std::mutex &GetLoaderJsonMutex() {
37-
static std::mutex loader_json_mutex;
38-
return loader_json_mutex;
39-
}
40-
41-
// Global lock to prevent simultaneous instance creation/destruction
42-
std::mutex &GetInstanceCreateDestroyMutex() {
43-
static std::mutex instance_create_destroy_mutex;
44-
return instance_create_destroy_mutex;
35+
// Global loader lock to:
36+
// 1. Ensure ActiveLoaderInstance get and set operations are done atomically.
37+
// 2. Ensure RuntimeInterface isn't used to unload the runtime while the runtime is in use.
38+
std::mutex &GetGlobalLoaderMutex() {
39+
static std::mutex loader_mutex;
40+
return loader_mutex;
4541
}
4642

4743
// Terminal functions needed by xrCreateInstance.
@@ -84,7 +80,7 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrEnumerateApiLayerProperties(uint32_t prop
8480
LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline");
8581

8682
// Make sure only one thread is attempting to read the JSON files at a time.
87-
std::unique_lock<std::mutex> json_lock(GetLoaderJsonMutex());
83+
std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
8884

8985
XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput,
9086
propertyCountOutput, properties);
@@ -117,8 +113,8 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrEnumerateInstanceExtensionProperties(cons
117113
XrResult result;
118114

119115
{
120-
// Make sure only one thread is attempting to read the JSON files at a time.
121-
std::unique_lock<std::mutex> json_lock(GetLoaderJsonMutex());
116+
// Make sure the runtime isn't unloaded while this call is in progress.
117+
std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
122118

123119
// Get the layer extension properties
124120
result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName,
@@ -231,7 +227,8 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrCreateInstance(const XrInstanceCreateInfo
231227
return XR_ERROR_VALIDATION_FAILURE;
232228
}
233229

234-
std::unique_lock<std::mutex> instance_lock(GetInstanceCreateDestroyMutex());
230+
// Make sure the ActiveLoaderInstance::IsAvailable check is done atomically with RuntimeInterface::LoadRuntime.
231+
std::unique_lock<std::mutex> instance_lock(GetGlobalLoaderMutex());
235232

236233
// Check if there is already an XrInstance that is alive. If so, another instance cannot be created.
237234
// The loader does not support multiple simultaneous instances because the loader is intended to be
@@ -248,7 +245,6 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrCreateInstance(const XrInstanceCreateInfo
248245

249246
// Make sure only one thread is attempting to read the JSON files and use the instance.
250247
{
251-
std::unique_lock<std::mutex> json_lock(GetLoaderJsonMutex());
252248
// Load the available runtime
253249
result = RuntimeInterface::LoadRuntime("xrCreateInstance");
254250
if (XR_FAILED(result)) {
@@ -318,7 +314,8 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrDestroyInstance(XrInstance instance) XRLO
318314
return XR_ERROR_HANDLE_INVALID;
319315
}
320316

321-
std::unique_lock<std::mutex> loader_instance_lock(GetInstanceCreateDestroyMutex());
317+
// Make sure the runtime isn't unloaded while it is being used by xrEnumerateInstanceExtensionProperties.
318+
std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
322319

323320
LoaderInstance *loader_instance;
324321
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyInstance");

src/loader/loader_logger.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,19 @@ LoaderLogger::LoaderLogger() {
136136
}
137137
}
138138

139-
void LoaderLogger::AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder) { _recorders.push_back(std::move(recorder)); }
139+
void LoaderLogger::AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder) {
140+
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
141+
_recorders.push_back(std::move(recorder));
142+
}
140143

141144
void LoaderLogger::AddLogRecorderForXrInstance(XrInstance instance, std::unique_ptr<LoaderLogRecorder>&& recorder) {
145+
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
142146
_recordersByInstance[instance].insert(recorder->UniqueId());
143147
_recorders.emplace_back(std::move(recorder));
144148
}
145149

146150
void LoaderLogger::RemoveLogRecorder(uint64_t unique_id) {
151+
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
147152
vector_remove_if_and_erase(
148153
_recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) { return recorder->UniqueId() == unique_id; });
149154
for (auto& recorders : _recordersByInstance) {
@@ -155,6 +160,7 @@ void LoaderLogger::RemoveLogRecorder(uint64_t unique_id) {
155160
}
156161

157162
void LoaderLogger::RemoveLogRecordersForXrInstance(XrInstance instance) {
163+
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
158164
if (_recordersByInstance.find(instance) != _recordersByInstance.end()) {
159165
auto recorders = _recordersByInstance[instance];
160166
vector_remove_if_and_erase(_recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) {
@@ -179,6 +185,7 @@ bool LoaderLogger::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severit
179185
callback_data.session_labels = names_and_labels.labels.empty() ? nullptr : names_and_labels.labels.data();
180186
callback_data.session_labels_count = static_cast<uint8_t>(names_and_labels.labels.size());
181187

188+
std::shared_lock<std::shared_timed_mutex> lock(_mutex);
182189
bool exit_app = false;
183190
for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
184191
if ((recorder->MessageSeverities() & message_severity) == message_severity &&
@@ -201,6 +208,7 @@ bool LoaderLogger::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT mess
201208
data_.WrapCallbackData(&augmented_data, callback_data);
202209

203210
// Loop through the recorders
211+
std::shared_lock<std::shared_timed_mutex> lock(_mutex);
204212
for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
205213
// Only send the message if it's a debug utils recorder and of the type the recorder cares about.
206214
if (recorder->Type() != XR_LOADER_LOG_DEBUG_UTILS ||

src/loader/loader_logger.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <vector>
1818
#include <set>
1919
#include <map>
20+
#include <shared_mutex>
2021

2122
#include <openxr/openxr.h>
2223

@@ -173,6 +174,8 @@ class LoaderLogger {
173174
private:
174175
LoaderLogger();
175176

177+
std::shared_timed_mutex _mutex;
178+
176179
// List of *all* available recorder objects (including created specifically for an Instance)
177180
std::vector<std::unique_ptr<LoaderLogRecorder>> _recorders;
178181

0 commit comments

Comments
 (0)