From: David Scott <dave.scott@eu.citrix.com>
To: Ian Campbell <Ian.Campbell@citrix.com>
Cc: Rob Hoes <Rob.Hoes@citrix.com>,
"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: [PATCH 08/28] libxc: ocaml: add simple binding for xentoollog (output only).
Date: Mon, 15 Apr 2013 10:39:43 +0100 [thread overview]
Message-ID: <516BCADF.602@eu.citrix.com> (raw)
In-Reply-To: <1365679894.8036.87.camel@zakaz.uk.xensource.com>
On 11/04/13 12:31, Ian Campbell wrote:
> On Fri, 2013-04-05 at 15:04 +0100, Rob Hoes wrote:
>>> I think we should avoid returning "bare pointers" to the OCaml heap for two
>>> reasons:
>
> malloc is the "C" runtime heap, is that the same as the ocaml heap?
> (From your description I understand the distinction isn't relevant in
> this context, but I'm curious).
The OCaml heap is a set of blocks acquired via malloc(), so you could
say that the OCaml heap is a subset of the C heap :-) I guess in a
long-running program you'd end up with some interleaving of <ocaml heap
block>; <normal C data> throughout application memory.
To make the GC work, the OCaml heap has to have enough structure for
pointers to other OCaml values to be found. The current OCaml convention
is that a "value" is a pointer if its least significant bit = 0 (the
Val_int macro sets the bit to 1 to mark a value as a plain integer) and
the pointer must point to somewhere within a previously-allocated OCaml
heap block. This last check is what makes it possible to stuff the
normal result of malloc() directly into an OCaml value and have it be
ignored by the GC... for a while :-)
It's also worth knowing that every heap block has a tag and the tags are
divided into two groups: one for blocks which should be introspected and
assumed to contain arrays of OCaml values (tuples, records, arrays etc),
and one group for blocks which should be ignored (and which are safe for
us to stick our stuff in). For example an OCaml string is a block with a
'String_tag' and won't be examined further by the GC.
in ocaml/byterun/mlvalues.h:
/* The lowest tag for blocks containing no value. */
#define No_scan_tag 251
/* Strings. */
#define String_tag 252
/* Arrays of floating-point numbers. */
#define Double_array_tag 254
...
>
>> [...]
>>
>> I see, thanks for pointing that out.
>>
>>> Instead of returning a "bare pointer" I think we should use a "Custom"
>>> value. This involves declaring a "struct custom_operations" like this:
>>>
>>> static struct custom_operations foo_custom_operations = {
>>> "foo_custom_operations",
>>> custom_finalize_default,
>>> custom_compare_default,
>>> custom_hash_default,
>>> custom_serialize_default,
>>> custom_deserialize_default
>>> };
>>>
>>> And then wrapping and unwrapping "Custom" blocks using something like:
>>>
>>> #define Foo_val(x) (*((struct foo *)Data_custom_val(x)))
>>>
>>> static value
>>> Val_foo (struct foo *x)
>>> {
>>> CAMLparam0 ();
>>> CAMLlocal1 (result);
>>> result = caml_alloc_custom (&foo_custom_operations,
>>> sizeof (struct foo*), 0, 1);
>>> Foo_val (result) = x;
>>> CAMLreturn (result);
>>> }
>>
>> I'll update all occurrences of this pattern. The same think happens
>> for the libxl context as well.
>
> And probably the libxc context too in that set of bindings?
>
> There's also a malloc in stub_xc_domain_get_pfn_list but that is free'd
> in the same C function, which I guess is not subject to this issue?
It looks ok to me -- the result of the malloc is not being stored in an
OCaml "value". The OCaml values look like they're being created properly
(caml_copy_nativeint) and stored in a place the GC can see (CAMLlocal2
and Store_field):
CAMLlocal2(array, v);
...
c_array = malloc(sizeof(uint64_t) * c_nr_pfns);
...
array = caml_alloc(ret, 0);
for (i = 0; i < ret; i++) {
v = caml_copy_nativeint(c_array[i]);
Store_field(array, i, v);
}
free(c_array);
>
> BTW when looking I found the mmap library uses:
> result = caml_alloc(sizeof(struct mmap_interface), Abstract_tag);
>
> Is that valid? If so then it avoids all the custom operations stuff,
> although if you want the finalizer callback then this is worthwhile
> anyway.
I think so... Looking in in ocaml/byterun/mlvalues.h:
/* Abstract things. Their contents is not traced by the GC;
therefore they must not contain any [value]. */
#define Abstract_tag 251
/* Custom blocks. They contain a pointer to a "method suite"
of functions (for finalization, comparison, hashing, etc)
followed by raw data. The contents of custom blocks is not traced
by the GC; therefore, they must not contain any [value].
See [custom.h] for operations on method suites. */
#define Custom_tag 255
So it looks like both Abstract_tag and Custom_tag shield the data within
from the GC. So it should be safe to store anything which isn't an OCaml
"value", including the raw result of a malloc(). If we stored an OCaml
"value" in there it would be hidden from the GC and probably prematurely
deallocated.
As for which option we should pick, as you say I think it just depends
whether we want the finalizer.
>
> Also in the same bit of the mmap library the mmap(2) result is stored as
> a bare pointer inside that "result" from above, is that visible to the
> GC and therefore also dangerous?
I think it's ok because
result = caml_alloc(sizeof(struct mmap_interface), Abstract_tag);
-- this creates a block on the OCaml heap where the contents will be
ignored by the GC ("not traced by the GC" above). If we created a
different type of block then it would probably be an immediate disaster
since the GC would look inside and see something different to what it
expects: it expects a simple array of "value"s and we've stuck a custom
struct in there.
Does that make sense?
Cheers,
Dave
next prev parent reply other threads:[~2013-04-15 9:39 UTC|newest]
Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-25 14:45 [PATCH 00/28] libxl: ocaml: improve the bindings Rob Hoes
2013-03-25 14:45 ` [PATCH 01/28] libxl: Add LIBXL_SHUTDOWN_REASON_UNKNOWN Rob Hoes
2013-03-25 14:45 ` [PATCH 02/28] libxl: idl: allow KeyedUnion members to be empty Rob Hoes
2013-03-25 14:45 ` [PATCH 03/28] libxl: ocaml: fix code intended to output comments before definitions Rob Hoes
2013-03-25 14:45 ` [PATCH 04/28] libxl: ocaml: support for Arrays in bindings generator Rob Hoes
2013-03-25 14:45 ` [PATCH 05/28] libxl: ocaml: avoid reserved words in type and field names Rob Hoes
2013-03-25 14:45 ` [PATCH 06/28] libxl: ocaml: support for KeyedUnion in the bindings generator Rob Hoes
2013-03-26 9:21 ` David Scott
2013-04-05 13:37 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 07/28] libxl: ocaml: add some more builtin types Rob Hoes
2013-03-25 14:45 ` [PATCH 08/28] libxc: ocaml: add simple binding for xentoollog (output only) Rob Hoes
2013-03-26 11:14 ` David Scott
2013-04-05 14:04 ` Rob Hoes
2013-04-11 11:31 ` Ian Campbell
2013-04-15 9:39 ` David Scott [this message]
2013-04-15 9:47 ` Ian Campbell
2013-03-25 14:45 ` [PATCH 09/28] libxl: ocaml: allocate a long lived libxl context Rob Hoes
2013-03-25 14:45 ` [PATCH 10/28] libxl: ocaml: switch all functions over to take a context Rob Hoes
2013-03-25 14:45 ` [PATCH 11/28] libxl: ocaml: propagate the libxl return error code in exceptions Rob Hoes
2013-03-26 11:33 ` David Scott
2013-04-05 14:15 ` Rob Hoes
2013-04-11 11:33 ` Ian Campbell
2013-04-23 13:28 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 12/28] libxl: ocaml: add domain_build/create_info/config and events to the bindings Rob Hoes
2013-03-25 14:45 ` [PATCH 13/28] libxl: idl: add domain_type field to libxl_dominfo struct Rob Hoes
2013-04-11 11:19 ` Ian Campbell
2013-04-23 13:10 ` Rob Hoes
2013-04-23 13:21 ` Ian Campbell
2013-04-23 13:27 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 14/28] libxl: ocaml: fix the META file Rob Hoes
2013-04-11 11:20 ` Ian Campbell
2013-03-25 14:45 ` [PATCH 15/28] libxl: ocaml: fix the handling of enums in the bindings generator Rob Hoes
2013-04-11 11:20 ` Ian Campbell
2013-03-25 14:45 ` [PATCH 16/28] libxl: ocaml: use the "string option" type for IDL strings Rob Hoes
2013-03-26 11:43 ` David Scott
2013-04-05 14:17 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 17/28] libxl: ocaml: add with_ctx helper function Rob Hoes
2013-04-11 11:19 ` Ian Campbell
2013-04-23 13:03 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 18/28] libxl: ocaml: add xen_console_read Rob Hoes
2013-03-26 11:48 ` David Scott
2013-03-26 15:27 ` Andrew Cooper
2013-04-05 14:33 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 19/28] libxl: ocaml: add dominfo_list and dominfo_get Rob Hoes
2013-04-11 11:23 ` Ian Campbell
2013-04-23 13:18 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 20/28] libxl: ocaml: implement some simple tests Rob Hoes
2013-03-25 14:45 ` [PATCH 21/28] libxl: ocaml: add wrappers for poll Rob Hoes
2013-03-26 11:53 ` David Scott
2013-04-05 14:18 ` Rob Hoes
2013-04-11 12:31 ` Ian Campbell
2013-04-23 13:37 ` Rob Hoes
2013-04-23 13:43 ` Ian Campbell
2013-04-23 13:56 ` David Scott
2013-04-23 15:31 ` Ian Campbell
2013-04-25 9:09 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 22/28] libxl: ocaml: event management Rob Hoes
2013-03-26 11:55 ` David Scott
2013-03-26 12:03 ` David Scott
2013-04-05 14:20 ` Rob Hoes
2013-04-11 12:41 ` Ian Campbell
2013-04-23 15:33 ` Rob Hoes
2013-04-23 15:58 ` Ian Campbell
2013-04-23 16:30 ` Rob Hoes
2013-04-23 16:39 ` Ian Campbell
2013-04-23 16:50 ` Ian Jackson
2013-04-24 9:02 ` Ian Campbell
2013-04-25 8:58 ` Rob Hoes
2013-04-23 16:14 ` Ian Jackson
2013-03-25 14:45 ` [PATCH 23/28] libxl: ocaml: allow device operations to be called asynchronously Rob Hoes
2013-04-11 12:51 ` Ian Campbell
2013-04-23 15:59 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 24/28] libxl: ocaml: add NIC helper functions Rob Hoes
2013-04-11 12:56 ` Ian Campbell
2013-04-23 17:04 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 25/28] libxl: ocaml: add PCI device " Rob Hoes
2013-04-11 12:56 ` Ian Campbell
2013-03-25 14:45 ` [PATCH 26/28] libxl: ocaml: add disk and cdrom " Rob Hoes
2013-04-11 12:58 ` Ian Campbell
2013-04-29 11:41 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 27/28] libxl: ocaml: add VM lifecycle operations Rob Hoes
2013-04-11 13:03 ` Ian Campbell
2013-04-29 14:01 ` Rob Hoes
2013-03-25 14:45 ` [PATCH 28/28] libxl: ocaml: provide default records for libxl types Rob Hoes
2013-04-11 13:08 ` Ian Campbell
2013-04-29 14:13 ` Rob Hoes
2013-04-29 14:19 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=516BCADF.602@eu.citrix.com \
--to=dave.scott@eu.citrix.com \
--cc=Ian.Campbell@citrix.com \
--cc=Rob.Hoes@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).