On Wed, Apr 02, 2008 at 03:27:55AM -0400, Mario Charest wrote:
> > We have an application which works under linux, but not qnx6. It talks to a
> > number of serial ports (max 16) and waits on a select for a port to receive
> > data. Each data packet is 12 bytes in length, and is binary data. Data rate
> > is 38k4 and running at full data rate. We set vmin to 12 in order that the
> > select doesn't get triggered before 12 bytes are available.
> > This works under linux, but under qnx6 the select always triggers on the first
> > byte, not the 12th as it should do. Consequently if O_NONBLOCK is set then
> > EAGAIN is returned on the subsequent read or if O_NONBLOCK is clear then the
> > read blocks until all the data is in or forever if the sending end aborts.
> > Setting vtime overrides vmin so can't be used and the timeout is too long for
> > us anyway.
> > Attached is a sample program we are using to test this compiled on linux with
> > ntox86-gcc -o testselect-q testselect.c
> >
> > Any ideas? It appears to us that the character/select interface is broken.
>
>
> Don't know about select and vmin stuff, can't help you there. here is what I would. Start a thread for each serial
port and use readcond(). This is more efficient then using select which add extra context switch and message passing.
>
> The parsing of the data can be handle by the thread. If you have more then 1 core, you'll get better performance/
througput.
This should work though. I've made PR 56779 on this. Here's
another self contained test case.
-seanb
#include <err.h>
#include <termios.h>
#include <unix.h>
#include <errno.h>
#include <pthread.h>
#include <sys/poll.h>
#define OURVMIN 4
int
main(void)
{
int master, slave, vmin, ret;
struct termios tiold, tinew;
char buf[OURVMIN];
struct pollfd pollfd;
vmin = 4;
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
err(1, "openpty");
if (tcgetattr(slave, &tiold) == -1)
err(1, "tcgetattr");
memcpy(&tinew, &tiold, sizeof(tinew));
cfmakeraw(&tinew);
tinew.c_cc[VMIN] = OURVMIN;
if (tcsetattr(slave, TCSANOW, &tinew) == -1)
err(1, "tcsetattr");
write(master, buf, 1);
pollfd.fd = slave;
pollfd.revents = 0;
pollfd.events = POLLRDNORM;
if ((ret = poll(&pollfd, 1, 1000)) != 0) {
if (ret == -1)
err(1, "poll");
errx(1, "poll succeeded unexpectedly: ret = %d", ret);
}
write(master, buf, OURVMIN - 1);
if ((ret = poll(&pollfd, 1, 1000)) != 1) {
if (ret == -1)
err(1, "poll");
if (ret == 0)
errx(1, "poll timed out");
errx(1, "poll unexpected rval: %d", ret);
}
(void)tcsetattr(slave, TCSANOW, &tiold);
printf("success\n");
return 0;
}