Can I use TimerTimeout() before read() ?

[I am running QNX6.3.0 SP1 for x86 on VMWare 4.5.2 without vmtoold ]

I want to timeout on a read() function call. Here’s my code:

fd = open ( /dev/ser1, O_RDWR ) ;
… or …
fd = open ( /dev/ttyq1, O_RDWR ) ;

flags = _NTO_TIMEOUT_REPLY ;
event.sigev_notify = SIGEV_UNBLOCK ;
TimerTimeout ( CLOCK_REALTIME, flags, &event, &timeout_nanosec, NULL);
size_read = read ( fd, buffer, buf_size ) ;

Sometimes the read() blocks forever.

I have several questions.

  1. Can I assume that read() eventually does one and only one MsgSend() ?

  2. The TimerTimeout docs say:
    [[
    MsgSendv() doesn’t unblock on SIGEV_UNBLOCK if the server has already
    received the message via MsgReceivev() and has specified
    _NTO_CHF_UNBLOCK in the flags argument to its ChannelCreate() call. In
    this case, it’s up to the server to do a MsgReplyv().
    ]]
    What dos this mean? Is there no guarantee that TimerTimeout will work?

  3. The TimerTimeout docs say:
    [[
    Instead of using these kernel calls directly, consider calling
    timer_timeout().
    ]]
    Why? Is it for POSIX compatibility?
    The problem is that the timer_timeout() docs say:
    [[
    Caveats:
    The timeout value starts timing out when timer_timeout() is called, not
    when the blocking state is entered. It might be possible to get
    preempted after calling timer_timeout() but before the blocking kernel call.
    ]]
    but isn’t this the same problem that alarm() has? and isn’t this why we
    should use timer_timeout() instead of alarm()?

  4. Someone might suggest using signals instead, however, from the
    TimerTimeout documentation:
    [[
    Only SIGEV_UNBLOCK guarantees that the kernel call unblocks. A signal
    may be ignored, blocked, or accepted by another thread, and a pulse can
    only unblock a MsgReceivev().
    ]]
    Does this mean that even if I setup a signal, I am not guaranteed that
    it would unblock the read()?

  5. Can I send an IO_READ message directly to the resource manager
    handling my device? Does anyone know how to do that?
    and wouldn’t that be the same as the code that read() implements?

  6. When the timeout works, it returns EINTR and not (like the docs say)
    ETIMEDOUT. Am I doing something wrong?

  7. Does VMWare properly emulate the RTC? Do I need vmtoold?

Alain.

“Alain Achkar” <js@simplytech.com> wrote in message
news:d5as5u$gh6$1@inn.qnx.com

[I am running QNX6.3.0 SP1 for x86 on VMWare 4.5.2 without vmtoold ]

I want to timeout on a read() function call. Here’s my code:

fd = open ( /dev/ser1, O_RDWR ) ;
… or …
fd = open ( /dev/ttyq1, O_RDWR ) ;

flags = _NTO_TIMEOUT_REPLY ;
event.sigev_notify = SIGEV_UNBLOCK ;
TimerTimeout ( CLOCK_REALTIME, flags, &event, &timeout_nanosec, NULL);
size_read = read ( fd, buffer, buf_size ) ;

Sometimes the read() blocks forever.

You might want to open the device in NON_BLOCKING mode and if applicable use
notification to be told where there is data in the buffer.

  1. Does VMWare properly emulate the RTC?

Yes, you can even have a different time/date for each virtual machine.

Do I need vmtoold?

If you want to keep the time between the host and the guest the same yes.
QNX time is handled by timer interrupt and this may get disrupted when
running on virtual machine. Also if you suspend the machine, vmtoold is
usefull to update the time (while suspended time stops)


Yes,
Alain.

Alain Achkar <js@simplytech.com> wrote:

[I am running QNX6.3.0 SP1 for x86 on VMWare 4.5.2 without vmtoold ]

I want to timeout on a read() function call. Here’s my code:

Other options I would consider:

If you are dealing with terminal devices (as your code suggests with
what it specifies on the open), you may find that readcond() will
work better for you.

Or open() with O_NONBLOCK and use io_notify() (or select()) to tell you
when there is data available to be read(), so that you will never
call read() in a case where it might block.

fd = open ( /dev/ser1, O_RDWR ) ;
… or …
fd = open ( /dev/ttyq1, O_RDWR ) ;

flags = _NTO_TIMEOUT_REPLY ;
event.sigev_notify = SIGEV_UNBLOCK ;
TimerTimeout ( CLOCK_REALTIME, flags, &event, &timeout_nanosec, NULL);
size_read = read ( fd, buffer, buf_size ) ;

Sometimes the read() blocks forever.

I have several questions.

  1. Can I assume that read() eventually does one and only one MsgSend() ?

