Skip to content

Commit

Permalink
[Decode] Prevent mt read/write conflict
Browse files Browse the repository at this point in the history
Two concurrent DdiMedia_SyncSurface function calls read and
write the same data when the second frame uses the first frame
as a reference frame.
Enqueue frames order:
  Frame #0
  Frame intel#1 (uses #0 as a reference)
Threads release order:
  Thread intel#1 (waits for Frame intel#1)
  Thread #0 (waits for Frame #0)
Resolution is lock with the mutex the problem source code
(read and update StatusReport), so only one thread writes
the data, the second thread is waiting.
  • Loading branch information
maksenox committed May 8, 2019
1 parent 2ea601b commit 807b404
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
5 changes: 2 additions & 3 deletions media_driver/linux/common/ddi/media_libva.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3289,6 +3289,8 @@ static VAStatus DdiMedia_SyncSurface (
PDDI_DECODE_CONTEXT decCtx = (PDDI_DECODE_CONTEXT)surface->pDecCtx;
if (decCtx && surface->curCtxType == DDI_MEDIA_CONTEXT_TYPE_DECODER)
{
DdiMediaUtil_LockGuard guard(&mediaCtx->SurfaceMutex);

Codechal *codecHal = decCtx->pCodecHal;
DDI_CHK_NULL(codecHal, "nullptr decCtx->pCodecHal", VA_STATUS_ERROR_INVALID_CONTEXT);

Expand Down Expand Up @@ -3335,7 +3337,6 @@ static VAStatus DdiMedia_SyncSurface (

if ((tempNewReport.m_codecStatus == CODECHAL_STATUS_SUCCESSFUL) || (tempNewReport.m_codecStatus == CODECHAL_STATUS_ERROR) || (tempNewReport.m_codecStatus == CODECHAL_STATUS_INCOMPLETE))
{
DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
PDDI_MEDIA_SURFACE_HEAP_ELEMENT mediaSurfaceHeapElmt = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)mediaCtx->pSurfaceHeap->pHeapBase;

uint32_t j = 0;
Expand All @@ -3355,10 +3356,8 @@ static VAStatus DdiMedia_SyncSurface (

if (j == mediaCtx->pSurfaceHeap->uiAllocatedHeapElements)
{
DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
}
else
{
Expand Down
22 changes: 22 additions & 0 deletions media_driver/linux/common/ddi/media_libva_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,28 @@ void DdiMediaUtil_LockMutex(PMEDIA_MUTEX_T mutex);
//!
void DdiMediaUtil_UnLockMutex(PMEDIA_MUTEX_T mutex);

//!
//! \brief Helper inline class intended to simplify mutex lock/unlock
//! operations primarily used as a stack-allocated object.
//! In that case, the compiler guarantees to call the destructor
//! leaving the scope. The class becomes handy in functions
//! where there are several return statements with different
//! exit code value.
//!
class DdiMediaUtil_LockGuard {
private:
PMEDIA_MUTEX_T m_pMutex;
public:
DdiMediaUtil_LockGuard(PMEDIA_MUTEX_T pMutex):m_pMutex(pMutex)
{
DdiMediaUtil_LockMutex(m_pMutex);
}
~DdiMediaUtil_LockGuard()
{
DdiMediaUtil_UnLockMutex(m_pMutex);
}
};

//!
//! \brief Destroy semaphore
//!
Expand Down

0 comments on commit 807b404

Please sign in to comment.