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.

Problem with MSGQ_get in Worker Thread

Here is the description of the system:

Processor: c6474           BIOS: 5.33     CCSv3.3

SW structure: One BossThread and three worker Threads. Worker Threads at lower priority than BossThread.

core0: BossThread (Task) and WorkerThread0 (Task)

core1: WorkerThread1 (Task)

core2: WorkerThread2 (Task)

Each of the WorkerThreads have a MSGQ associated with it (MSGQ opened using MSGQ_open() as part of main function)

No Error reported during MSGQ_open.

WorkerThreads should pend on MSGQ_get() in a forever loop as shown below

void workerThread(void)

{

      for(; ;)

     {

          msgqStatus = MSGQ_get(WorkerMsgQueue[workerId], (MSGQ_Msg *)&msg, SYS_FOEVER);

         if(msgqStatus == SYS_OK)

           {

            }

      }

}

PROBLEM: While all the Worker Threads are behaving properly on core1 & core2, there is problem with core0 worker thread. It doesn't pend on the MSGQ_get and always return msgqStatus as 9.

I couldn't find any description of when does MSGQ_get call fails and what does status of '9' mean.

Please help.

 

Thnaks,

SBanik

  

 

 

  • MSGQ_get returns a status. Here is the definition of the return from spru403 which is shipped with BIOS in the docs directory.

    " If successful, this function returns SYS_OK. Otherwise, SYS_ETIMEOUT is returned if the timeout expires before the message is received."

    Specifically SYS_ETIMEOUT is 9. You will get 9 in the following situations:

    1. The timeout specified in the MSGQ_get() call expires without receiving a message. For example, if you use a semaphore as the notifier and pass in 100 as the timeout. If no messages are present and no messages come before the 100 clock ticks expire, the call return SYS_ETIMEOUT.

    2. There is no message present when the MSGQ_get() call is made and the notifier does not support timeout (e.g. when using SWIs). Since the notifier does not support timeouts and there are no messages, SYS_ETIMEOUT is returned. Note: the default MSGQ attrs (MSGQ_ATTRS) contains a notifier that does not support timeout. Below is the definition of MSGQ_ATTRS

    const MSGQ_Attrs MSGQ_ATTRS = {NULL,                   /* notifyHandle */
                                   (MSGQ_Pend)SYS_zero,    /* pend         */
                                   FXN_F_nop};             /* post         */

    Note: The pend function (specified in the attrs for the MSGQ_open) is only called in MSGQ_get if there are no messages in the queue.

    Please note, in general each MSGQ queue should have it's own notifier. For example, two MSGQ queues should not be given the same semaphore handle in the MSGQ_open. I mention this because someone made this mistake last week.

    Todd

  • Thanks for your input. This is how it is setup in my project.

    Please let me know if you find any violation. Thanks.

    msgqAttrs.pend = (MSGQ_Pend)SEM_pendBinary;
    msgqAttrs.post = (MSGQ_Post)SEM_postBinary;
     workerId = GBL_getProcId();

    for the BOSS Thread:

     /* Create a semaphore */
            bossSemHandle = SEM_create(0, NULL);
            msgqAttrs.notifyHandle = (Ptr)bossSemHandle;

    /* Create the boss message queue */
            msgqAttrs              = MSGQ_ATTRS;
            msgqStatus = MSGQ_open(BOSSNAME, &gBossMsgQueue, &msgqAttrs);

     

    and for the Worker Thread in the same core:

    /* Create the worker message queue */
            workerSemHandle = SEM_create(0, NULL);
            msgqAttrs.notifyHandle = (Ptr)workerSemHandle;

    msgqStatus = MSGQ_open(workerName, &gWorkerMsgQueue[workerId], &msgqAttrs);

     

  • This looks fine. One nit, you should check the return from the SEM_create's. 

  •  

    Yes, there is check for SEM_create as follows.

    /* Create the worker message queue */
            workerSemHandle = SEM_create(0, NULL);
            msgqAttrs.notifyHandle = (Ptr)workerSemHandle;

    if (msgqAttrs.notifyHandle == NULL) {
                SYS_abort("Semaphore creation failed");
            }

    I just didn't put everything here to keep it short.

    Similar check is done for Boss Thread SEM_create also.

    If this is corect, then my basic question still remains - why do I see the failure as described in my first posting?

  • Can you check the status of the MSGQ queues in KOV? It's an easy way to verify the notify for the queues are correct and also the status of them.

  • I am not sure what you mean by checking status of MSGQ queues, but I don't see any problem in KOV.

    I see there are 3 MSGQ queues associated with the core - one for BossThread, one for WorkerThread and one for Error Handler.

    For BossThread MSGQ queue, Name is boss, Msgq is 0x0000, #Msgs=0, Notify Handle =0x0, Pend Function is SYS_zero, Post_Function is FXN_F_nop

    For Worker Thread (workerX), Name is workerX, Msgq =1, #Msgs=1, NotifyHandle is 0x875F9C, Pend_Function is SYS_zero, Post_Function is FXN_F_nop

    The message in the worketr MSGQ queue shows

    # =0, Msg Id =0xFFFF, Msg Addr = 0x80480000, Msg Size = 128, PoolId =0x0, Src Msgq = 0x0000 (implying the message was from Boss, I believe)

     

     

     

  • In the boss message queue, the Notify Handle, Pend and Post functions are wrong. Given the code that opened the message queue you posted earlier, the Notify Handle should be some valid address (not zero) that corresponds to a SEM instance. The pend function should be SEM_pendBinary. The post function should be SEM_postBinary. The notifier that you have set up is for when you want to poll. If you use NULL for the attrs in the MSGQ_open, you get this setup.

     

    In the worker message queue, Pend and Post functions are wrong. The Notify Handle might be ok (look under SEM to see if this address corresponds to a SEM object.

     

    When a message is sent the post function is called after the message is placed onto the destination queue. So if the post function is FXN_F_nop, nothing is done. If the post function is SEM_postBinary, the semaphore is posted.

     

    On the receiving side, when MSGQ_get is called and there are no messages, the pend function is called. If the pend function is SYS_zero, 0 is returned from the pend call and MSGQ_get returns SYS_ETIMEOUT (regardless of the specified timeout).

     

    The defaulting of the attrs to polling can be debated. We did this to allow a message queue to be used in any threading model (HWI, SWI or TSK).

     

    Please confirm that you are setting the msgqAttrs structure up properly and not passing in NULL into all the MSGQ_open calls.

     

     

  • I see a new twist to the problem I have reported. May be there is clue in this observation and someone in TI can help me understand this. I have copied below the BossThread code that is in infinite loop pending on message in its MSGQ queue. It does MSGQ_get with pend for ever (SYS_FOREVER). Please note how I am counting number of times the msgqStatus (status returned when MSGQ_get returns) is OK (coutn is gCountMsgQStatOK) versus status not OK (count is gCountMsgQStatNOK). What I find is that the ratio of gCountMsgQStatNOK to gCountMsgQStatOK is something like 9240000:1. What it means is that the Boss Thread is not pending forever when there is no message in its MSGQ. What would cause that?

    I really appreciate your help.

    for (;;) {

           MSGQ_count(gBossMsgQueue, &gBmsgCountPre);
            msgqStatus = MSGQ_get(gBossMsgQueue, (MSGQ_Msg *)&msg, SYS_FOREVER);
           MSGQ_count(gBossMsgQueue, &gBmsgCountPost);
      

            switch(msg->msgType)
            {
                case SPDSP_IPC_MSG_ADD_CMD:

                    MultiCoreMgr_addEntry( msg->command, msg->inAddr, msg->outAddr );
               
                break;

                case SPDSP_IPC_MSG_FINISHED_CMD:

                    MultiCoreMgr_completedEntry( msg->jobId, msg->timeStarted, msg->timeEnded );
                break;

                default:
                break;
            }

            if (msgqStatus == SYS_OK)
            {
                MSGQ_free((MSGQ_Msg)msg);
                gCountMsgQStatOK++;
            }
      else
              gCountMsgQStatNOK++;
        }

  • It looks like we were posting at the same time:)

    My previous post explains why you are seeing this.

     

    One additional point, you need to check the return status of MSGQ_get before you reference msg (like you are doing in the switch statement). If the status is not SYS_OK (i.e. SYS_ETIMEOUT), do not use msg since no msg was received. The contents of msg when status is not SYS_OK is garbage.

     

    So two things:

    1. Verify the values of the attrs variable when you call MSGQ_open. I expect you are passing in NULL or not properly initialized them

    2. Check status from MSGQ_get before you reference the returned msg.

  • We were definitely writing at the same time :-)

    Thank You for your help. I think I have found the problem. When I was creating the MSGQ, this was the sequence.

    1. msgqAttrs.pend = (MSGQ_Pend)SEM_pendBinary;
    2. msgqAttrs.post = (MSGQ_Post)SEM_postBinary;

    3. msgqAttrs.notifyHandle = (Ptr)bossSemHandle;

    4. msgqAttrs              = MSGQ_ATTRS;  <-- This was the culprit I believe. This was overwriting the setup in previous steps. Now I do this step as the very first step followed by rest of the initializations of msgqAttrs and it seems to work.
    5. msgqStatus = MSGQ_open(BOSSNAME, &gBossMsgQueue, &msgqAttrs);

    Thanks again.

    SBanik