[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: IDL issue - struct return vs. cap return
From: |
Neal H. Walfield |
Subject: |
Re: IDL issue - struct return vs. cap return |
Date: |
Mon, 09 Jul 2007 23:24:07 +0200 |
User-agent: |
Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.6 (Marutamachi) APEL/10.6 Emacs/21.4 (i386-pc-linux-gnu) MULE/5.0 (SAKAKI) |
At Mon, 09 Jul 2007 15:14:25 -0400,
Jonathan S. Shapiro wrote:
>
> On Mon, 2007-07-09 at 18:10 +0200, Neal H. Walfield wrote:
> > At Sun, 08 Jul 2007 00:03:10 -0400,
> > Jonathan S. Shapiro wrote:
> >
> > > If we choose to adopt the "return the return value" convention, it is
> > > still necessary to handle capability returns specially in C, because the
> > > caller must say where the incoming capability is to be stored (we cannot
> > > get compiler help for this from an unmodified compiler).
> >
> > How is this different from returning a struct? There is a general
> > rule of thumb not to return large structs from function calls.
> > Instead, the convention is for either the function allocates memory or
> > the caller to pass a pointer to a block of allocated memory.
>
> The convention you describe is actually unnecessary, because good
> compilers already implement it automatically. If you write something of
> the form:
>
> s = f(...);
>
> where s is some structure type larger than (typically) 2 words, most
> calling conventions will automatically rewrite it as:
>
> f(..., &s);
Are you sure? This change changes the semantics of the return. gcc,
for instance, does not do this. Consider:
#include <string.h>
#include <stdio.h>
struct foo
{
char *p;
char s[100000];
};
struct foo bar (void)
{
struct foo foo;
foo.p = foo.s;
return foo;
}
int
main ()
{
struct foo foo;
foo.p = foo.s;
printf ("before: %x\n", foo.p);
foo = bar ();
printf ("after: %x\n", foo.p);
}
$ ./foo
before: 7339c5c8
after: 7336b848
(Having a pointer to an internal member is not an uncommon practice.
If you have a struct and a number of variable size elements whose size
you know at allocation, but not compile, time, you can allocate them
with a single call to malloc to save a bit of CPU and storage overhead
plus get a bit of locality.)
> Many, but not all compilers, will automatically suppress this rewrite
> for small, registerizable structs. The convention you describe is mainly
> relevant for legacy compilers these days.
I don't completely buy the legacy argument. When the struct is
returned, the pointer needs to be updated, however, the compiler
doesn't know that memcpy isn't enough. When returning a struct, you
need to be careful in a similar way to which you have to be careful
when dealing with opaque references.
> Because cap_t is a reference, you basically have two options if you want
> to return a cap_t from an IDL procedure:
>
> 1. Use a well-known return location, e.g. capability register 2.
> 2. Call the capability location allocator from inside the stub, as
> in:
>
> f() {
> cap_t _retVal = alloc_cap_location();
> DO_SYSCALL_HERE(_retVal);
> return _retVal;
> }
3. The caller provides the address of the slot in which the function
should store the capability. (You want this for the same reasons
you may not necessarily want a function to call malloc.)
- Re: IDL issue, (continued)
- Re: IDL issue, Michal Suchanek, 2007/07/10
Re: IDL issue, Neal H. Walfield, 2007/07/09
Re: IDL issue - struct return vs. cap return, Jonathan S. Shapiro, 2007/07/09
Re: IDL issue - struct return vs. cap return, Jonathan S. Shapiro, 2007/07/10
Re: IDL issue - struct return vs. cap return, Neal H. Walfield, 2007/07/10
Re: IDL issue - struct return vs. cap return, Jonathan S. Shapiro, 2007/07/10
Re: IDL issue - struct return vs. cap return, Neal H. Walfield, 2007/07/10
Re: IDL issue - struct return vs. cap return, Jonathan S. Shapiro, 2007/07/10