2-way process communication

QNX 6.1 (patch A)

I have a process which sets up a socket for TCP communication with other
nodes (non QNX) over ethernet. It then creates two threads one which is for
sending data over ethernet and one which is for receiving over ethernet. I
would like the send thread to do something like:

// SEND_THREAD
while(1)
{
receive(); // Block until another QNX process sends data to be
sent out over ethernet
reply();
send(); // Send data out over ethernet
}

The receive thread to do something like:
// RECEIVE_THREAD
while(1)
{
recv(); // Block until data is received from ethernet
send(); // Send data to QNX process
}

The other QNX process looks something like:
// QNX_PROCESS
while(1)
{
receive(); // Block until receive_thread sends data
process_data();

send() // Send data to send_thread
}

As I understand it 2-way communication between processes like this is not
allowed because if both send() at the same time then deadlock occurs. How
can I achieve this functionality without risking deadlock?

Can I create two communication channels between the processes?
Can I receive() instead of send() in the receive_thread (and consequently
swap receive() for send() in the qnx_process) and reply() with the data?
What happens if two threads in a process are receive() blocked and a message
is sent? Can they both examine the message and act appropriately?

Any help would be appreciated.

Paul.

Paul Jones <paul.jones@bnc.ox.ac.uk> wrote:

QNX 6.1 (patch A)

You ask:

As I understand it 2-way communication between processes like this is not
allowed because if both send() at the same time then deadlock occurs. How
can I achieve this functionality without risking deadlock?

Use what we sometimes call reply-based messaging.

That is, take advantage of the fact that a MsgReply() can move data,
and move data in one direction with MsgSend() and in the other direction
with a MsgReply(), provoked by a non-blocking MsgSendPulse().

I have a process which sets up a socket for TCP communication with other
nodes (non QNX) over ethernet. It then creates two threads one which is for
sending data over ethernet and one which is for receiving over ethernet. I
would like the send thread to do something like:

// some setup, including finding each other, and registering an event for
// use with MsgDeliverEvent().

// SEND_THREAD
while(1)
{
receive(); // Block until another QNX process sends data to be
sent out over ethernet
if (data to send out over internet)
reply();
send(); // Send data out over ethernet
else (request for data)

MsgReply() from queued data

}

And… you could even make it a bit more efficent, and if you’ve just
been sent data to send out over the internet, and already have queued
data to be worked on, just put it in that Reply…


The receive thread to do something like:
// RECEIVE_THREAD
while(1)
{
recv(); // Block until data is received from ethernet
MsgDeliverEvent() // tell client there is data

// queue data internally

}

The other QNX process looks something like:
// QNX_PROCESS
while(1)
{
receive(); // Block until receive_thread sends data
if pulse from server

MsgSend() // get data

process_data();
MsgSend() // send reply
send() // Send data to send_thread
}



Can I create two communication channels between the processes?

You could – probably not needed.

Can I receive() instead of send() in the receive_thread (and consequently
swap receive() for send() in the qnx_process) and reply() with the data?

I think that is what I just suggested in more detail above. (But, with
the addition of the MsgDeliverEvent() for the notification.)

What happens if two threads in a process are receive() blocked and a message
is sent? Can they both examine the message and act appropriately?

One of them is chosen to get the message.

Any help would be appreciated.

Hope the above helps.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David,
Thanks for your help. Your reply has prompted me for some more
questions. How do I obtain the channel id for the MsgReceive() that is
waiting for the MsgDeliverEvent() pulse? Does it make a difference that the
process waiting with MsgReceive() created the process that is to deliver the
MsgDeliverEvent() pulse?

Paul.

Paul Jones <paul.jones@bnc.ox.ac.uk> wrote:

David,
Thanks for your help. Your reply has prompted me for some more
questions. How do I obtain the channel id for the MsgReceive() that is
waiting for the MsgDeliverEvent() pulse? Does it make a difference that the
process waiting with MsgReceive() created the process that is to deliver the
MsgDeliverEvent() pulse?

I skipped over the setup.

In your "2nd process, that one that worked with the data, it already
had a receive() on a channel.

So, it already had created a channel. What it would also have to do
is create a connection to its own channel, and setup a pulse event
with SIGEV_PULSE_INIT() – take a look at docs for sigevent structure.
Then it hands this off to the other process, says, “here’s my event
for notificaton”, the person stores away the event & rcvid for use
in MsgDeliverEvent.

The two processes don’t have to be related – but if one starts that
other, that can make things easier… the TCP/IP one can create a
channel first & pass the chid on the cmd line to the worker one, so
that the worker one doesn’t have to discover it.

If they’re not related, check out name_attach() and name_open() for
registering and locating a name.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.