priority inversion of event?

Hi Folks,

I am using event to communicate between two threads, it seems to me that the priority of the receiving thread get inverted when the event is received even if I initiate the event with SIGEV_PULSE_PRIO_INHERIT flag. I have two threads/processes, the main process created the receiving thread and deliver event to it later on. The priority of both main and receiving thread are 94, the problem is, after receiving a event, the priority of receiving thread downgrade to 11. Here is my related code ( Most of them are just directly from the QNX doc):

/the receiving thread***********/
void receiver_thread()
{
struct _pulse pulse;

/* we need a channel to receive the pulse notification on */
chid = ChannelCreate( 0 );

/* and we need a connection to that channel for the pulse to be
delivered on */
coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );

/* find the server */
if ( (srv_coid = name_open( MY_SERV, 0 )) == -1)
{
printf(“failed to find server, errno %d\n”, errno );
exit(1);
}

/* fill in the event structure for a pulse */
SIGEV_PULSE_INIT( &msg.event, coid, SIGEV_PULSE_PRIO_INHERIT,
MY_PULSE_CODE, 0 );
msg.type = MSG_GIVE_PULSE;

/* give the pulse event we initialized above to the server for
later delivery */
MsgSend( srv_coid, &msg, sizeof(msg), NULL, 0 );

/* wait for the pulse from the server */
for( ; ; ) {
rcvid = MsgReceivePulse( chid, &pulse, sizeof( pulse ), NULL );
…/do some process/
}
}
/the end of the receiving thread/

/the main process****/
main()
{
pthread_create(NULL, NULL, (void *)receiver_thread, NULL);

/* attach the name the client will use to find us /
/
our channel will be in the attach structure */
if ( (attach = name_attach( NULL, MY_SERV, 0 )) == NULL)
{
printf(“server:failed to attach name, errno %d\n”, errno );
exit(1);
}

/* wait for the message from the client */
rcvid = MsgReceive( attach->chid, &msg, sizeof( msg ), NULL );
MsgReply(rcvid, 0, NULL, 0);

…/do some work/

/* deliver notification to client that client requested */
MsgDeliverEvent( rcvid, &msg.event );
}

/end of main thread*******/

Any hint?

Thanks!
Yicheng

Which QNX version are you using? Service Pack?

When the thread does a name_open that will end up sending a message to your main process. I’m not 100% sure but I believe the message will be coming from gns, which could cause the thread to switch to the priority of the gns.

You code as is can’t work because it’s missing a receive loop. Tthe MsgReceive of main will actually unblock when the name_open() is done by the thread and not when the MsgSend is done.

You could use the system profiler to see what is going on.

Mario, I think the message will not come from gns because name_open is called with 0 y 2nd parameter and not NAME_FLAG_ATTACH_GLOBAL, so gns is not needed because both threads runs locally.

Here is something from the docs and is in: What’s new in QNX Neutrino 6.3.0 Service Pack 1?

if you don’t want to modify the priority of the thread that receives the
pulse, specify SIGEV_PULSE_PRIO_INHERIT for the priority when you call
SIGEV_PULSE_INIT().

The driven-priority is a expected way the scheduler works. If some thread sends a message to other, the receiving thread will switch its priority to the priority of the thread which sends the message. This a normal scene.

I’ve never used this flag SIGEV_PULSE_PRIO_INHERIT, but it seems that it breaks the driven-priority normal schedule policy…

But I don’t know, really… you have to try.

There’s one “MsgReply()” missing in the main process. The following is the whole part of the main process. But I don’t believe it’s related to the priority inversion problem. Actually the priority of the receiving thread is the same as the main process (both set to 94) just before the line of "rcvid = MsgReceivePulse( chid, &pulse, sizeof( pulse ), NULL ); ", its priority changed to 11 right after it returns from the “MsgReceivePulse” function call. It has nothing to do with GNS as well.

I am using 6.3.2 service pack 3.

The problem is gone if I manually set the pulse priority to 94 in the receiving thread like this:
SIGEV_PULSE_INIT( &msg.event, coid, 94, MY_PULSE_CODE, 0 );

/main process**************/
main()
{
struct pulse_msg msg;

/* attach the name the client will use to find us /
/
our channel will be in the attach structure */
if ( (attach = name_attach( NULL, MY_SERV, 0 )) == NULL)
{
printf(“server:failed to attach name, errno %d\n”, errno );
exit(1);
}

pthread_create(NULL, NULL, (void *)receiver_thread, NULL);

/* wait for the connection message from the client */
while(msg.type != MSG_INT_PULSE_CONNECTION)
{
rcvid = MsgReceive( attach->chid, &msg, sizeof(msg), NULL );

if(rcvid == -1)
{
    mthca_err(NULL, "server:revid error, errno %d\n", errno );
    goto out;
 }

  /* name_open() sends a connect message, must EOK this */
  if (msg.hdr.type == _IO_CONNECT ) {
    MsgReply( rcvid, EOK, NULL, 0 );
  }

}

/reply to MsgSend/
MsgReply(rcvid, 0, NULL, 0);

…/do some work/

/* deliver notification to client that client requested */
MsgDeliverEvent( rcvid, &msg.event );
}

/end of main process********/

Dude, why try and guess what’s happening? The System Profiler will show you precisely what is happening, if you think there is a priority inversion then, post the screen captures from the System Profiler, and then we can discuss what’s happening…

SIGEV_PULSE_PRIO_INHERIT sets the priority of the pulse to the ORIGINAL priority of the process. Ie what it was spawned at.