Fix TSan-reported race conditions

This commit is contained in:
Jack Andersen 2018-06-01 14:01:47 -10:00
parent fdddeebf52
commit 1a71ed813a
9 changed files with 45 additions and 40 deletions

View File

@ -70,6 +70,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
static void MIDIReceiveProc(snd_rawmidi_t* midi, const ReceiveFunctor& receiver) static void MIDIReceiveProc(snd_rawmidi_t* midi, const ReceiveFunctor& receiver)
{ {
logvisor::RegisterThreadName("Boo MIDI");
snd_rawmidi_status_t* midiStatus; snd_rawmidi_status_t* midiStatus;
snd_rawmidi_status_malloc(&midiStatus); snd_rawmidi_status_malloc(&midiStatus);
pthread_cleanup_push(MIDIFreeProc, midiStatus); pthread_cleanup_push(MIDIFreeProc, midiStatus);

View File

@ -1329,7 +1329,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
#if _WIN32 #if _WIN32
std::string thrName = WCSTMBS(APP->getFriendlyName().data()) + " GL Rendering Thread"; std::string thrName = WCSTMBS(APP->getFriendlyName().data()) + " GL Rendering Thread";
#else #else
std::string thrName = std::string(APP->getFriendlyName()) + " GL Rendering Thread"; std::string thrName = std::string(APP->getFriendlyName()) + " Render";
#endif #endif
logvisor::RegisterThreadName(thrName.c_str()); logvisor::RegisterThreadName(thrName.c_str());
GLDataFactoryImpl* dataFactory = static_cast<GLDataFactoryImpl*>(self->m_parent->getDataFactory()); GLDataFactoryImpl* dataFactory = static_cast<GLDataFactoryImpl*>(self->m_parent->getDataFactory());

View File

@ -1,6 +1,7 @@
#include "boo/inputdev/IHIDListener.hpp" #include "boo/inputdev/IHIDListener.hpp"
#include "boo/inputdev/DeviceFinder.hpp" #include "boo/inputdev/DeviceFinder.hpp"
#include "boo/inputdev/HIDParser.hpp" #include "boo/inputdev/HIDParser.hpp"
#include "logvisor/logvisor.hpp"
#include <libudev.h> #include <libudev.h>
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
@ -30,15 +31,14 @@ class HIDListenerUdev final : public IHIDListener
std::thread m_udevThread; std::thread m_udevThread;
bool m_scanningEnabled; bool m_scanningEnabled;
static void deviceConnected(HIDListenerUdev* listener, void deviceConnected(udev_device* device)
udev_device* device)
{ {
if (!listener->m_scanningEnabled) if (!m_scanningEnabled)
return; return;
/* Prevent redundant registration */ /* Prevent redundant registration */
const char* devPath = udev_device_get_syspath(device); const char* devPath = udev_device_get_syspath(device);
if (listener->m_finder._hasToken(devPath)) if (m_finder._hasToken(devPath))
return; return;
/* Filter to USB/BT */ /* Filter to USB/BT */
@ -140,21 +140,20 @@ class HIDListenerUdev final : public IHIDListener
fprintf(stderr, "\n\n"); fprintf(stderr, "\n\n");
#endif #endif
listener->m_finder._insertToken( m_finder._insertToken(std::make_unique<DeviceToken>(type, vid, pid, manuf, product, devPath));
std::make_unique<DeviceToken>(type, vid, pid, manuf, product, devPath));
} }
static void deviceDisconnected(HIDListenerUdev* listener, void deviceDisconnected(udev_device* device)
udev_device* device)
{ {
const char* devPath = udev_device_get_syspath(device); const char* devPath = udev_device_get_syspath(device);
listener->m_finder._removeToken(devPath); m_finder._removeToken(devPath);
} }
static void _udevProc(HIDListenerUdev* listener) void _udevProc()
{ {
udev_monitor_enable_receiving(listener->m_udevMon); logvisor::RegisterThreadName("Boo udev");
int fd = udev_monitor_get_fd(listener->m_udevMon); udev_monitor_enable_receiving(m_udevMon);
int fd = udev_monitor_get_fd(m_udevMon);
while (true) while (true)
{ {
fd_set fds; fd_set fds;
@ -168,14 +167,14 @@ class HIDListenerUdev final : public IHIDListener
} }
int oldtype; int oldtype;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype);
udev_device* dev = udev_monitor_receive_device(listener->m_udevMon); udev_device* dev = udev_monitor_receive_device(m_udevMon);
if (dev) if (dev)
{ {
const char* action = udev_device_get_action(dev); const char* action = udev_device_get_action(dev);
if (!strcmp(action, "add")) if (!strcmp(action, "add"))
deviceConnected(listener, dev); deviceConnected(dev);
else if (!strcmp(action, "remove")) else if (!strcmp(action, "remove"))
deviceDisconnected(listener, dev); deviceDisconnected(dev);
udev_device_unref(dev); udev_device_unref(dev);
} }
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldtype); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldtype);
@ -205,7 +204,7 @@ public:
m_scanningEnabled = false; m_scanningEnabled = false;
/* Start hotplug thread */ /* Start hotplug thread */
m_udevThread = std::thread(_udevProc, this); m_udevThread = std::thread(std::bind(&HIDListenerUdev::_udevProc, this), this);
} }
~HIDListenerUdev() ~HIDListenerUdev()
@ -243,7 +242,7 @@ public:
const char* devPath = udev_list_entry_get_name(uenumItem); const char* devPath = udev_list_entry_get_name(uenumItem);
udev_device* dev = udev_device_new_from_syspath(UDEV_INST, devPath); udev_device* dev = udev_device_new_from_syspath(UDEV_INST, devPath);
if (dev) if (dev)
deviceConnected(this, dev); deviceConnected(dev);
udev_device_unref(dev); udev_device_unref(dev);
} }
udev_enumerate_unref(uenum); udev_enumerate_unref(uenum);

