LivoxGen1: Use syncCancelerForAsyncWork in producer pipeline
This commit is contained in:
@@ -464,117 +464,137 @@ public:
|
||||
void produceFrameReq1_doAssemble_posted(
|
||||
std::shared_ptr<ProduceFrameReq> context)
|
||||
{
|
||||
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock);
|
||||
if (!pcloudProducer.shouldContinue)
|
||||
const bool shouldContinue = pcloudProducer.stimulusProducerCanceler
|
||||
.execUncancelableSegmentOrAbort(
|
||||
[this, context]()
|
||||
{
|
||||
pcloudProducer.ioUringAssemblyEngine.assembleFrameReq(
|
||||
{context, std::bind(
|
||||
&ProduceFrameReq::produceFrameReq2_assembleDone,
|
||||
context.get(), context,
|
||||
std::placeholders::_1, std::placeholders::_2)});
|
||||
});
|
||||
|
||||
if (!shouldContinue)
|
||||
{
|
||||
callOriginalCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
pcloudProducer.ioUringAssemblyEngine.assembleFrameReq(
|
||||
{context, std::bind(
|
||||
&ProduceFrameReq::produceFrameReq2_assembleDone,
|
||||
context.get(), context,
|
||||
std::placeholders::_1, std::placeholders::_2)});
|
||||
}
|
||||
|
||||
void produceFrameReq2_assembleDone(
|
||||
std::shared_ptr<ProduceFrameReq> context,
|
||||
bool success, sscl::AsynchronousLoop loop)
|
||||
{
|
||||
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock);
|
||||
if (!pcloudProducer.shouldContinue)
|
||||
bool shouldContinue = pcloudProducer.stimulusProducerCanceler
|
||||
.execUncancelableSegmentOrAbort(
|
||||
[this, context, success, loop]()
|
||||
{
|
||||
callOriginalCallback();
|
||||
return;
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
callOriginalCallback();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
callOriginalCallback();
|
||||
|
||||
if (pcloudProducer.attachedStimulusBuffers.size() > 0) {
|
||||
std::cerr << __func__ << ": Failed to assemble frame.\n";
|
||||
if (pcloudProducer.attachedStimulusBuffers.size() > 0) {
|
||||
std::cerr << __func__
|
||||
<< ": Failed to assemble frame.\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
context->frameAssemblyResult = loop;
|
||||
|
||||
// Check if intensity buffer is attached and acquire frame if so
|
||||
if (auto intensityBuff = pcloudProducer
|
||||
.intensityStimulusBuffer.load(
|
||||
std::memory_order_acquire))
|
||||
{
|
||||
size_t intensityRingbuffIndex = intensityBuff
|
||||
->ringBuffer.getIndexToProduceInto();
|
||||
|
||||
StimulusFrame& intensityStimFrame = intensityBuff
|
||||
->ringBuffer.getDataAtSlot(
|
||||
intensityRingbuffIndex);
|
||||
|
||||
intensityStimFrame.lock.writeAcquire();
|
||||
context->intensityStimFrame = std::make_optional(
|
||||
std::ref(intensityStimFrame));
|
||||
}
|
||||
else {
|
||||
context->intensityStimFrame = std::nullopt;
|
||||
}
|
||||
|
||||
// Check if light ambience buffer is attached and acquire frame if so
|
||||
std::optional<AmbienceProductionDesc>
|
||||
lightAmbienceProductionDescDesc;
|
||||
if (auto lightAmbienceBuff =
|
||||
pcloudProducer.lightAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire))
|
||||
{
|
||||
size_t lightAmbienceRingbuffIndex = lightAmbienceBuff
|
||||
->ringBuffer.getIndexToProduceInto();
|
||||
|
||||
StimulusFrame& lightAmbienceStimFrame =
|
||||
lightAmbienceBuff->ringBuffer.getDataAtSlot(
|
||||
lightAmbienceRingbuffIndex);
|
||||
|
||||
lightAmbienceStimFrame.lock.writeAcquire();
|
||||
context->lightAmbienceStimFrame = std::make_optional(
|
||||
std::ref(lightAmbienceStimFrame));
|
||||
lightAmbienceProductionDescDesc =
|
||||
AmbienceProductionDesc{
|
||||
std::ref(lightAmbienceStimFrame),
|
||||
lightAmbienceBuff
|
||||
->passbandCountGtComparator};
|
||||
}
|
||||
else {
|
||||
context->lightAmbienceStimFrame = std::nullopt;
|
||||
}
|
||||
|
||||
// Check if dark ambience buffer is attached and acquire frame if so
|
||||
std::optional<AmbienceProductionDesc>
|
||||
darkAmbienceProductionDescDesc;
|
||||
if (auto darkAmbienceBuff =
|
||||
pcloudProducer.darkAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire))
|
||||
{
|
||||
size_t darkAmbienceRingbuffIndex = darkAmbienceBuff
|
||||
->ringBuffer.getIndexToProduceInto();
|
||||
|
||||
StimulusFrame& darkAmbienceStimFrame =
|
||||
darkAmbienceBuff->ringBuffer.getDataAtSlot(
|
||||
darkAmbienceRingbuffIndex);
|
||||
|
||||
darkAmbienceStimFrame.lock.writeAcquire();
|
||||
context->darkAmbienceStimFrame = std::make_optional(
|
||||
std::ref(darkAmbienceStimFrame));
|
||||
darkAmbienceProductionDescDesc =
|
||||
AmbienceProductionDesc{
|
||||
std::ref(darkAmbienceStimFrame),
|
||||
darkAmbienceBuff
|
||||
->passbandCountLtComparator};
|
||||
}
|
||||
else {
|
||||
context->darkAmbienceStimFrame = std::nullopt;
|
||||
}
|
||||
|
||||
pcloudProducer.openClCollatingAndMeshingEngine
|
||||
.compactCollateAndMeshFrameReq(
|
||||
context->frameAssemblyResult, stimulusFrame,
|
||||
context->intensityStimFrame,
|
||||
std::move(lightAmbienceProductionDescDesc),
|
||||
std::move(darkAmbienceProductionDescDesc),
|
||||
{context, std::bind(
|
||||
&ProduceFrameReq
|
||||
::produceFrameReq3_compactCollateDone,
|
||||
context.get(), context,
|
||||
std::placeholders::_1, std::placeholders::_2)});
|
||||
});
|
||||
|
||||
if (!shouldContinue)
|
||||
{
|
||||
callOriginalCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
context->frameAssemblyResult = loop;
|
||||
|
||||
// Check if intensity buffer is attached and acquire frame if so
|
||||
if (auto intensityBuff = pcloudProducer.intensityStimulusBuffer.load(
|
||||
std::memory_order_acquire))
|
||||
{
|
||||
size_t intensityRingbuffIndex = intensityBuff
|
||||
->ringBuffer.getIndexToProduceInto();
|
||||
|
||||
StimulusFrame& intensityStimFrame = intensityBuff
|
||||
->ringBuffer.getDataAtSlot(
|
||||
intensityRingbuffIndex);
|
||||
|
||||
intensityStimFrame.lock.writeAcquire();
|
||||
context->intensityStimFrame = std::make_optional(
|
||||
std::ref(intensityStimFrame));
|
||||
}
|
||||
else {
|
||||
context->intensityStimFrame = std::nullopt;
|
||||
}
|
||||
|
||||
// Check if light ambience buffer is attached and acquire frame if so
|
||||
std::optional<AmbienceProductionDesc> lightAmbienceProductionDescDesc;
|
||||
if (auto lightAmbienceBuff =
|
||||
pcloudProducer.lightAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire))
|
||||
{
|
||||
size_t lightAmbienceRingbuffIndex = lightAmbienceBuff
|
||||
->ringBuffer.getIndexToProduceInto();
|
||||
|
||||
StimulusFrame& lightAmbienceStimFrame = lightAmbienceBuff
|
||||
->ringBuffer.getDataAtSlot(lightAmbienceRingbuffIndex);
|
||||
|
||||
lightAmbienceStimFrame.lock.writeAcquire();
|
||||
context->lightAmbienceStimFrame = std::make_optional(
|
||||
std::ref(lightAmbienceStimFrame));
|
||||
lightAmbienceProductionDescDesc = AmbienceProductionDesc{
|
||||
std::ref(lightAmbienceStimFrame),
|
||||
lightAmbienceBuff->passbandCountGtComparator};
|
||||
}
|
||||
else {
|
||||
context->lightAmbienceStimFrame = std::nullopt;
|
||||
}
|
||||
|
||||
// Check if dark ambience buffer is attached and acquire frame if so
|
||||
std::optional<AmbienceProductionDesc> darkAmbienceProductionDescDesc;
|
||||
if (auto darkAmbienceBuff =
|
||||
pcloudProducer.darkAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire))
|
||||
{
|
||||
size_t darkAmbienceRingbuffIndex = darkAmbienceBuff
|
||||
->ringBuffer.getIndexToProduceInto();
|
||||
|
||||
StimulusFrame& darkAmbienceStimFrame = darkAmbienceBuff
|
||||
->ringBuffer.getDataAtSlot(darkAmbienceRingbuffIndex);
|
||||
|
||||
darkAmbienceStimFrame.lock.writeAcquire();
|
||||
context->darkAmbienceStimFrame = std::make_optional(
|
||||
std::ref(darkAmbienceStimFrame));
|
||||
darkAmbienceProductionDescDesc = AmbienceProductionDesc{
|
||||
std::ref(darkAmbienceStimFrame),
|
||||
darkAmbienceBuff->passbandCountLtComparator};
|
||||
}
|
||||
else {
|
||||
context->darkAmbienceStimFrame = std::nullopt;
|
||||
}
|
||||
|
||||
pcloudProducer.openClCollatingAndMeshingEngine.compactCollateAndMeshFrameReq(
|
||||
loop, stimulusFrame,
|
||||
context->intensityStimFrame,
|
||||
std::move(lightAmbienceProductionDescDesc),
|
||||
std::move(darkAmbienceProductionDescDesc),
|
||||
{context, std::bind(
|
||||
&ProduceFrameReq::produceFrameReq3_compactCollateDone,
|
||||
context.get(), context,
|
||||
std::placeholders::_1, std::placeholders::_2)});
|
||||
}
|
||||
|
||||
void produceFrameReq3_compactCollateDone(
|
||||
@@ -603,7 +623,10 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
// Release intensity frame if it was used
|
||||
/** EXPLANATION:
|
||||
* Release intensity/ambience frames if they were supplied/used,
|
||||
* regardless of whether or not a cancelation request occurred.
|
||||
*/
|
||||
if (context->intensityStimFrame.has_value()) {
|
||||
context->intensityStimFrame->get().lock.writeRelease();
|
||||
}
|
||||
@@ -615,130 +638,169 @@ public:
|
||||
context->darkAmbienceStimFrame->get().lock.writeRelease();
|
||||
}
|
||||
|
||||
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock);
|
||||
if (!pcloudProducer.shouldContinue)
|
||||
if (!success)
|
||||
{
|
||||
callOriginalCallback();
|
||||
|
||||
std::cerr << __func__
|
||||
<< ": Failed to compact and collate frame"
|
||||
<< std::endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** EXPLANATION:
|
||||
* Cancellation early exit for the success path. Analogous to the
|
||||
* (legacy, removed) pre-canceler check under shouldContinueLock before
|
||||
* lock.unlockPrematurely() in the former CPS version of this handler.
|
||||
*
|
||||
* Assumptions that make the unlocked tail (dump, debug logging, stage
|
||||
* durations, final callOriginalCallback()) safe without holding
|
||||
* stimulusProducerCanceler.s.lock:
|
||||
*
|
||||
* 1. This handler is only entered from
|
||||
* CompactCollateAndMeshFrameReq4's execUncancelableSegmentOrAbort
|
||||
* body, so openClCollatingAndMeshingEngine::finalize() cannot
|
||||
* tear down OpenCL/engine state until this function returns.
|
||||
*
|
||||
* 2. PcloudStimulusProducer::stop() finalizes OpenCL before io_uring,
|
||||
* so getCompactKernelDuration()/getCollateKernelDuration() and
|
||||
* getAssemblyDuration() are not racing engine finalize here.
|
||||
*
|
||||
* 3. dump/logging reads only producer-owned state (pcloudFrameDumper,
|
||||
* collationBuffer, device, context->frameAssemblyResult) that
|
||||
* stop()/finalize() do not destroy.
|
||||
*
|
||||
* 4. A stop() that lands after this read but before the tail is
|
||||
* intentional stale work (same as unlockPrematurely()), not UAF.
|
||||
*
|
||||
* Rework to run portions inside stimulusProducerCanceler
|
||||
* execUncancelableSegmentOrAbort if any of the above ceases to hold:
|
||||
* e.g. this callback is invoked outside the OpenCL uncancelable
|
||||
* segment, the tail begins touching engine or buffer state that
|
||||
* finalize() resets, or stop() ordering changes so teardown can
|
||||
* interleave with the unlocked tail.
|
||||
*/
|
||||
const bool shouldContinue =
|
||||
!pcloudProducer.stimulusProducerCanceler.isCancellationRequested();
|
||||
|
||||
if (!shouldContinue)
|
||||
{
|
||||
callOriginalCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
std::cerr << __func__ << ": Failed to compact and collate frame" << std::endl;
|
||||
} else
|
||||
if (pcloudProducer.pcloudFrameDumper.isEnabled())
|
||||
{
|
||||
lock.unlockPrematurely();
|
||||
if (pcloudProducer.pcloudFrameDumper.isEnabled())
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
pcloudProducer.pcloudFrameDumper.dumpProducedFrame(
|
||||
*pcloudProducer.device,
|
||||
pcloudProducer.collationBuffer,
|
||||
context->frameAssemblyResult);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << __func__ << ": Failed to dump pcloud frame: "
|
||||
<< e.what() << std::endl;
|
||||
}
|
||||
pcloudProducer.pcloudFrameDumper.dumpProducedFrame(
|
||||
*pcloudProducer.device,
|
||||
pcloudProducer.collationBuffer,
|
||||
context->frameAssemblyResult);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << __func__ << ": Failed to dump pcloud frame: "
|
||||
<< e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#if SMO_DEBUG_PCLOUD_AMBIENCE_INTRIN
|
||||
if (logLightAmbience)
|
||||
if (logLightAmbience)
|
||||
{
|
||||
auto lightBuff =
|
||||
pcloudProducer.lightAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire);
|
||||
if (lightBuff)
|
||||
{
|
||||
auto lightBuff =
|
||||
pcloudProducer.lightAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire);
|
||||
if (lightBuff)
|
||||
std::cerr << __func__ << ": pcloudLightAmbience "
|
||||
<< "passbandCount=" << logLightPassbandCount
|
||||
<< " (per-slot avg intensity "
|
||||
<< ambienceComparatorOpChar(
|
||||
lightBuff->passbandCountGtComparator.op)
|
||||
<< " " << lightBuff->passbandCountGtComparator.value
|
||||
<< ")";
|
||||
if (lightBuff->negtrinInterestConfig.has_value())
|
||||
{
|
||||
std::cerr << __func__ << ": pcloudLightAmbience "
|
||||
<< "passbandCount=" << logLightPassbandCount
|
||||
<< " (per-slot avg intensity "
|
||||
<< ambienceComparatorOpChar(
|
||||
lightBuff->passbandCountGtComparator.op)
|
||||
<< " " << lightBuff->passbandCountGtComparator.value
|
||||
<< ")";
|
||||
if (lightBuff->negtrinInterestConfig.has_value())
|
||||
const auto& nc = *lightBuff->negtrinInterestConfig;
|
||||
std::cerr << " negtrinInterestThr=" << nc.threshold;
|
||||
if (nc.percentage != 0U)
|
||||
{
|
||||
const auto& nc = *lightBuff->negtrinInterestConfig;
|
||||
std::cerr << " negtrinInterestThr=" << nc.threshold;
|
||||
if (nc.percentage != 0U)
|
||||
{
|
||||
std::cerr << " (from " << nc.percentage << "%)";
|
||||
}
|
||||
std::cerr << " meetsNegtrinInterest="
|
||||
<< (lightBuff->shouldTriggerNegtrinEvent(
|
||||
logLightPassbandCount)
|
||||
? "yes" : "no");
|
||||
std::cerr << " (from " << nc.percentage << "%)";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " negtrinInterest(n/a)";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " meetsNegtrinInterest="
|
||||
<< (lightBuff->shouldTriggerNegtrinEvent(
|
||||
logLightPassbandCount)
|
||||
? "yes" : "no");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " negtrinInterest(n/a)";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
if (logDarkAmbience)
|
||||
}
|
||||
if (logDarkAmbience)
|
||||
{
|
||||
auto darkBuff =
|
||||
pcloudProducer.darkAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire);
|
||||
if (darkBuff)
|
||||
{
|
||||
auto darkBuff =
|
||||
pcloudProducer.darkAmbienceStimulusBuffer.load(
|
||||
std::memory_order_acquire);
|
||||
if (darkBuff)
|
||||
std::cerr << __func__ << ": pcloudDarkAmbience "
|
||||
<< "passbandCount=" << logDarkPassbandCount
|
||||
<< " (per-slot avg intensity "
|
||||
<< ambienceComparatorOpChar(
|
||||
darkBuff->passbandCountLtComparator.op)
|
||||
<< " " << darkBuff->passbandCountLtComparator.value
|
||||
<< ")";
|
||||
if (darkBuff->postrinInterestConfig.has_value())
|
||||
{
|
||||
std::cerr << __func__ << ": pcloudDarkAmbience "
|
||||
<< "passbandCount=" << logDarkPassbandCount
|
||||
<< " (per-slot avg intensity "
|
||||
<< ambienceComparatorOpChar(
|
||||
darkBuff->passbandCountLtComparator.op)
|
||||
<< " " << darkBuff->passbandCountLtComparator.value
|
||||
<< ")";
|
||||
if (darkBuff->postrinInterestConfig.has_value())
|
||||
const auto& pc = *darkBuff->postrinInterestConfig;
|
||||
std::cerr << " postrinInterestThr=" << pc.threshold;
|
||||
if (pc.percentage != 0U)
|
||||
{
|
||||
const auto& pc = *darkBuff->postrinInterestConfig;
|
||||
std::cerr << " postrinInterestThr=" << pc.threshold;
|
||||
if (pc.percentage != 0U)
|
||||
{
|
||||
std::cerr << " (from " << pc.percentage << "%)";
|
||||
}
|
||||
std::cerr << " meetsPostrinInterest="
|
||||
<< (darkBuff->shouldTriggerPostrinEvent(
|
||||
logDarkPassbandCount)
|
||||
? "yes" : "no");
|
||||
std::cerr << " (from " << pc.percentage << "%)";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " postrinInterest(n/a)";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " meetsPostrinInterest="
|
||||
<< (darkBuff->shouldTriggerPostrinEvent(
|
||||
logDarkPassbandCount)
|
||||
? "yes" : "no");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " postrinInterest(n/a)";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SMO_PRINT_PCLOUD_STAGE_DURATIONS
|
||||
const auto logNow = std::chrono::system_clock::now();
|
||||
const std::time_t logTime =
|
||||
std::chrono::system_clock::to_time_t(logNow);
|
||||
const auto logSubsecMs =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
logNow.time_since_epoch()) % 1000;
|
||||
auto assemblyDuration =
|
||||
pcloudProducer.ioUringAssemblyEngine.getAssemblyDuration();
|
||||
auto compactDuration =
|
||||
pcloudProducer.openClCollatingAndMeshingEngine
|
||||
.getCompactKernelDuration();
|
||||
auto collateDuration =
|
||||
pcloudProducer.openClCollatingAndMeshingEngine
|
||||
.getCollateKernelDuration();
|
||||
std::cout << std::put_time(std::localtime(&logTime), "%T")
|
||||
<< '.' << std::setfill('0') << std::setw(3)
|
||||
<< logSubsecMs.count() << ' '
|
||||
<< __func__ << ": stage durations: assembly="
|
||||
<< assemblyDuration.count()
|
||||
<< "ms, compactKernel=" << compactDuration.count()
|
||||
<< "ms, collateKernel=" << collateDuration.count()
|
||||
<< "ms" << std::endl;
|
||||
const auto logNow = std::chrono::system_clock::now();
|
||||
const std::time_t logTime =
|
||||
std::chrono::system_clock::to_time_t(logNow);
|
||||
const auto logSubsecMs =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
logNow.time_since_epoch()) % 1000;
|
||||
auto assemblyDuration =
|
||||
pcloudProducer.ioUringAssemblyEngine.getAssemblyDuration();
|
||||
auto compactDuration =
|
||||
pcloudProducer.openClCollatingAndMeshingEngine
|
||||
.getCompactKernelDuration();
|
||||
auto collateDuration =
|
||||
pcloudProducer.openClCollatingAndMeshingEngine
|
||||
.getCollateKernelDuration();
|
||||
std::cout << std::put_time(std::localtime(&logTime), "%T")
|
||||
<< '.' << std::setfill('0') << std::setw(3)
|
||||
<< logSubsecMs.count() << ' '
|
||||
<< __func__ << ": stage durations: assembly="
|
||||
<< assemblyDuration.count()
|
||||
<< "ms, compactKernel=" << compactDuration.count()
|
||||
<< "ms, collateKernel=" << collateDuration.count()
|
||||
<< "ms" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
callOriginalCallback();
|
||||
}
|
||||
@@ -748,10 +810,9 @@ void PcloudStimulusProducer::produceFrameReq(
|
||||
sscl::cps::Callback<produceFrameReqCbFn> callback)
|
||||
{
|
||||
/** EXPLANATION:
|
||||
* We shouldn't acquire the StimulusProducer::shouldContinueLock here because
|
||||
* this function is called from
|
||||
* StimulusProducer::stimFrameProductionTimesliceInd(), which is already
|
||||
* holding the lock.
|
||||
* We don't do any additional canceler-lock acquisition here because
|
||||
* callback segment methods already use stimulusProducerCanceler
|
||||
* checkpoints before running uncancelable work.
|
||||
*/
|
||||
auto caller = smoHooksPtr->ComponentThread_getSelf();
|
||||
auto request = std::make_shared<ProduceFrameReq>(
|
||||
|
||||
Reference in New Issue
Block a user