c++linuxmultithreadingraspberry-piopenmax

RPi2, OpenMAX, Deadlock


Environment

Use-case

Problem description

The first port being enabled to the Camera Input port ( Port #73 ), the port is being enabled using the “OMX_CommandPortEnable” command, as with the “OMX_CommandPortDisable” command, it is expected for the camera component to fire it’s “OMX_CALLBACKTYPE::EventHandler” event handler having “eEvent == OMX_EventCmdComplete” and “nData1 == OMX_CommandPortEnable”, however, this never happen and the application infinitely wait for the port to become enabled.

Problem Analysis

I am using std::condition_variable in conjunction with std::mutex to wait for the state change to complete, hence, OMX_CALLBACKTYPE::EventHandler updates the condition variable and calls “notify_one()” while the caller thread locks std::mutex and wait for the condition variable to be set, using this approach “OMX_CALLBACKTYPE::EventHandler” is never called ( with any argument ), and the program locks forever.
NOTE: When waiting for the condition variable the mutex is verified not to be owned, this is done by verifying (0 == std::mutex::__owner).
HOWEVER, All works fine when polling the status of the port by calling usleep and OMX_GetParameter(OMX_IndexParamPortDefinition) iteratively.

Question at hand

Why is “OMX_CALLBACKTYPE::EventHandler” triggered when polling it’s value and NOT triggered when using a conditional_variable? With windows there is the notion of APC & Alertable threads, is there any equivalent in linux? One that can explain the above mentioned?


Solution

  • My experience is that enabling a port does not issue the event callback until the port is populated with buffers. That is, the sequence is:

    If you wait for the event callback before you allocate the buffers then you will have deadlock.

    When you poll by testing OMX_PARAM_PORTDEFINITIONTYPE.bEnabled, that is going to return OMX_TRUE immediately because the spec says this member is set synchronously:

    The port shall immediately set bEnabled in its port definition structure when the port receives OMX_CommandPortEnable.

    Here's what I think is happening for you when things "work":

    You may be mistakenly thinking that it happens in this order instead:

    This makes it seem that using a condition variable somehow changes OpenMAX behavior. In actuality bEnabled and the OMX_CommandPortEnable callback aren't really reporting the same thing. I don't believe that any synchronization is necessary (or desirable) between enabling the port and allocating its buffers.