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