[idd] common: use CSRWLock throughout the drivers

Make CSRWLock own the native lock and provide scoped guards for shared,
exclusive, early-unlock, and non-blocking use.

Replace direct SRW lock management throughout the IDD, input driver,
and helper while preserving the existing lock scopes.
This commit is contained in:
Geoffrey McRae
2026-08-11 22:06:31 +10:00
parent 2543366f5f
commit 61a49ebaba
37 changed files with 576 additions and 525 deletions

View File

@@ -207,18 +207,18 @@ void CLGMPControl::SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info,
void CLGMPControl::SetColorTransform(
std::shared_ptr<const D12ColorTransform> transform)
{
AcquireSRWLockExclusive(&m_colorTransformLock);
m_colorTransform = std::move(transform);
ReleaseSRWLockExclusive(&m_colorTransformLock);
{
CSRWExclusiveLock lock(m_colorTransformLock);
m_colorTransform = std::move(transform);
}
SendColorTransform();
}
std::shared_ptr<const D12ColorTransform>
CLGMPControl::GetColorTransform() const
{
AcquireSRWLockShared(&m_colorTransformLock);
CSRWSharedLock lock(m_colorTransformLock);
std::shared_ptr<const D12ColorTransform> transform = m_colorTransform;
ReleaseSRWLockShared(&m_colorTransformLock);
return transform;
}

View File

@@ -20,6 +20,8 @@
#pragma once
#include "CSRWLock.h"
#include "transport/lgmp/CLGMPHost.h"
#include "transport/IControlTransport.h"
@@ -55,7 +57,7 @@ private:
int m_cursorX = 0;
int m_cursorY = 0;
mutable SRWLOCK m_colorTransformLock = SRWLOCK_INIT;
mutable CSRWLock m_colorTransformLock;
std::shared_ptr<const D12ColorTransform> m_colorTransform;
void SendColorTransform();

View File

