This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: Tiovx state mutex issue

Part Number: TDA4VM

Hi team,

Reading and writing issue of node_desc_obj->flags regarding the Lines 573 and 234 in the framework/VX_target.c file in tiovx:

Corresponds to two functions: tivxTargetNodeDescNodeMarkComplete and tivxTargetNodeDescCanNodeExecute

This code is implemented on line 573: tivxFlagBitSet(&node_obj_desc->flags, TIVX_NODE_FLAG_IS_EXECUTED)

The code near line 573 of VX_target.c (in tivxTargetNodeDescNodeMarkComplete) is as follows: 

static void tivxTargetNodeDescNodeMarkComplete(tivx_obj_desc_node_t *node_obj_desc, uint16_t *blocked_node_id)
{
    /* check if any node is blocked on this node to get unblocked and complete execution
     * This will be a node from next pipeline instance
     */
    *blocked_node_id = node_obj_desc->blocked_node_id;
    node_obj_desc->blocked_node_id = (vx_enum)TIVX_OBJ_DESC_INVALID;
    node_obj_desc->state = TIVX_NODE_OBJ_DESC_STATE_IDLE;
    tivxFlagBitSet(&node_obj_desc->flags, TIVX_NODE_FLAG_IS_EXECUTED); //my confused code
}

This code is implemented on line 234: tivxFlagIsBitSet(prev_node_obj_desc->flags, TIVX_NODE_FLAG_IS_EXECUTED)

The code near line 234 of VX_target.c (in tivxTargetNodeDescCanNodeExecute) is as follows: 

static vx_bool tivxTargetNodeDescCanNodeExecute(
    const tivx_obj_desc_node_t *node_obj_desc)
{
    tivx_obj_desc_node_t *prev_node_obj_desc;
    uint16_t prev_node_obj_desc_id;
    uint16_t i;
    vx_bool can_execute = (vx_bool)vx_true_e;

    for(i=0; i<node_obj_desc->num_in_nodes; i++)
    {
        prev_node_obj_desc_id = node_obj_desc->in_node_id[i];
        prev_node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(prev_node_obj_desc_id);

        if( tivxObjDescIsValidType( (tivx_obj_desc_t*)prev_node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
        {
            if( tivxFlagIsBitSet(prev_node_obj_desc->flags,
                        TIVX_NODE_FLAG_IS_EXECUTED) == (vx_bool)vx_false_e)  //my confused
            {
                can_execute = (vx_bool)vx_false_e;
            }
        }
    }

    return can_execute;
}

If NodeA and NodeB are present in DSP0 and DSP1 respectively, the following occurs: 

Once NodeA is complete, it will need to set the node_desc_obj->flags to TIVX_NODE_FLAG_IS_EXECUTED. NodeB is checking node_desc_obj->flags for NodeA on DSP1, and this flag for NodeA should be read at this time. 

However, the customer thinks that the two nodes are on different CPUs and that the read and write of the same target memory should be synchronized, such as mutexes with global spin_lock. But there's no mutex here. 

Mutex is not required to be locked because node_desc_obj is all share_mem of uncache, is this the case? 

Could you help check this case? Thanks.

Best Regards,

Cherry

  • Hi Cherry,

    Both the function tivxTargetNodeDescNodeMarkComplete and tivxTargetNodeDescCanNodeExecute are excecuted by the same node.

    Only after the first function is called, the second would be called.

    Here, these are called by the same node.

    For eg, Node A calls tivxTargetNodeDescNodeMarkComplete and then Node A itself calls tivxTargetNodeDescCanNodeExecute() i.e., the next node information is extracted from the Node A's object descriptor. Only after this the Node B is triggered.

    The TIOVX framework has been tested multiple times and there are customers who has gone into production with this framework. Hence, there shouldn't be an issue here.

    Regards,

    Nikhil

  • Hello, 

    I think I should explain my question clearly at first,

    my problem like the following graph:

    let's take this assumption:

    NodeA and NodeB finish their jobs at a same time point(we can assume they almost completed their work at the same time) 。

    and let's look at these two functions:

    tivxTargetNodeDescCanNodeExecute, check other's status, finished or not;

    tivxTargetNodeDescNodeMarkComplete, set self status。

    In TIOVX code, tivxTargetNodeDescNodeMarkComplete is called at the first, and tivxTargetNodeDescCanNodeExecute is called at the second。

    So, I think above two functions should be protected by some mutex/lock, such as global SPIN_lock.

    I only care where this mutually exclusive logic is located, maybe, it doesn't matter with tivxTargetNodeDescNodeMarkComplete and tivxTargetNodeDescNodeMarkComplete.

    So, Would you like to tell me where is the mutually exclusive logic in TIOVX, if it doesn't matter with tivxTargetNodeDescNodeMarkComplete and tivxTargetNodeDescNodeMarkComplete.

  • Hi Nikhil,

    Thank you for the support.

    (Xiao Wu) is the end customer and you could keep discuss this issue, please let me know if any questions.

    Thanks and regards,

    Cherry

  • Hi Xiao Wu,

    So, I think above two functions should be protected by some mutex/lock, such as global SPIN_lock

    As the node object desc. being updated are unique to each node, and node C would start executing only when all the input nodes states are made EXECUTED, there need not be a mutex/lock to protect this region.

    The ownTargetTaskMain from which this is called is created for each target.

    Regards,

    Nikhil Dasan

  • Hello, Nikhil

    thanks for your help at first

    as you said: "As the node object desc. being updated are unique to each node"

    1. node_object_desc is created on the shared memory, so, every target can read/write these memory.

    2. I found it need to check the status of other nodes, in  "tivxTargetNodeDescTriggerNextNodes"(ti-processor-sdk-rtos-j721e-evm-08_04_00_06/tiovx/source/framework/vx_target.c, line244)。 it call tivxTargetNodeDescCanNodeExecute in tivxTargetNodeDescTriggerNextNodes。

    you can check these code:

    static void tivxTargetNodeDescTriggerNextNodes(
        const tivx_obj_desc_node_t *node_obj_desc)
    {
        vx_bool can_execute;
        uint16_t i;
        tivx_obj_desc_node_t *next_node_obj_desc;
        uint16_t next_node_obj_desc_id;
    
        /* check and trigger next set of nodes */
        for(i=0; i<node_obj_desc->num_out_nodes; i++)
        {
            next_node_obj_desc_id = node_obj_desc->out_node_id[i];
            next_node_obj_desc = (tivx_obj_desc_node_t*)tivxObjDescGet(next_node_obj_desc_id);
    
            if( tivxObjDescIsValidType( (tivx_obj_desc_t*)next_node_obj_desc, TIVX_OBJ_DESC_NODE) != 0)
            {
                can_execute = tivxTargetNodeDescCanNodeExecute(next_node_obj_desc);
    
                if(can_execute == (vx_bool)vx_true_e)
                {
                    tivxObjDescSend( next_node_obj_desc->target_id, next_node_obj_desc_id);
                }
            }
        }
    }

    maybe, the other node is on other target.

    So, I'm very confused, why it is not protected by mutex.

    Maybe, I'm wrong, I don't know.

    But, I think it need to be protected if the other nodes are on other targets.