Yes.

  1. The TimerTimeout docs say:
    [[
    MsgSendv() doesn’t unblock on SIGEV_UNBLOCK if the server has already
    received the message via MsgReceivev() and has specified
    _NTO_CHF_UNBLOCK in the flags argument to its ChannelCreate() call. In
    this case, it’s up to the server to do a MsgReplyv().
    ]]
    What dos this mean? Is there no guarantee that TimerTimeout will work?

It depends on the server to properly handle the unblock pulse – what will
happen on the timeout is that a pulse will be sent to the server by the
kernel telling the server that you want to timeout. The server will clean
up whatever resources/operations are in progress on your behalf, then
unblock you.

  1. The TimerTimeout docs say:
    [[
    Instead of using these kernel calls directly, consider calling
    timer_timeout().
    ]]
    Why? Is it for POSIX compatibility?

Neither is POSIX, they just specify the time parameter differently –
timer_timeout() uses the, usually more familiar struct timespec
(seconds & nanoseconds) for the timeout, while TimerTimeout uses
64-bit nanoseconds.

The problem is that the timer_timeout() docs say:
[[
Caveats:
The timeout value starts timing out when timer_timeout() is called, not
when the blocking state is entered. It might be possible to get
preempted after calling timer_timeout() but before the blocking kernel call.
]]
but isn’t this the same problem that alarm() has? and isn’t this why we
should use timer_timeout() instead of alarm()?

If you use alarm(), and get pre-empted, and the signal hits before you
block, you will handle the signal, and then block, forever.

If you use a kernel timeout, and the timeout expires before you go to
block, the pending timeout will be remembered, and as you are about to
block you will fail to block and timeout immmediately.

See the difference?

(Also, with kernel timeouts you don’t have the annoyances of setting up
a handler for SIGALARM, and of clearing the alarm() afterwords if it
hasn’t fired. The timeout is automatically cleared on successful
kernel call completion.)

  1. Someone might suggest using signals instead, however, from the
    TimerTimeout documentation:
    [[
    Only SIGEV_UNBLOCK guarantees that the kernel call unblocks. A signal
    may be ignored, blocked, or accepted by another thread, and a pulse can
    only unblock a MsgReceivev().
    ]]
    Does this mean that even if I setup a signal, I am not guaranteed that
    it would unblock the read()?

Nope, I wouldn’t recommend signals instead. See above reason for alarm().

  1. Can I send an IO_READ message directly to the resource manager
    handling my device? Does anyone know how to do that?
    and wouldn’t that be the same as the code that read() implements?

That would be the same.

Basically read looks like:

int read( int fd, void *buf, ssize_t nbytes )
{
struct _io_read hdr;
hdr.type = IO_READ;
hdr.nbytes = nbytes;
hdr.xtype = 0;
return MsgSend(fd, &hdr, sizeof(hdr), buf, nbytes );
}

  1. When the timeout works, it returns EINTR and not (like the docs say)
    ETIMEDOUT. Am I doing something wrong?

No, you’re not doing anything wrong. The problem is the pulse that
notifies the server that you want to unblock does NOT have enough
space to tell the server WHY you want to unblock, yet the server still
has to pick an errno for failing your read() (or other blocking call).
Generally, they always pick EINTR. I think I’ve got a docs PR outstanding
against this.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

So why does my code work sometimes, and other times the read() blocks
forever?

If I am guaranteed that the read() will issue a MsgSend, then the
MsgSend should unblock when the timeout expires and the read() should
return. How come my thread becomes REPLY-blocked forever?

“Alain Achkar” <js@simplytech.com> wrote in message
news:d5b828$olu$1@inn.qnx.com

So why does my code work sometimes, and other times the read() blocks
forever?

If I am guaranteed that the read() will issue a MsgSend, then the MsgSend
should unblock when the timeout expires and the read() should return. How
come my thread becomes REPLY-blocked forever?

Are you sure it’s blocked in that read()?

Alain Achkar <js@simplytech.com> wrote:

So why does my code work sometimes, and other times the read() blocks
forever?

Without seeing your code, it is really hard to say.

For instance:

TimerTimeout()
printf(“the next read will be time-limitted\n”);
read();

Will not timeout the read.

If I am guaranteed that the read() will issue a MsgSend, then the
MsgSend should unblock when the timeout expires and the read() should
return. How come my thread becomes REPLY-blocked forever?

You don’t have things coded properly, or you’re REPLY blocked in
some other call than that read().

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Alain Achkar wrote:

[I am running QNX6.3.0 SP1 for x86 on VMWare 4.5.2 without vmtoold ]

Don’t expect real-time performance. VMware does not have
the scheduler responsiveness QNX does, and you’re at the
mercy of VMware. Other than for debug or out of curiosity,
this probably isn’t all that useful.

I want to timeout on a read() function call. Here’s my code:

It will work, but “select” is probably preferable.

For serial ports, note that there’s “readcond”, and
you can also set timeouts via IO control functions.
This may be more efficient than blasting your way out
of the read call with TimerTimeout.

John Nagle
Team Overbot