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.

A question about critical section

Hi,

   I am working on K2K platform. I need to use QMSS which is shared by 8 DSP cores and each core has multi threads. I found one example code which is showed below.

Void* Osal_qmssAccCsEnter (Void)
{
/* Get the hardware semaphore.
*
* Acquire Multi core QMSS synchronization lock
*/
while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0);

/* Disable all interrupts and OS scheduler.
*
* Acquire Multi threaded / process synchronization lock.
*/
coreKey [CSL_chipReadDNUM ()] = Hwi_disable();

return NULL;
}

Say that I have 2 tasks: Task_1 which has lower priority than Task_2. If Task_1 got  QMSS_ACC_HW_SEM and Task_2 is triggered before Hwi_disable(), and Task_2 will call this function also, there will be a deadlock.

My question is that how this code prevent there won't be an interrupt between CSL_semAcquireDirect (QMSS_ACC_HW_SEM) and Hwi_disable()?

  • Hi,

    Thanks for your post.

    In Osal_qmssAccCsEnter() API, acquiring the hardware semaphore "while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0)" and acquiring multi process synchronization lock doesn't happen at different instances. I mean, acquiring synchronization lock only happens at only one instance while getting the hardware semaphone as "while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0)", then there could be no chance of interrupt between CSL_semAcquireDirect (QMSS_ACC_HW_SEM) and Hwi_disable(). Also, this API ensures multi-core synchronization between multiple tasks trying to access QMSS shared library at the same time and it acquires synchronization lock task by task basis at one instance which means, no other tasks can be triggered unless one task is locked at one instance.

    So, there would be no chances of your situation arised by your post above. Also, the API Osal_qmssAccCsExit() needs to be called to exit a previously acquired critical section lock using  Osal_qmssAccCsEnter () API which does passes the handle argument for unlocking critical section. It resets the multi-core and multi-threaded lock, enabling another process/core to grab QMSS access.

    Unfortunately, I could see the usage of qmssAccCsEnter() & Osal_qmssAccCsExit() API's in any of the QMSS example projects or test project under pdk of MCSDK 3.0 for K2K platform.

    For more details, please refer the Mulitcore Navigator User's Guide as below;

    http://www.ti.com/lit/ug/sprugr9f/sprugr9f.pdf

    I think, you could refer qmssExampleProject as well as qmssTestProject available under pdk of MCSDK 3.0. The example project would be better for a reference design, you can reuse most of that code in your application

    Are you using your own code to use these API's and could you please elloborate your use case scenarios on the usage of these API's?

    Could you please locate the source file path from where you taken these API's and your code where you used this API's for what usecase?

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sivaraj,

       Thanks for your response.

       In Osal_qmssAccCsEnter() API, acquiring the hardware semaphore "while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0)" and acquiring multi process synchronization lock doesn't happen at different instances.

        What do you mean different instances here? Say that I have 2 tasks: task_1 uses FFTC_1 and task_2 uses FFTC_2 and both of them need to use qmss, is it possible that both of them are trying to call the function Osal_qmssCsEnter()? Same question for other functions i.e. Osal_cppiCsEnter().

        I mean, acquiring synchronization lock only happens at only one instance while getting the hardware semaphone as "while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0)", then there could be no chance of interrupt between CSL_semAcquireDirect (QMSS_ACC_HW_SEM) and Hwi_disable().

        How can you prevent the interrupt here? Is there any tricky stuff I don't know?

        I am using the MCSDK code and I don't want to write the code which TI supplied already. This API function I put comes from FFTC examples and AIF2 examples.

       I will design a case which uses all the 8 cores and each core need to operate FFTCs, AIF2 and also communications among the cores. Each core will have multi threads.

        I want to make it clear what happens for these OSAL functions since I met some problem when I worked on FFTC and used the API Osal_cppiMalloc() I copied from AIF2, it didn't work.

        The function used by AIF2 example is :

     void* Osal_cppiMalloc (Uint32 num_bytes)

    {
    void* dataPtr = NULL;

    /* Allocate a buffer from system heap */
    dataPtr = malloc(num_bytes);

    if (dataPtr == NULL) printf("CPPI malloc issue\n");

    return (dataPtr);
    }

      And used by FFTC example is:

        

    Void* Osal_cppiMalloc (UInt32 num_bytes)
    {
    Error_Block errorBlock;
    Void* dataPtr;

    /* Increment the allocation counter. */
    fftcCppiMallocCounter++;

    /* Allocate a buffer from the default HeapMemMp */
    if (SharedRegion_getHeap(0) != NULL)
    {
    dataPtr = Memory_alloc ((xdc_runtime_IHeap_Handle) SharedRegion_getHeap(0), num_bytes, 0, &errorBlock);
    }
    else
    {
    #ifdef FFTC_TEST_DEBUG
    Fftc_osalLog ("CppiAlloc Failed for size: %d \n", num_bytes);
    #endif
    return NULL;
    }

    #ifdef FFTC_TEST_DEBUG
    Fftc_osalLog ("CppiAlloc DataP: %p size: %d \n", dataPtr, num_bytes);
    #endif

    return dataPtr;
    }

     

    Thanks!

  • Hi,

    Thanks for your update.

    I mean to say, two tasks as you mentioned above which are not possible to enter at the same time instance t1 and acquire synchronization lock. Actually, based on task priority, each task would enter this API Osal_qmssAccCsEnter() seperately and acquire the multi-threaded synchronization lock only at the time when it gets the hardware semaphore. So, there wouldn't be any chance for the particular task to trigger before disabling the interrupts and by this way, the above code prevents an interrupt between CSL_semAcquireDirect (QMSS_ACC_HW_SEM) and Hwi_disable(). This is because, getting the hardware semaphore and acquiring the synchronization lock happens at same time instance t1 and not at different time instances t1 & t2.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sivara,

        Thanks for your explanation!

       Sorry that I couldn't understand. You mentioned t1, I think t1 is not a specific cycle it includes several cycles. Since getting the QMSS_ACC_HW_SEM and  disable interrupt is not an atom operation I can't understand why Tsk_2 has no chance to run in the between of these 2 operation.

    Following the previous assumption, say that Tsk_1 has LOW priority and Tsk_2 has HIGH priority.    The current status is that Tsk_1 is calling the function Osal_qmssAccCsEnter() and get the QMSS_ACC_HW_SEM.

       Is it possible that the core gets an interrupt and the scheduler switches to Tsk_2 ?

                If not, why the core doesn't response the interrupt and switch to Tsk_2 since interrupt is enabled at the current time and Tsk_2 has the HIGH priority.

               If yes, Tsk_1 will pend and Tsk_2 will run, Tsk_2 can call Osal_qmssAccCsEnter(), of course it can't get the QMSS_ACC_HW_SEM, then the thing   happens Tsk_1 holds QMSS_ACC_HW_SEM and Tsk_2 holds Core, which is deadlock.

    I hope my question is clear now.

    BTW: I know this case has very low probability to happen if it can.

    /Zijun

  • Hi,

    Thanks for your update.

    Only through disabling all interrupts, you could achieve multi-core synchronization between multiple tasks trying to access QMSS shared library at the same time and that is why, this API "Osal_qmssAccCsEnter()"  is ensured for. Then how could it has the possibility for the core to get an interrupt when it acquired synchronization lock between tasks scheduled. So, the core will not respond to the interrupt when it is in synchronization lock across tasks.

    Hope it clears.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sivaraj,

       Thanks for your feedback.

       I agree with you that:

      1) this API "Osal_qmssAccCsEnter()"  is intended for locking the critical region.

     2) Only through disabling all interrupts, you could achieve multi-core synchronization between multiple tasks trying to access QMSS shared library at the same time.

     3) when it acquired synchronization lock no other interrupt and tasks can be scheduled.

     My question is the implementation of the function   "Osal_qmssAccCsEnter()":

    Void* Osal_qmssAccCsEnter (Void)

    {

       while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0);

       coreKey [CSL_chipReadDNUM ()] = Hwi_disable();

       return NULL;

    }

     How this function can meet the purpose?  As you said only through disable all interrupts, but after get the QMSS_ACC_HW_SEM, the interrupt is still in enable state. So I can't understand how it can prevent the interrupt and task switch after while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0); and before  coreKey [CSL_chipReadDNUM ()] = Hwi_disable();

    Thanks!

    /Zijun

  • Hi,

    Thanks for your update.

    How do you say that, after getting the QMSS_ACC_HW_SEM, the interrupt is still in enable state? It is never possible since getting the hardware semaphore QMSS_ACC_HW_SEM & acquiring the multi threaded synchronization lock happens at exactly same time. Then there won''t be any situation to prevent the interrupt and task switch.

    Actually to get the hardware semaphore, it keeps waiting for the flag to set in while loop as 'while ((CSL_semAcquireDirect (QMSS_ACC_HW_SEM)) == 0)" and once it sets, it will acquire the multi threaded synchronization lock at the same time.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sivaraj,

       Thanks for your response.

        The reason why I said the interrupt is still in enable state after the Task gets the QMSS_ACC_HW_SEM is based on the code. That's the reason why the code disables the interrupt after gets the QMSS_ACC_HW_SEM.

        You mentioned they happens at the same time, that's the thing I couldn't understand how do you define "the same time". My understanding the same time means the same clock cycle or some atomic operation, I can't see either of them based on my knowledge.

        Thanks!

    /Zijun