View File

@ -441,10 +441,12 @@ public:
/* SetFullscreen call for OpenGL window */ /* SetFullscreen call for OpenGL window */
DoSetFullscreen(*reinterpret_cast<OGLContext::Window*>(msg.wParam), msg.lParam); DoSetFullscreen(*reinterpret_cast<OGLContext::Window*>(msg.wParam), msg.lParam);
continue; continue;
#if BOO_HAS_VULKAN
case WM_USER+6: case WM_USER+6:
/* SetFullscreen call for Vulkan window */ /* SetFullscreen call for Vulkan window */
DoSetFullscreen(*reinterpret_cast<boo::VulkanContext::Window*>(msg.wParam), msg.lParam); DoSetFullscreen(*reinterpret_cast<boo::VulkanContext::Window*>(msg.wParam), msg.lParam);
continue; continue;
#endif
default: break; default: break;
} }
} }

View File

@ -57,6 +57,7 @@ static inline void SetFullscreen(OGLContext::Window& win, bool fs)
g_nwcv.wait(lk); g_nwcv.wait(lk);
} }
#if BOO_HAS_VULKAN
static inline void SetFullscreen(boo::VulkanContext::Window& win, bool fs) static inline void SetFullscreen(boo::VulkanContext::Window& win, bool fs)
{ {
std::unique_lock<std::mutex> lk(g_nwmt); std::unique_lock<std::mutex> lk(g_nwmt);
@ -64,6 +65,7 @@ static inline void SetFullscreen(boo::VulkanContext::Window& win, bool fs)
g_nwcv.wait(lk); g_nwcv.wait(lk);
} }
#endif #endif
#endif
struct Boo3DAppContextWin32 : Boo3DAppContext struct Boo3DAppContextWin32 : Boo3DAppContext
{ {

View File

@ -64,7 +64,7 @@ int ApplicationRun(IApplication::EPlatformType platform,
bool deepColor, bool deepColor,
bool singleInstance) bool singleInstance)
{ {
std::string thrName = std::string(friendlyName) + " Main Thread"; std::string thrName = std::string(friendlyName) + " Main";
logvisor::RegisterThreadName(thrName.c_str()); logvisor::RegisterThreadName(thrName.c_str());
if (APP) if (APP)
return 1; return 1;

View File

@ -467,7 +467,7 @@ public:
std::unique_lock<std::mutex> innerLk(initmt); std::unique_lock<std::mutex> innerLk(initmt);
innerLk.unlock(); innerLk.unlock();
initcv.notify_one(); initcv.notify_one();
std::string thrName = std::string(getFriendlyName()) + " Client Thread"; std::string thrName = std::string(getFriendlyName()) + " Client";
logvisor::RegisterThreadName(thrName.c_str()); logvisor::RegisterThreadName(thrName.c_str());
clientReturn = m_callback.appMain(this); clientReturn = m_callback.appMain(this);
pthread_kill(mainThread, SIGUSR2); pthread_kill(mainThread, SIGUSR2);
@ -574,6 +574,7 @@ public:
std::shared_ptr<IWindow> newWindow(std::string_view title) std::shared_ptr<IWindow> newWindow(std::string_view title)
{ {
XLockDisplay(m_xDisp);
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, m_xcbConn, m_xDefaultScreen, m_xIM, std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, m_xcbConn, m_xDefaultScreen, m_xIM,
m_bestStyle, m_fontset, m_lastGlxCtx, (void*)m_getVkProc, &m_glContext); m_bestStyle, m_fontset, m_lastGlxCtx, (void*)m_getVkProc, &m_glContext);
@ -582,6 +583,7 @@ public:
m_bestStyle, m_fontset, m_lastGlxCtx, nullptr, &m_glContext); m_bestStyle, m_fontset, m_lastGlxCtx, nullptr, &m_glContext);
#endif #endif
m_windows[(Window)newWindow->getPlatformHandle()] = newWindow; m_windows[(Window)newWindow->getPlatformHandle()] = newWindow;
XUnlockDisplay(m_xDisp);
return newWindow; return newWindow;
} }

