Some more questions regarding Mqueue.

Strolling along the sea shore on the sunny day I think I’ve found a
peculiar way of using the Mqueue to the full advantage in my project.

I have a message receiving process which is activated by an IRQ proxy.
The process is the while() loop which begings with mq_recieve(), later on
in the loop, under some conditions, it may decide to mq_send() to the same
queue it is reading from, marking the message with the highest priority.
It exits the while() loop waiting for the next IRQ proxy.

All other senders to the queue are allocated with message priorities less
than the maximum.
And additionally - they are running on a lesser priorities than the
receiver.

Am I guaranteed that on the next execution of the said loop (because of
IRQ proxy) it will mq_receive() the data it had last sent there?
Will it mq_receive() it’s own messages while in the while() loop? (It may
decide to send itself a message more than once.) Does this depend on the
relative priorites of the Mqueue server and the receiving process?

(I see that Mqueue is by default on “10o” priority level, the receiver is
considered to be a driver process and may be somewhere around level 15~19.)

Am I at any risk of the deadlock? May the mq_send() from the while() loop
block because some other sender (though running on a lower priority than
my driver) managed to post a message in the queue making it full again?

Please comment.

Tony.

PS If it really works as I think - it may save me a lot of logic both in
the driver and the senders.
The expected behaviour is to repeat some messages if some conditions were
true. It is also expected to begin the next run with the same (repeated)
message intentionally left (sent by my driver, actually) in the queue from
the last run.
I expect the queue to have a free slot to mq_send() to for my driver
because of the previous mq_receive() there.

May be I should exit the loop if there are no pending messages in the
queue so that mq_receive() never blocks…
Should I reexecute mq_receive() if it returned EINTR? Will I have to merge
the two parts of the INTRupted message?

There is the flow chart here, have a look, please.

:slight_smile:

Tony <mts.spb.suxx@mail.ru> wrote:

Strolling along the sea shore on the sunny day I think I’ve found a
peculiar way of using the Mqueue to the full advantage in my project.

Life sounds rough. :slight_smile:

I have a message receiving process which is activated by an IRQ proxy.
The process is the while() loop which begings with mq_recieve(), later on
in the loop, under some conditions, it may decide to mq_send() to the same
queue it is reading from, marking the message with the highest priority.
It exits the while() loop waiting for the next IRQ proxy.

All other senders to the queue are allocated with message priorities less
than the maximum.
And additionally - they are running on a lesser priorities than the
receiver.

Am I guaranteed that on the next execution of the said loop (because of
IRQ proxy) it will mq_receive() the data it had last sent there?

There isn’t enough information provided to answer this question.

If nowhere in that loop between the mq_receive() and the mq_send() does
it make a blocking call, then the new message will go in to the (still
available) slot in the queue because no other process will get to run,
and when the mq_send() is done, because your process is higher priority
than any of the others trying to send to Mqueue, your send will be
received first.

But, if you do anything that might result in a blocking call, then you
risk someone else using up that queue entry, because Mqueue or another
process may get a chance to execute.

And, what does a blocking call can be quite subtle – e.g. one of the easiest
to miss is a call to printf().

Will it mq_receive() it’s own messages while in the while() loop? (It may
decide to send itself a message more than once.) Does this depend on the
relative priorites of the Mqueue server and the receiving process?

If it does an mq_send() and then an mq_receive() on the same queue, it
should receive its own message. I have not actually tested this, but
can think of no reason it should not do so.

(I see that Mqueue is by default on “10o” priority level, the receiver is
considered to be a driver process and may be somewhere around level 15~19.)

If you check a “sin -PMqueue flags” you will see that the priority for
Mqueue is float, so it will actually rise to the priority of the Send()er.
In this case, it will rise to meet your priority in order to handle your
sending on the queue and/or receiving on the queue (since both are, actually,
QNX Send() calls.)

Am I at any risk of the deadlock? May the mq_send() from the while() loop
block because some other sender (though running on a lower priority than
my driver) managed to post a message in the queue making it full again?

You are at a risk of a deadlock if you make any blocking call between the
point where you do an mq_receive() and the following mq_send() that you
expect to use the just-been-made-available queue entry.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

On Mon, 30 May 2005 20:57:54 +0400, David Gibbs <dagibbs@qnx.com> wrote:

… what does a blocking call can be quite subtle – e.g. one of the
easiest to miss is a call to printf().
Is there a chance of blocking in these:

(void)time(&t1); /* store current UTC calendar time into t1 /
tm = gmtime(&t1); /
convert it into structure as UTC still */

tm->tm_isdst = -1; /* let OS determine if it is DST in action /
t2 = mktime™; /
convert the structure into LOCAL timezone as t2 /
/
I’ve called them as “do something neutral” on the flow chart */

All other code is mostly busy with the received data contents.

Tony.

Tony <mts.spb.suxx@mail.ru> wrote:

On Mon, 30 May 2005 20:57:54 +0400, David Gibbs <> dagibbs@qnx.com> > wrote:
… what does a blocking call can be quite subtle – e.g. one of the
easiest to miss is a call to printf().
Is there a chance of blocking in these:
(void)time(&t1); /* store current UTC calendar time into t1 */

I think this one would be a Send() to Proc to get the time. So, yup, possible
SEND and REPLY blocked states. But, Proc shouldn’t keep you blocked for
any period of time, it should reply to this immediately, so you would
probably be ok.

A hack that works around this risk:

Do this as setup, outside the loop:

struct _osinfo osdata;
volatile struct _timesel far *tptr;

/* get a pointer to the memory which the kernel updates every tick */
qnx_osinfo( 0, &osdata );
tptr = MK_FP( osdata.timesel, 0 );

Then, instead of the time() call:

t1 = tptr->seconds;

The rest of these would, I think, operate fully in local memory, and
not make any kernel calls – blocking or non-blocking.

tm = gmtime(&t1); /* convert it into structure as UTC still /
tm->tm_isdst = -1; /
let OS determine if it is DST in action /
t2 = mktime™; /
convert the structure into LOCAL timezone as t2 /
/
I’ve called them as “do something neutral” on the flow chart */

All other code is mostly busy with the received data contents.

Tony.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com