IPC problem with dice-3.3.0
Carsten Weinhold
weinhold at os.inf.tu-dresden.de
Thu Mar 26 15:03:12 CET 2009
Am 26.03.2009 um 12:33 schrieb Marcel Selhorst:
> Hi Carsten,
Hello Marcel,
>>> [...] The error message
>> you get might also indicate a stack overrun (maybe the generated DICE
>> code uses too much stack ... ?).
>
> I think it is indeed a stack overrun.
> I have implemented CORBA_alloc() and CORBA_free() to force DICE to
> allocate the
> used buffers during IPC via the Linux kernel vmalloc, but it seems,
> that DICE is
> not using these methods at all:
>
> My IDL-File looks like this:
> long read
> (
> [in, size_is(name_len), max_is(MAX_NAME_LEN)] char *name,
> [in] unsigned long name_len,
> [in] unsigned long start,
> [in] unsigned long bytes_to_read,
> [out, prealloc_client, max_is(MAX_PAGE_SIZE)] unsigned char
> read_buffer[]
> );
>
> long write
> (
> [in, size_is(name_len), max_is(MAX_NAME_LEN)] char *name,
> [in] unsigned long name_len,
> [in] unsigned long start,
> [in] unsigned long bytes_to_write,
> [in, prealloc_client, max_is(MAX_PAGE_SIZE)] unsigned char
> write_buffer[]
> );
>
> My according CORBA_alloc/free implementation looks like this:
>
> #include <linux/vmalloc.h>
>
> void *CORBA_alloc(unsigned long size)
> {
> return vmalloc(size);
> }
>
> void CORBA_free(void *addr)
> {
> vfree(addr);
> }
>
> But the generated code doesn't even include a call for CORBA_free,
> instead it
> generates:
>
> [...]
> struct
> {
> l4_fpage_t _dice_rcv_fpage;
> l4_msgdope_t _dice_size_dope;
> l4_msgdope_t _dice_send_dope;
> long _dice_opcode;
> unsigned long name_len;
> unsigned long start;
> unsigned long bytes_to_write;
> unsigned char write_buffer[4096];
> char name[100];
> } dummy_write_in;
> [...]
Whoops, a message buffer with an array of 4096 bytes will indeed not
fit onto a Linux kernel stack.
> What am I missing? ;)
The magic keywords here are 'prealloc_server' and 'ref'. They are
described in the DICE user manual. I modified your interface as follows:
/* guessed from your generated code */
#define MAX_NAME_LEN 32
#define MAX_PAGE_SIZE 4096
interface dummy {
long read
(
[in, size_is(name_len), max_is(MAX_NAME_LEN)] char *name,
[in] unsigned long name_len,
[in] unsigned long start,
[in] unsigned long bytes_to_read,
[out, ref, prealloc_server, prealloc_client, size_is(MAX_PAGE_SIZE),
max_is(MAX_PAGE_SIZE)] unsigned char **read_buffer
);
long write
(
[in, size_is(name_len), max_is(MAX_NAME_LEN)] char *name,
[in] unsigned long name_len,
[in] unsigned long start,
[in] unsigned long bytes_to_write,
[in, ref, prealloc_client, size_is(MAX_PAGE_SIZE),
max_is(MAX_PAGE_SIZE)] unsigned char *write_buffer
);
};
This instructs DICE to generate code that uses indirect string IPC.
This has the desired advantage that the IPC message buffer gets much
smaller and your buffers are instead allocated using CORBA_alloc().
The downside is that it might actually be slower for small buffers
(e.g., 4096 bytes as you seem to be transferring) due to additional
mappings being used by Fiasco. Also, the receive buffer in the server
used for your write() function is newly allocated and then freed for
each call; doing some manual caching in the CORBA_{alloc,free}()
functions might make this a non-issue. The function signatures also
changed a bit (client and server side).
Carsten
More information about the l4-hackers
mailing list