As is often the case, polling for PPS data is a bad idea. It's much better to wait for PPS data on a file descriptor, using one of the following mechanisms:
A blocking read() is the simplest mechanism. Generally, you use ionotify() if you want to combine input from file descriptors with QNX Neutrino messaging in the same process. Use select() when you're handling multiple file descriptors from sockets, pipes, serial ports, and so on. These mechanisms are described below; for examples, see Subscribers in the Examples appendix.
This behavior is atypical for most filesystems. It's done this way so that standard utilities won't hang waiting for a change when they make a read() call on a file. For example, with the default behavior, you could tar up the entire state of PPS using the standard tar utility. Without this default behavior, tar would never make it past the first file opened and read.
For more information on the ?wait option, see Pathname open options.
A typical loop in a subscriber would live in its own thread. For a subscriber that opened the object with the ?wait option, this loop might do the following:
/* Assume that the object was opened with the ?wait option No error checking in this example. */ for(;;) { read(fd, buf, sizeof(buf)); // Read waits until the object changes. process(buf); }
If you opened an object without the ?wait option and want to change to blocking reads, you can clear the O_NONBLOCK bit by using fcntl():
flags = fcntl(fd, F_GETFL); flags &= ~O_NONBLOCK; fcntl(fd, F_SETFL, flags);
or ioctl():
int i=0; ioctl(fd,FIONBIO,&i);
The PPS service implements ionotify() functionality, allowing subscribers to request notification via a pulse, signal, semaphore, etc. On notification of a change, you must issue a read() to the object file to get the contents of the object. For example:
/* Process events while there are some */ while ( ( flags = ionotify( fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, event ) != -1 ) && (flags & _NOTIFY_COND_INPUT) ) { nbytes = read(fd, buf, sizeof(buf)); if ( nbytes > 0 ) process(buf); } /* If flags != -1, the event will be triggered in the future to get our attention */
For more information, see the entry for ionotify() in the QNX Neutrino C Library Reference.
The select() function examines a set of file descriptors to see if they're ready for reading or writing. To use select() with PPS, set up an fd_set that includes the file descriptor for the PPS object. You can optionally set a time limit. For example:
FD_ZERO( &readfds ); FD_SET( fd, &readfds ); switch ( ret = select( fd + 1, &readfds, NULL, NULL, &timeout ) ) { case -1: /* An error occurred. */ break; case 0: /* select() timed out. */ break; default: if( FD_ISSET( fd, &readfds ) ) { num_bytes = read( fd, buf, sizeof(buf) ); if (num_bytes > 0) process(buf); } }
For more information, see the entry for select() in the C Library Reference.