Skip to content

Commit

Permalink
usb: fix pending transfers queue pop race condition when stopping stream
Browse files Browse the repository at this point in the history
  • Loading branch information
rjonaitis committed Aug 18, 2024
1 parent c003b34 commit e17ae25
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/comms/USB/USBDMAEmulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ USBDMAEmulation::~USBDMAEmulation()
void USBDMAEmulation::AbortAllTransfers()
{
std::vector<AsyncXfer*> temp;

std::unique_lock lck{ queuesMutex };
temp.reserve(pendingXfers.size());
while (!pendingXfers.empty())
{
Expand All @@ -68,6 +70,8 @@ void USBDMAEmulation::AbortAllTransfers()
port->FinishDataXfer(async->xfer);
transfers.push(async);
}
assert(pendingXfers.empty());
assert(transfers.size() == maxAsyncTransfers);
}

std::vector<IDMA::Buffer> USBDMAEmulation::GetBuffers() const
Expand Down Expand Up @@ -107,6 +111,7 @@ OpStatus USBDMAEmulation::EnableContinuous(bool enable, uint32_t maxTransferSize
if (dir != DataTransferDirection::DeviceToHost)
return OpStatus::Success;
// For continuous transferring, preemptively request data to be transferred
std::unique_lock lck{ queuesMutex };
while (!transfers.empty())
{
AsyncXfer* async = transfers.front();
Expand All @@ -123,6 +128,7 @@ OpStatus USBDMAEmulation::EnableContinuous(bool enable, uint32_t maxTransferSize

void USBDMAEmulation::UpdateProducerStates()
{
std::unique_lock lck{ queuesMutex };
while (!pendingXfers.empty())
{
AsyncXfer* async = pendingXfers.front();
Expand All @@ -149,7 +155,7 @@ USBDMAEmulation::State USBDMAEmulation::GetCounters()
OpStatus USBDMAEmulation::SubmitRequest(uint64_t index, uint32_t bytesCount, DataTransferDirection dir, bool irq)
{
int count = 1;

std::unique_lock lck{ queuesMutex };
count = std::min(size_t(count), transfers.size());
if (!transfers.empty() && count > 0)
{
Expand All @@ -169,6 +175,7 @@ OpStatus USBDMAEmulation::SubmitRequest(uint64_t index, uint32_t bytesCount, Dat

OpStatus USBDMAEmulation::Wait()
{
std::unique_lock lck{ queuesMutex };
if (pendingXfers.empty())
return OpStatus::Success;

Expand Down
2 changes: 2 additions & 0 deletions src/comms/USB/USBDMAEmulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <cstdint>
#include <memory>
#include <mutex>
#include <vector>
#include <queue>

Expand Down Expand Up @@ -48,6 +49,7 @@ class USBDMAEmulation : public IDMA
std::queue<AsyncXfer*> transfers;
std::queue<AsyncXfer*> pendingXfers;
std::vector<Buffer> mappings;
std::mutex queuesMutex;

void AbortAllTransfers();
void UpdateProducerStates();
Expand Down

0 comments on commit e17ae25

Please sign in to comment.