View File

@ -298,6 +298,8 @@ struct GraphicsContextXlib : IGraphicsContext
GLContext* m_glCtx; GLContext* m_glCtx;
Display* m_xDisp; Display* m_xDisp;
std::mutex m_initmt;
std::condition_variable m_initcv;
std::mutex m_vsyncmt; std::mutex m_vsyncmt;
std::condition_variable m_vsynccv; std::condition_variable m_vsynccv;
@ -506,15 +508,13 @@ public:
/* Spawn vsync thread */ /* Spawn vsync thread */
m_vsyncRunning = true; m_vsyncRunning = true;
std::mutex initmt; std::unique_lock<std::mutex> outerLk(m_initmt);
std::condition_variable initcv;
std::unique_lock<std::mutex> outerLk(initmt);
m_vsyncThread = std::thread([&]() m_vsyncThread = std::thread([&]()
{ {
Display* vsyncDisp; Display* vsyncDisp;
GLXContext vsyncCtx; GLXContext vsyncCtx;
{ {
std::unique_lock<std::mutex> innerLk(initmt); std::unique_lock<std::mutex> innerLk(m_initmt);
vsyncDisp = XOpenDisplay(0); vsyncDisp = XOpenDisplay(0);
if (!vsyncDisp) if (!vsyncDisp)
@ -531,7 +531,7 @@ public:
if (!glXMakeCurrent(vsyncDisp, DefaultRootWindow(vsyncDisp), vsyncCtx)) if (!glXMakeCurrent(vsyncDisp, DefaultRootWindow(vsyncDisp), vsyncCtx))
Log.report(logvisor::Fatal, "unable to make vsync context current"); Log.report(logvisor::Fatal, "unable to make vsync context current");
} }
initcv.notify_one(); m_initcv.notify_one();
while (m_vsyncRunning) while (m_vsyncRunning)
{ {
@ -549,7 +549,7 @@ public:
XUnlockDisplay(vsyncDisp); XUnlockDisplay(vsyncDisp);
XCloseDisplay(vsyncDisp); XCloseDisplay(vsyncDisp);
}); });
initcv.wait(outerLk); m_initcv.wait(outerLk);
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
m_commandQueue = _NewGLCommandQueue(this, m_glCtx); m_commandQueue = _NewGLCommandQueue(this, m_glCtx);
@ -642,7 +642,7 @@ struct GraphicsContextXlibVulkan : GraphicsContextXlib
std::unique_ptr<IGraphicsCommandQueue> m_commandQueue; std::unique_ptr<IGraphicsCommandQueue> m_commandQueue;
std::thread m_vsyncThread; std::thread m_vsyncThread;
bool m_vsyncRunning; std::atomic_bool m_vsyncRunning;
static void ThrowIfFailed(VkResult res) static void ThrowIfFailed(VkResult res)
{ {
@ -676,9 +676,9 @@ public:
m_surface = VK_NULL_HANDLE; m_surface = VK_NULL_HANDLE;
} }
if (m_vsyncRunning) if (m_vsyncRunning.load())
{ {
m_vsyncRunning = false; m_vsyncRunning.store(false);
if (m_vsyncThread.joinable()) if (m_vsyncThread.joinable())
m_vsyncThread.join(); m_vsyncThread.join();
} }
@ -832,16 +832,15 @@ public:
m_ctx->initSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace); m_ctx->initSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
/* Spawn vsync thread */ /* Spawn vsync thread */
m_vsyncRunning = true; m_vsyncRunning.store(true);
std::mutex initmt; std::unique_lock<std::mutex> outerLk(m_initmt);
std::condition_variable initcv;
std::unique_lock<std::mutex> outerLk(initmt);
m_vsyncThread = std::thread([&]() m_vsyncThread = std::thread([&]()
{ {
logvisor::RegisterThreadName("Boo VSync");
Display* vsyncDisp; Display* vsyncDisp;
GLXContext vsyncCtx; GLXContext vsyncCtx;
{ {
std::unique_lock<std::mutex> innerLk(initmt); std::unique_lock<std::mutex> innerLk(m_initmt);
vsyncDisp = XOpenDisplay(0); vsyncDisp = XOpenDisplay(0);
if (!vsyncDisp) if (!vsyncDisp)
@ -858,9 +857,9 @@ public:
if (!glXMakeCurrent(vsyncDisp, DefaultRootWindow(vsyncDisp), vsyncCtx)) if (!glXMakeCurrent(vsyncDisp, DefaultRootWindow(vsyncDisp), vsyncCtx))
Log.report(logvisor::Fatal, "unable to make vsync context current"); Log.report(logvisor::Fatal, "unable to make vsync context current");
} }
initcv.notify_one(); m_initcv.notify_one();
while (m_vsyncRunning) while (m_vsyncRunning.load())
{ {
unsigned int sync; unsigned int sync;
int err = glXWaitVideoSyncSGI(1, 0, &sync); int err = glXWaitVideoSyncSGI(1, 0, &sync);
@ -874,7 +873,7 @@ public:
XUnlockDisplay(vsyncDisp); XUnlockDisplay(vsyncDisp);
XCloseDisplay(vsyncDisp); XCloseDisplay(vsyncDisp);
}); });
initcv.wait(outerLk); m_initcv.wait(outerLk);
m_dataFactory = _NewVulkanDataFactory(this, m_ctx); m_dataFactory = _NewVulkanDataFactory(this, m_ctx);
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this); m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
@ -1118,7 +1117,9 @@ public:
void setCallback(IWindowCallback* cb) void setCallback(IWindowCallback* cb)
{ {
XLockDisplay(m_xDisp);
m_callback = cb; m_callback = cb;
XUnlockDisplay(m_xDisp);
} }
void closeWindow() void closeWindow()
@ -2064,11 +2065,9 @@ std::shared_ptr<IWindow> _WindowXlibNew(std::string_view title,
int defaultScreen, XIM xIM, XIMStyle bestInputStyle, XFontSet fontset, int defaultScreen, XIM xIM, XIMStyle bestInputStyle, XFontSet fontset,
GLXContext lastCtx, void* vulkanHandle, GLContext* glCtx) GLXContext lastCtx, void* vulkanHandle, GLContext* glCtx)
{ {
XLockDisplay(display);
std::shared_ptr<IWindow> ret = std::make_shared<WindowXlib>(title, display, xcbConn, std::shared_ptr<IWindow> ret = std::make_shared<WindowXlib>(title, display, xcbConn,
defaultScreen, xIM, bestInputStyle, fontset, lastCtx, defaultScreen, xIM, bestInputStyle, fontset, lastCtx,
vulkanHandle, glCtx); vulkanHandle, glCtx);
XUnlockDisplay(display);
return ret; return ret;
} }

@ -1 +1 @@
Subproject commit 2352699c6598866548b81c3886337b4a8bb91472 Subproject commit 82f1df9c40edc99a2d68499f363161e5b0bef849