@@ -216,19 +216,20 @@ void CLGMPFrameTransport::DeInit()
{
m_frameScheduler.Reset();
AcquireSRWLockExclusive(&m_framePublishLock);
m_submittedFrameIndex.store(-1, std::memory_order_release);
m_readyFrameIndex.store(-1, std::memory_order_release);
m_deferredOwnerFrameIndex = -1;
m_framePublishSequence = 0;
memset(m_frameLastPublishSequence, 0,
sizeof(m_frameLastPublishSequence));
memset(m_frameCompleted, 0, sizeof(m_frameCompleted));
for (FrameDelivery& delivery : m_frameDelivery)
delivery = {};
for (OwnerDelivery& delivery : m_ownerDelivery)
delivery = {};
ReleaseSRWLockExclusive(&m_framePublishLock);
{
CSRWExclusiveLock lock(m_framePublishLock);
m_submittedFrameIndex.store(-1, std::memory_order_release);
m_readyFrameIndex.store(-1, std::memory_order_release);
m_deferredOwnerFrameIndex = -1;
m_framePublishSequence = 0;
memset(m_frameLastPublishSequence, 0,
sizeof(m_frameLastPublishSequence));
memset(m_frameCompleted, 0, sizeof(m_frameCompleted));
for (FrameDelivery& delivery : m_frameDelivery)
delivery = {};
for (OwnerDelivery& delivery : m_ownerDelivery)
delivery = {};
}
for (int i = 0; i < LGMP_Q_FRAME_BUFFER_LEN; ++i)
{
@@ -444,7 +445,7 @@ void CLGMPFrameTransport::ProcessFrameDeliveries()
if (!m_frameOwnerQueue[i])
return;
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
bool released = false;
for (unsigned i = 0; i < LGMP_Q_FRAME_BUFFER_LEN; ++i)
@@ -482,7 +483,7 @@ void CLGMPFrameTransport::ProcessFrameDeliveries()
owner = {};
released = true;
}
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
if (released)
m_frameScheduler.NotifyPublisher();
@@ -632,7 +633,7 @@ bool CLGMPFrameTransport::FrameBufferAvailable(
if (!m_frameOwnerQueue[i])
return false;
AcquireSRWLockShared(&m_framePublishLock);
CSRWSharedLock lock(m_framePublishLock);
bool allowReady = false;
// Pipeline one frame through each independent owner lane. Count the shared
// fallback against the same limit so it cannot become a third delivery for
@@ -647,15 +648,11 @@ bool CLGMPFrameTransport::FrameBufferAvailable(
(ownerBlocked || ownerQueuesBlocked);
}
else if (lgmpHostQueuePending(m_frameQueue) != 0)
{
ReleaseSRWLockShared(&m_framePublishLock);
return false;
}
// With no owner delivery lane available, a copy can still replace an
// unreferenced retained frame and be republished when a lane clears.
const bool available = FindAvailableFrameBuffer(allowReady) >= 0;
ReleaseSRWLockShared(&m_framePublishLock);
return available;
}
@@ -679,16 +676,13 @@ bool CLGMPFrameTransport::GetPendingDeliveryTarget(uint64_t now,
if (!m_frameQueue)
return false;
AcquireSRWLockShared(&m_framePublishLock);
CSRWSharedLock lock(m_framePublishLock);
const LONG frameIndex =
m_readyFrameIndex.load(std::memory_order_acquire);
if (frameIndex < 0 ||
m_frameInFlight[frameIndex].load(std::memory_order_acquire) ||
lgmpHostQueuePending(m_frameQueue) != 0)
{
ReleaseSRWLockShared(&m_framePublishLock);
return false;
}
uint32_t blockedClientIDs[LGMP_Q_FRAME_LEN] = {};
unsigned blockedCount = 0;
@@ -699,7 +693,6 @@ bool CLGMPFrameTransport::GetPendingDeliveryTarget(uint64_t now,
const bool result = m_frameScheduler.GetSecondaryTarget(
m_frame[frameIndex]->frameSerial, now,
blockedClientIDs, blockedCount, target);
ReleaseSRWLockShared(&m_framePublishLock);
return result;
}
@@ -709,20 +702,17 @@ bool CLGMPFrameTransport::RetryPendingDelivery(uint64_t now, bool& retry)
if (!m_frameQueue)
return false;
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
const LONG frameIndex =
m_readyFrameIndex.load(std::memory_order_acquire);
if (frameIndex < 0 ||
m_frameInFlight[frameIndex].load(std::memory_order_acquire) ||
lgmpHostQueuePending(m_frameQueue) != 0)
{
ReleaseSRWLockExclusive(&m_framePublishLock);
return false;
}
const SharedFramePostResult result = PostSharedFrame(
static_cast<unsigned>(frameIndex), 0, now);
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
retry = result == SHARED_FRAME_FAILED;
return result == SHARED_FRAME_POSTED;
}
@@ -746,7 +736,7 @@ PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer(
return result;
}
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
const bool ownerBlocked = schedule.clientID &&
CountOwnerDeliveries(schedule.clientID) >= LGMP_Q_FRAME_LEN;
const bool allowReady = allowReadyReplacement &&
@@ -774,7 +764,7 @@ PreparedFrameBuffer CLGMPFrameTransport::PrepareFrameBuffer(
(!m_frameLastPublishSequence[availableFrameIndex] ||
m_framePublishSequence >
m_frameLastPublishSequence[availableFrameIndex] + 1);
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
if (!acquired)
return result;
const unsigned frameIndex = static_cast<unsigned>(availableFrameIndex);
@@ -939,16 +929,13 @@ bool CLGMPFrameTransport::PublishFrameBuffer(unsigned frameIndex,
return false;
const uint64_t now = CFrameScheduler::Nanotime();
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
CFrameScheduler::Schedule currentSchedule = {};
const bool scheduling =
m_frameScheduler.GetSchedule(currentSchedule);
if (scheduling != (schedule.clientID != 0) ||
(scheduling && !FrameScheduleMatches(schedule, currentSchedule)))
{
ReleaseSRWLockExclusive(&m_framePublishLock);
return false;
}
KVMFRFrame * frame = m_frame[frameIndex];
frame->timingFlags = 0;
@@ -1023,7 +1010,7 @@ bool CLGMPFrameTransport::PublishFrameBuffer(unsigned frameIndex,
m_submittedFrameIndex.store(
static_cast<LONG>(frameIndex), std::memory_order_release);
}
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
if (!published)
{
@@ -1042,14 +1029,11 @@ bool CLGMPFrameTransport::RepublishFrameBuffer(
if (!schedule.clientID)
return false;
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
CFrameScheduler::Schedule currentSchedule = {};
if (!m_frameScheduler.GetSchedule(currentSchedule) ||
!FrameScheduleMatches(schedule, currentSchedule))
{
ReleaseSRWLockExclusive(&m_framePublishLock);
return false;
}
LONG frameIndex = m_deferredOwnerFrameIndex;
if (frameIndex >= 0 &&
@@ -1063,10 +1047,7 @@ bool CLGMPFrameTransport::RepublishFrameBuffer(
frameIndex = m_readyFrameIndex.load(std::memory_order_acquire);
if (frameIndex < 0 ||
m_frameInFlight[frameIndex].load(std::memory_order_acquire))
{
ReleaseSRWLockExclusive(&m_framePublishLock);
return false;
}
CFrameScheduler::Schedule deliverySchedule = schedule;
deliverySchedule.deliveryDeadlineSerial = 0;
@@ -1078,16 +1059,13 @@ bool CLGMPFrameTransport::RepublishFrameBuffer(
{
if (m_deferredOwnerFrameIndex == frameIndex)
m_deferredOwnerFrameIndex = -1;
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
m_frameScheduler.FrameRepublished(schedule, frameSerial);
return true;
}
if (CountOwnerDeliveries(schedule.clientID) >= LGMP_Q_FRAME_LEN)
{
ReleaseSRWLockExclusive(&m_framePublishLock);
return false;
}
const int ownerQueueIndex =
FindAvailableOwnerQueue(static_cast<unsigned>(frameIndex));
@@ -1097,7 +1075,7 @@ bool CLGMPFrameTransport::RepublishFrameBuffer(
static_cast<unsigned>(frameIndex), deliverySchedule);
if (published && m_deferredOwnerFrameIndex == frameIndex)
m_deferredOwnerFrameIndex = -1;
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
if (published)
m_frameScheduler.FrameRepublished(schedule, frameSerial);
return published;
@@ -1123,7 +1101,7 @@ bool CLGMPFrameTransport::RepublishFrameBuffer(
if (m_deferredOwnerFrameIndex == frameIndex)
m_deferredOwnerFrameIndex = -1;
}
ReleaseSRWLockExclusive(&m_framePublishLock);
lock.Unlock();
if (status != LGMP_OK || !recipientCount)
{
@@ -1201,7 +1179,7 @@ void CLGMPFrameTransport::AbortFrameBuffer(unsigned frameIndex)
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
return;
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
m_frameBuffer[frameIndex]->wp = 0;
InterlockedExchange(
(volatile LONG *)&m_frame[frameIndex]->timingValid, 0);
@@ -1209,7 +1187,6 @@ void CLGMPFrameTransport::AbortFrameBuffer(unsigned frameIndex)
if (m_deferredOwnerFrameIndex == static_cast<LONG>(frameIndex))
m_deferredOwnerFrameIndex = -1;
m_frameInFlight[frameIndex].store(false, std::memory_order_release);
ReleaseSRWLockExclusive(&m_framePublishLock);
}
void CLGMPFrameTransport::FailFrameBuffer(unsigned frameIndex)
@@ -1229,7 +1206,7 @@ void CLGMPFrameTransport::CompleteFrameBuffer(
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
return;
AcquireSRWLockExclusive(&m_framePublishLock);
CSRWExclusiveLock lock(m_framePublishLock);
m_frameCompleted[frameIndex] = succeeded;
if (!succeeded &&
m_deferredOwnerFrameIndex == static_cast<LONG>(frameIndex))
@@ -1248,7 +1225,6 @@ void CLGMPFrameTransport::CompleteFrameBuffer(
static_cast<LONG>(frameIndex), std::memory_order_release);
}
m_frameInFlight[frameIndex].store(false, std::memory_order_release);
ReleaseSRWLockExclusive(&m_framePublishLock);
}
void CLGMPFrameTransport::SetFrameTiming(unsigned frameIndex,

View File

@@ -20,6 +20,8 @@
#pragma once
#include "CSRWLock.h"
#include <Windows.h>
#include <atomic>
#include <stdint.h>
@@ -97,7 +99,7 @@ private:
LONG m_deferredOwnerFrameIndex = -1;
std::atomic<bool> m_frameInFlight[LGMP_Q_FRAME_BUFFER_LEN] = {};
bool m_frameCompleted[LGMP_Q_FRAME_BUFFER_LEN] = {};
SRWLOCK m_framePublishLock = SRWLOCK_INIT;
CSRWLock m_framePublishLock;
uint64_t m_framePublishSequence = 0;
uint64_t m_frameLastPublishSequence[LGMP_Q_FRAME_BUFFER_LEN] = {};

View File

@@ -137,9 +137,8 @@ void CLGMPHost::DeInit()
LGMP_STATUS CLGMPHost::Process()
{
AcquireSRWLockExclusive(&m_processLock);
CSRWExclusiveLock lock(m_processLock);
const LGMP_STATUS status = lgmpHostProcess(m_host);
ReleaseSRWLockExclusive(&m_processLock);
return status;
}

View File

@@ -20,6 +20,8 @@
#pragma once
#include "CSRWLock.h"
#include <Windows.h>
#include <stddef.h>
@@ -34,8 +36,8 @@ class CIVSHMEM;
class CLGMPHost
{
private:
PLGMPHost m_host = nullptr;
SRWLOCK m_processLock = SRWLOCK_INIT;
PLGMPHost m_host = nullptr;
CSRWLock m_processLock;
public:
CLGMPHost() = default;

View File

@@ -179,7 +179,7 @@ void CLGMPInputTransport::PublishStatus()
bool CLGMPInputTransport::Start(IInputSink& sink)
{
CSRWExclusiveLock lock(&m_lifecycleLock);
CSRWExclusiveLock lock(m_lifecycleLock);
if (m_thread)
{
const DWORD state = WaitForSingleObject(m_thread, 0);
@@ -249,7 +249,7 @@ bool CLGMPInputTransport::Start(IInputSink& sink)
void CLGMPInputTransport::Stop()
{
CSRWExclusiveLock lock(&m_lifecycleLock);
CSRWExclusiveLock lock(m_lifecycleLock);
if (m_stopEvent)
SetEvent(m_stopEvent);

View File

@@ -20,6 +20,7 @@
#pragma once
#include "CSRWLock.h"
#include "transport/IInputTransport.h"
#include "common/LGMPConfig.h"
@@ -64,10 +65,10 @@ private:
PLGMPMemory m_statusMemory[LGMP_Q_INPUT_LEN] = {};
IInputSink * m_sink = nullptr;
SRWLOCK m_lifecycleLock = SRWLOCK_INIT;
HANDLE m_stopEvent = nullptr;
HANDLE m_pollTimer = nullptr;
HANDLE m_thread = nullptr;
CSRWLock m_lifecycleLock;
HANDLE m_stopEvent = nullptr;
HANDLE m_pollTimer = nullptr;
HANDLE m_thread = nullptr;
uint32_t m_ownerClientID = 0;
uint32_t m_ownerGeneration = 0;