io_notify, MsgDeliverEvent or something else ?

Hi all,

I am writing a small resource manager (RM) and I need to notify my clients if ‘A’, ‘B’, ‘C’ or ‘D’ happened within the RM.

There are a couple of optios here to notify the client namely:
io_notify()
MsgDeleliverEvent()
kill()

I would like to use io_notify but I am having problems implementing it. Does someone have a pointer where to find some details how to implement io_notify on the RM side? Can I use io_notify to tell the clients what exactly happened (A, B, C or D) in the RM or does io_notify tell me that something happened and that I need to check back if it was A, B, C or D.

TIA,
Freddy

This is all based on the “Handling ionotify() and select()” section of the “Writing a Resource Manager” topic in the Neutrino Programmers Reference (http://www.qnx.com/developers/docs/momentics621_docs/neutrino/prog/resmgr.html#HANDLING_ionotify).

  1. Add an “iofunc_notify_t events[3]” to your extended OCB structure to keep track of what each client has requested to be notified for (sys/iofunc.h defines these 3 entries as IOFUNC_NOTIFY_INPUT, IOFUNC_NOTIFY_OUTPUT and IOFUNC_NOTIFY_OBAND).

  2. Install a “notify” handler in the resmgr_io_funcs_t structure.

  3. In your ocb_calloc handler (installed when you call iofunc_func_init()):

IOFUNC_NOTIFY_INIT(ocb->events); for( int ii=0; ii<3; ii++) ocb->events[ ii].list = NULL; Your notification events will now be initialized and unarmed.

  1. Your clients will make calls to “ionotify()” to tell your RM what type of event they are interested. The flags passed to ionotify() can be one of _NOTIFY_COND_INPUT, _NOTIFY_COND_OUTPUT or _NOTIFY_COND_OBAND (corresponding to the defines from sys/iofunc.h listed in step1 above). You may have to get creative with how you use these flags as there are only 3 defiined and you have 4 types of events.

  2. Inside your “notify” handler (mentioned in step 2 above and called in response to a client’s ionotify() call) you will need to call iofunc_notify() so the res manager library can setup the notification structures inside the OCB.

  3. Now, your RM simply has to know when one of the desired events has occurred and do the following:

if( IOFUNC_NOTIFY_INPUT_CHECK(ocb->events, (int)len, 0)) iofunc_notify_trigger(ocb->events, len, IOFUNC_NOTIFY_INPUT); if( IOFUNC_NOTIFY_OUTPUT_CHECK(ocb->events, (int)len, 0)) iofunc_notify_trigger(ocb->events, len, IOFUNC_NOTIFY_OUTPUT); if( IOFUNC_NOTIFY_OBAND_CHECK(ocb->events, (int)len, 0)) iofunc_notify_trigger(ocb->events, len, IOFUNC_NOTIFY_OBAND);This is where the notification actuall yoccurrs by delivering the sigevent structure (specified by the client in his call to ionotify()) back to the client. The len argument tells the res manager library how many “items” are “armed” (i.e. how many bytes are available for reading from a serial port. Not sure what your application will use here).

  1. Don’t forget to call iofunc_notify_remove() when the client closes his connection.
    Hope this helps (and that I did not forget anything).

If I am not mistaking, iofunc_notify_trigger is actually a MsgDeliverEvent. The event structure withing iofunc_notify_t is passed to the client right. Can I manipulate the event structure before calling iofunc_notify_trigger() ?

TIA,
Freddy

That is correct: iofunc_notify_trigger is indeed just a wrapper for MsgDeliverEvent. The upper nibble (4 bits) of the sigevent code gets manipulated inside iofunc_notify_trigger (for pulses, signals and thread type sigevent structs). So you should be able to modify the lower 28bits of the sigevent code if you need to.

and in the MsgReceive loop I need to remove the upper 4 bit to obtain my value right?.

Well, I’ll fiddle around to get it working.

thanks,
Freddy

I don’t think you need to remove the upper 4 bits (think this is done automatically for you).

You could always do what I did and look at the source for iofunc_notify_trigger() in cvs.qnx.com. It may be a little out of date, but it does a better job of explaining it than the docs - in the same way that source is always the ultimate documentation. ;-)

Rick…

lol…that’s exactly what I did. Must be that great minds really do think alike…

Thank you both for showing me the path to the proper documentation ;-)

Freddy

Hurm, having problems finding it. Rick do you have a pointer to the location ?

Freddy

cvs.qnx.com/cgi-bin/cvsweb.cgi/l … web-markup

Thanks mate, it works ;-)

Hi,

I’m not able to receive the ionotify events through MsgReceive(). I need to look into it a little further.

Freddy

Hi all,

This is what I do in the client:

// Set up the event structure for pulse messages
SIGEV_PULSE_INIT( &event, coid, 15, PULSE_CODE, 0);

// Re-register for notifications of received data
if((status = ionotify( fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event)) == -1)
{
	printf( "ionotify() failed: %s\n", strerror( errno));
}
else if( status & _NOTIFY_COND_INPUT)
{
	// Send a pulse to our channel
	MsgSendPulse( event.sigev_coid, event.sigev_priority,  event.sigev_code, event.sigev_value.sival_int+1);
}

In a thread, a MsgReceive is wating for pulses.

In my server, I do everything according to the QNX docs.
I am calling io_notify trigger() where len is set to any value.

In my client, I am not reveiving pulses from the server. Is there something I forgot ?

I need to call ionotify once right, to “register” for a recurring event?

Does anyone have a clue?

To change the value it did: (list[0] is for testing)
dattr->notify[0].list[0].event.sigev_value.sival_int = 111;

What am I doing wrong?

Cheers,
Freddy

Hi all,

I solved my problem and I am posting my answer here for others to use.

In the main thread, I did:

// Create a channel to receive messages on.
chid = ChannelCreate(0);

// Connect to the channel to send messages on.
coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0);

// Start a thread dedicated to receive pulses and setting up
    // ionotify
pthread_create(&tid, NULL, process_IPC, NULL);

// Set up the event structure for pulse messages
SIGEV_PULSE_INIT( &event, coid, 15, PULSE_CODE, 0);

// Register for notifications of received data
if((status = ionotify( fd, _NOTIFY_ACTION_TRANARM, _NOTIFY_COND_INPUT, &event)) == -1)
{
	printf( "ionotify() failed: %s\n", strerror( errno));
}

The thread looks like:
void* process_IPC (void *arg)
{
int rcvid = 0;
int status = 0;
struct _pulse pulse;
static long events = 0;

for (; ; ) 
{
	rcvid = MsgReceive(chid, &pulse, sizeof(pulse), NULL);
	if (rcvid != 0)
	{
		printf("Received a message\n"	);
	}
	if (rcvid == 0)
	{
		if (pulse.code == PULSE_CODE) 
		{
			printf("%ld: we got notified by the driver: event# %d occured\n", events++, pulse.value.sival_int);
			if((status = ionotify( fd, _NOTIFY_ACTION_TRANARM, _NOTIFY_COND_INPUT, &event)) == -1)
			{
				printf( "ionotify() failed: %s\n", strerror( errno));
			}
		}
	}
}	

}

I hope this is usefull to others.

Hereby, I want to thank Rick and RoverFan for their help.

Cheers,
Freddy