problem with SETIOV in Resource Manager

Hello,



I write a resource manager. I handle _IO_READ messages with the
io_read() function (as in the documentation “writing a Resource
Manager”).
I have a problem with the macro SETIOV.When the client program does a
read(), an error returns : “Server fault on msg pass” (errno=312).


Here is the code :

#define LEN 65535

int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
{

off64_t offset;
static char *addr;

if( (addr = (char*)mmap_device_memory(0, LEN,
PROT_NOCACHE|PROT_READ|PROT_WRITE,
MAP_PHYS|MAP_SHARED,
offset)) == MAP_FAILED ) {
perror(“mmap_device_memory”);
return -1;
}
SETIOV (ctp->iov, addr, nbytes);
munmap(addr, LEN);

return (_RESMGR_NPARTS (nparts));
}


offset is the physical address of my 64K buffer, and mmap convert it
into a virtual address.
When I do a printf of addr, I can display the text I have wrote in the
buffer and the address is 0x40380000.
But, when the client does a read(), there is the error “Server fault
on msg pass”.

If I declare
char *buf = “hello world\n”;
in the io_read() function and if I do
SETIOV (ctp->iov, buf, nbytes);
I have no error. The address of buf is 0x804c3b6 and printf displays
the good text.

My questions are :
Why SETIOV does not work with mmap() while it works whith “char *buf”
as in my example ?
Is there an error in my code ?


Thank you in advance for your answer.


– Phil.

Bretin <philippebretin@hotmail.com> wrote:

Hello,



I write a resource manager. I handle _IO_READ messages with the
io_read() function (as in the documentation “writing a Resource
Manager”).
I have a problem with the macro SETIOV.When the client program does a
read(), an error returns : “Server fault on msg pass” (errno=312).

Didn’t you just “munmap()” the area before you returning ?
If you want to unmap it, you have to do a MsgReplyv() youself,
and munmap() the 64k area, and return (RESMGR_NOREPLY)

-xtang

Here is the code :

#define LEN 65535

int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
{

off64_t offset;
static char *addr;

if( (addr = (char*)mmap_device_memory(0, LEN,
PROT_NOCACHE|PROT_READ|PROT_WRITE,
MAP_PHYS|MAP_SHARED,
offset)) == MAP_FAILED ) {
perror(“mmap_device_memory”);
return -1;
}
SETIOV (ctp->iov, addr, nbytes);
munmap(addr, LEN);

return (_RESMGR_NPARTS (nparts));
}



offset is the physical address of my 64K buffer, and mmap convert it
into a virtual address.
When I do a printf of addr, I can display the text I have wrote in the
buffer and the address is 0x40380000.
But, when the client does a read(), there is the error “Server fault
on msg pass”.

If I declare
char *buf = “hello world\n”;
in the io_read() function and if I do
SETIOV (ctp->iov, buf, nbytes);
I have no error. The address of buf is 0x804c3b6 and printf displays
the good text.

My questions are :
Why SETIOV does not work with mmap() while it works whith “char *buf”
as in my example ?
Is there an error in my code ?



Thank you in advance for your answer.

– Phil.

Bretin <philippebretin@hotmail.com> wrote:

Hello,



I write a resource manager. I handle _IO_READ messages with the
io_read() function (as in the documentation “writing a Resource
Manager”).
I have a problem with the macro SETIOV.When the client program does a
read(), an error returns : “Server fault on msg pass” (errno=312).

SETIOV does NOT copy the memory pointed to – it just records the
address and length for later use.


Here is the code :

#define LEN 65535

int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
{

off64_t offset;
static char *addr;

if( (addr = (char*)mmap_device_memory(0, LEN,
PROT_NOCACHE|PROT_READ|PROT_WRITE,
MAP_PHYS|MAP_SHARED,
offset)) == MAP_FAILED ) {
perror(“mmap_device_memory”);
return -1;
}

So, you record the pointer:

SETIOV (ctp->iov, addr, nbytes);

Then you specifically make that pointer invalid:

munmap(addr, LEN);

So, of course, this will fail.

return (_RESMGR_NPARTS (nparts));
}



offset is the physical address of my 64K buffer, and mmap convert it
into a virtual address.
When I do a printf of addr, I can display the text I have wrote in the
buffer and the address is 0x40380000.
But, when the client does a read(), there is the error “Server fault
on msg pass”.

Yup, at the MsgReply() point, when the kernel tried to read that memory
on the server’s behalf, it hit bad memory, the kernel won’t actually
crash from the SIGSEGV, but traps the error, and fails the MsgSend
(buried in read()) with the “Server fault” error.

You can’t unmap the memory until after the reply is complete.

A previous poster told how to do that.

-David

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