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.

Queue

Hi

I am actually trying to understand the concept of queues from the TI-workshop lab.

void mailbox_queue(void)
{

//---------------------------------
// msg used for Mailbox and Queue
//---------------------------------
MsgObj msg; // create an instance of MsgObj named msg

//---------------------------------
// msgp used for Queue only
//---------------------------------
Msg msgp; // Queues pass POINTERS, so we need a pointer of type Msg
msgp = &msg; // init message pointer to address of msg


msg.val = 1; // set initial value of msg.val (LED state)

while(1){

msg.val ^= 1; // toggle msg.val (LED state)

Semaphore_pend(LEDSem, BIOS_WAIT_FOREVER); // wait on semaphore from Timer ISR

//------------------------------
// MAILBOX CODE follows...
//------------------------------
// Mailbox_post (???, &msg, BIOS_WAIT_FOREVER); // post msg containing LED state into the MAILBOX


//------------------------------
// QUEUE CODE follows...
//------------------------------
Queue_put(queue0, (Queue_Elem*)msgp); // pass pointer to Message object via LED_Queue
Semaphore_post (qMsgSem); // unblock Queue_get to get msg

}

}

I this example, 

msg.val is toggled and its address (pointer) is posted in the queue.

On the receiver side, the pointer is read on the queue and the corresponding value is off loaded.

But one scenario i am not able to understand is 

For Ex: 

msg.val=1 and the pointer is put on Queue_put.

On the receiver side, if the msg.val is already changed (as this structure being defined as local) to a different value before the receiver has got the msg.val this would give a wrong result?

Can some one help me understand this.

  • rambabu surada said:
    On the receiver side, if the msg.val is already changed (as this structure being defined as local) to a different value before the receiver has got the msg.val this would give a wrong result?

    In general you're right, there is the potential for msg.val to be overwritten before being read by the receiving side.  But for the workshop labs there shouldn't be any issue, since "writer" of msg.val waits long enough that it "knows" the reader has consumed the msg.val setting.

    It appears that you are quoting portions of different labs in your post, so it's hard to know exactly what the dynamics are here, but in general:
        - the msg writer writes a new msg.val and informs the LED task of the new value via Semaphore_post()
        - the msg writer then waits until a different sem gets posted before writing again, and it can know that the last msg.val was read by the led task by this time (in this case the "different sem" that's pended on by the writer is more for controlling the blink rate).

    These labs are kept simple so that the basic concepts can be more easily understood, and in the "real world" I would do things differently. One solution would be to have yet another semaphore that indicated that the msg.val had been read.  The reader posts that semaphore and the writer pends on that semaphore before proceeding to overwrite msg.val.

    Or better yet, a different solution would actually utilize the queuing mechanism and queue *different* msgs in a Queue.  The lab that you're asking about could just have well done away with the Queue altogether and have both writer and reader just use the static global msg.

    One goal of Lab 9 is to show how to use Mailboxs vs Queues.  The Mailbox carries its own storage and copies the msg to that storage, so it is safer than the Queue version but carries higher overhead.

    Regards,

    - Rob

  • Robert

    Thanks for your prompt response.

    I am actually trying to use Queues in my project.

    Based on your suggestion, I think i have to make those structures static but this would duplicate a copy in every function that i decide to declare the struct as static.

    This would leave us the concept same as for mail_box which is a copy based.

    Any other suggestions? 

  • rambabu surada said:

    I am actually trying to use Queues in my project.

    Based on your suggestion, I think i have to make those structures static but this would duplicate a copy in every function that i decide to declare the struct as static.

    This would leave us the concept same as for mail_box which is a copy based.

    Any other suggestions?

    I would need to know more about your communication goals with respect to the Queues that you want to use, in order to suggest a data architecture for you.

    With Queues there is a concept of data ownership.  Typically, one thread will allocate a data structure (that has Queue_Elem as its first element) and give it to another Task via Queue_put().  As soon as it calls Queue_put() the ownership of that data structure has been passed to the receiver (the thread calling Queue_get()).  The receiver will return from Queue_get(), and at this point that receiver thread owns the data structure.  Only the owner should ever modify the data structure (including freeing it).

    The receiver could then do any number of things with the data structure after processing it, such as:
        - Free it (using the same mechanism that the sender used to allocate, such as Memory_alloc()/Memory_free() or malloc()/free(), or even application managed allocation such as from an array of data structures)
        - Pass it back to the sender on a separate Queue (and the sender could reuse the data structure once it receives it back)
        - Pass it to another thread (thus giving up ownership to the next receiving thread)

    The allocation of the data structure could be as simple as a local stack variable in the function, but that function would still need to handle the ownership properly - as soon as it gives the local data structure to Queue_put() it has given up ownership and should not "touch" that local data structure in any way until it "knows" that the receiver has consumed it (i.e., the receiver is done with the data).  By "touch", I mean not changing the contents of the data structure, nor returning from its function which implicitly frees the data structure.

    Regards,

    - Rob