Pulse

Message and pulse are QNX native IPC, no POSIX/UNIX.
Usually, message passing is synchronous:  after MsgSend(), the client blocks(send-blocked, or reply-blocked) until the server gets around to replying.
If you want asynchronous messaging,
  1. if you need to transfer data
    1. Have the server dedicate a thread to receive and immediately reply messages, minimizing the blocking interval.
    2. Have the client send the data via a thrad
    3. Use POSIX message queue
  2. If you don’t need to transfer data
    1. Posix signal
    2. pulse
Pulse is asynchronous. Pulse makes “a non-blocking send” possible, which works for the scenario where senders can’t afford to block.
Pulse has fixed payload size (32 bit value, 8 bit code)
Pulse initialization/send/receive
  • SIGEV_PULSE_INIT(&event, coid, priority, pulse_code, pulse_value);
    • If you want the thread that receives the pulse to run at the initial priority of the process, set priority to SIGEV_PULSE_PRIO_INHERIT.
  • Int MsgSendPulse(coid, priority, pulse_code, pulse_value)
  • Int MsgRecivePulse(chid, &pulse, sizeof(pulse), struct _msg_info *info);  // info should be NULL for pulse.
  • Int MsgReceive(chi, &msg, bytes, struct _msg_info *info);       // a return of “0” means a pulse is received; if >0, a normal message.

Priority Inversion: a low-piority thread consumes all available CPU time, even though a higher-priroity thread is ready to run.

To avoid it, the solution is Priority inheritance, or Message-driven priority: A server process receives messages & pulses in priority order. the receiving thread within the server process inherits the priority of the sender thread; when it receives messages (for pulses, receiving thread will run at the priority of the pulse).

Assume there are 3 threads, t1 (priority 13), t2 (priority 10), server thread (priority 22),

  • If the sender(t2) is of lower priority (10) than the receiver (22), the effective priority of the server thread changes when the message is received (on MsgReceive).
    • the sender(t2)’s work is done at priority 10.
    • If another higher priority thread(t1) is running when t2 calls MsgSend(), it will not preempted by t2.
  • If the sender(t1) is of higher priority(13) than the receiver(10), the effective priority of the server thread changes on MsgSend().
    •  If multiple clients are SEND blocked, server will inherit the priority the higher client.
  • After the server reply to t1 and t2, its priority will still be 13, and receive blocked.
 Note
  • Priority inheritance can be turned off by channel flag _NTO_CHF_FIXED_PRIORITY. If the channel is created with _NTO_CHF_FIXED_PRIORITY, receiving threads won’t change priorities to those of the sending threads (does it work for pulses???)
  • For pulses (an example of pulse priority)
    • Pulse have a priority value while being initialized. If you want the thread that receives the pulse to run at the initial priority of the process, set sigev_priority to SIGEV_PULSE_PRIO_INHERIT (note: not the priority of the thread which sends the pulse, but the initial priority of the process!???)
    • Sender can specify the priority of the pulse, or –1 to use the priority of the calling thread.
Example
#include <sys/neutrino.h>
#include <sys/netmgr.h>
#define MY_PULSE PULSE_CODE_MINAVAIL+2
 
int chid = ChannelCreate(unsigned flags);
Int coid = ConnectAttach(node_id, pid, chid, 0 | _NTO_SIDE_CHANNEL, flags);
Struct sigevent event;
SIGEV_PULSE_INIT(&event, coid, prio, MY_PULSE, NULL);
In a thread,
struct _pulse pulse;
If(MsgReceivePulse(chid, &pulse, sizeof(pulse), NULL) != -1) {  //similar to MsgReceive(), but only receives pulses.
    Switch(pulse.code) {
        Case MY_PULSE:
        Break;
    Default:
        …..
    }
}
In the other thread,
MsgSendPulse(coid, -1, MY_PULSE, 0);
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s