3

We have a vxWorks design which requires one task to process messages from two message queues, Q1 & Q2.

We would like to wait on both Queues and whichever gets a message, process the message from the queue.

We want to avoid either polling the queues or using a timeout value which could cause the other queue to fill up.

Is there a way to do this?

Benoit
  • 37,894
  • 24
  • 81
  • 116
  • If they have to be handled FIFO, why are there two queues? Surely one queue is the better solution. And, if they're being handled FIFO, what does the concept of high and low priority mean (highs can't bypass lows in FIFO)? – paxdiablo Sep 23 '08 at 12:29
  • Message from 14 years in the future: There's a high priority queue and a separate low priority queue. This pattern is very common. – Cozmo Feb 25 '22 at 19:08

2 Answers2

3

If you use named pipes (pipeDevCreate(), write(), read()) instead of message queues, you can use select() to block until there are messages in either pipe.

Whenever select() triggers, you process all messages in the high priority pipe. Then you process a single message from the low priority pipe. Then call select again (loop).

Example Code snippets:

 // Initialization: Create high and low priority named pipes
 pipeDrv(); //initialize pipe driver
 int fdHi = pipeDevCreate("/pipe/high",numMsgs,msgSize);
 int fdLo = pipeDevCreate("/pipe/low",numMsgs,msgSize);

 ...

 // Message sending thread: Add messages to pipe
 write(fdHi, buf, sizeof(buf));

 ...

 // Message processing Thread: select loop
 fd_set rdFdSet;

 while(1)
 {
     FD_ZERO(&rdFdSet);
     FD_SET(fdHi, &rdFdSet);
     FD_SET(fdLo, &rdFdSet;

     if (select(FD_SETSIZE, &rdFdSet, NULL, NULL, NULL) != ERROR)
     {
         if (FD_ISSET(fdHi, &rdFdSet))
         {
             // process all high-priority messages
             while(read(fdHi,buf,size) > 0)
             {
                 //process high-priority
             }
         }

         if (FD_ISSET(fdLo, &rdFdSet))
         {
             // process a single low priority message
             if (read(fdLo,buf,size) > 0)
             {
                 // process low priority
             }
         }
     }
 }
JayG
  • 4,339
  • 3
  • 23
  • 19
1

In vxWorks, you can't wait directly on multiple queues. You can however use the OS events (from eventLib) to achieve this result. Here is a simple code snippet:


MSG_Q_ID lowQ, hiQ;

void Init() {
// Task Initialization Code.  This should be called from the task that will
// be receiving the messages
...
hiQ = msgQCreate(...);
lowQ = msgQCreate(...);
msgQEvStart(hiQ, VX_EV01);  // Event 1 sent when hiQ receives message
msgQEvStart(loQ, VX_EV02);  // Event 2 sent when loQ receives message
...
}
void RxMessages() {
...
  UINT32 ev;   // Event received

   // Blocks until we receive Event 1 or 2
   eventReceive(VX_EV01 | VX_EV02, EVENT_WAIT_ANY, WAIT_FOREVER, &ev);
   if(ev & VX_EV01) {
      msgQReceive(hiQ, ...);
   }
   if(ev & VX_EV02) {
      msgQReceive(loQ, ...);
   }
}

Note that you need to modify that code to make sure you drain all your queues in case there is more than one message that was received.

The same mechanism can also be applied to Binary semaphores using the semEvStart() function.

Benoit
  • 37,894
  • 24
  • 81
  • 116
  • I have a nagging feeling that this can allow a lo msg to be processed before a hi one, but don't know VxWorks so can't prove it. What happens if, while you're processing a lo msg, another lo msg and then a hi msg are added to your queues? – Steve Jessop Sep 23 '08 at 13:21
  • I guess as long as you get a combined EV01 + EV02 event it's fine, and there are only natural races. Is that what VxWorks does? – Steve Jessop Sep 23 '08 at 13:23
  • The example given wouldn't exactly match the spec, as you could do a lo msg when there are still hi msg left. You need to add a loop to process the hi msgs. That's what I meant by "drain" the queue. – Benoit Sep 23 '08 at 13:53
  • Seems like you answering your own questions!? – JayG Sep 30 '08 at 21:52
  • @JayG See http://stackoverflow.com/questions/86634/so-frequent-question-asker-and-answerer These are all questions that came from classes I teach. – Benoit Sep 30 '08 at 22:18