io_read "return by value" rather than "return by reference"

Hi all,

I’m writing a short io_read function for a resource manager.
It’s easy enough to copy the examples off the web page, but of
course once you stray from the script a bit, lots of questions form…

The on-line documentation recommends copying data to the client’s
buffer rather than simply returning a pointer. This is paramount for
my application since I’m using a circular queue as my internal data
structure and I need to release the buffer storage when I return.

Couple of questions:

  1. does SETIOV or _IO_SET_READ_NBYTES do the actual data copying?

  2. For the io_read_t data structure there is a commented out field,
    data[nbytes].
    The documentation seems to imply that this is the “output” data
    structure while
    the “i” field is the input data structure. Is this correct? If so, do
    I just copy the
    data to where this guy points?

Else, how do I do a “return by value” on this data?
Thanks,
Randy Hyde

Randall Hyde <randall.nospam.hyde@ustraffic.net> wrote:

Hi all,

I’m writing a short io_read function for a resource manager.
It’s easy enough to copy the examples off the web page, but of
course once you stray from the script a bit, lots of questions form…

The on-line documentation recommends copying data to the client’s
buffer rather than simply returning a pointer. This is paramount for
my application since I’m using a circular queue as my internal data
structure and I need to release the buffer storage when I return.

Couple of questions:

  1. does SETIOV or _IO_SET_READ_NBYTES do the actual data copying?

  2. For the io_read_t data structure there is a commented out field,
    data[nbytes].
    The documentation seems to imply that this is the “output” data
    structure while
    the “i” field is the input data structure. Is this correct? If so, do
    I just copy the
    data to where this guy points?

Else, how do I do a “return by value” on this data?
Thanks,
Randy Hyde

You might wish to take a look at a few real-world examples;
www.parse.com/free has a RAMDisk and a .tar filesystem that
illustrate how to return the data… :slight_smile:

Cheers,
-RK


Robert Krten, PARSE Software Devices +1 613 599 8316.
Realtime Systems Architecture, Books, Video-based and Instructor-led
Training and Consulting at www.parse.com.
Email my initials at parse dot com.

“Robert Krten” <nospam84@parse.com> wrote in message
news:b1f9mt$m2g$1@inn.qnx.com

You might wish to take a look at a few real-world examples;
www.parse.com/free > has a RAMDisk and a .tar filesystem that
illustrate how to return the data… > :slight_smile:

Thanks,
Randy Hyde

Randall Hyde <randall.nospam.hyde@ustraffic.net> wrote:

Hi all,

I’m writing a short io_read function for a resource manager.
It’s easy enough to copy the examples off the web page, but of
course once you stray from the script a bit, lots of questions form…

The on-line documentation recommends copying data to the client’s
buffer rather than simply returning a pointer. This is paramount for
my application since I’m using a circular queue as my internal data
structure and I need to release the buffer storage when I return.

Couple of questions:

  1. does SETIOV or _IO_SET_READ_NBYTES do the actual data copying?

Neither do.

After the return( _RESMGR_NPARTS(x)), there is an implied
MsgReplyv() done that does the actual copying.


  1. For the io_read_t data structure there is a commented out field,
    data[nbytes].

Be careful – the io_read_t data type is a union, not a structure.

The documentation seems to imply that this is the “output” data
structure while
the “i” field is the input data structure. Is this correct?

Essentially yes. But, it is mostly describing the TYPE of the
return, rather than the need to use that location (especially as
it is commented out.)

If so, do
I just copy the
data to where this guy points?

Not usually. If you wanted to re-use your receive buffer for building
the reply data, then pointing to it, you could do so. (Though, this will
only usually be reasonable for small replies.)

Else, how do I do a “return by value” on this data?

You can & you can’t.
– you will have to have one copy – the data MUST be copied from the
resource manager back to the client.

Within the resource manager, you don’t need to copy:
– SETIOV takes a reference to the data wherever you have it
– return _RESMGR_NPARTS and the data will be copied to the client
Or
– you can MsgReply() or MsgReplyv() directly yourself and return
RESMGR_NOREPLY

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Randall Hyde wrote:

  1. does SETIOV or _IO_SET_READ_NBYTES do the actual data copying?

No they setup the copy-list that gets passed into MsgReplyv(), the
kernel does the copying via MsgWrite() or MsgReply()…

  1. For the io_read_t data structure there is a commented out field,
    data[nbytes].
    The documentation seems to imply that this is the “output” data
    structure while
    the “i” field is the input data structure. Is this correct? If so, do
    I just copy the
    data to where this guy points?

This is not recommended. There are two virtual “data areas” associated
with any MsgSend() (like a client’s read()). A readonly area and a
writeonly area. As it turns out, the _io_read header part goes into the
read-only section and the actual reply buffer goes into the write-only
section. So, the two are not even logically contiguous and are
definitely not mapped into your resmgr’s address space (so writing to
“wherever this guy points” is a baaad thing) .

The safest way to reply with data is to do:

MsgReply (ctp->rcvid, bufsize, buf, bufsize);
// invalidate the buffer or other kind of clean-up
return (_RESMGR_NOREPLY);

This means that your function will cause the kernel to do the copy and
reply immediately. After the copy is done, you can clean-up the buffer
before the operation is complete.

Daryl Low