Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Guillaume Yziquel <guillaume.yziquel@citycable.ch>
To: Richard Jones <rich@annexia.org>
Cc: David Allsopp <dra-news@metastack.com>,
	'caml-list List' <caml-list@yquem.inria.fr>
Subject: Re: [Caml-list] problem creating .cma library
Date: Sat, 09 Jan 2010 20:29:22 +0100	[thread overview]
Message-ID: <4B48D912.8090602@citycable.ch> (raw)
In-Reply-To: <20100109125224.GC26610@annexia.org>

Richard Jones a écrit :
>
> Why is this a problem?  Because you might in your C code have some
> value on the stack.  'value' is (or can be) a pointer.  The OCaml
> garbage collector can move pointed-to-objects around, firstly from the
> minor heap to the major heap, secondly when compacting the major heap.
> So your C value (pointer) *could* become an invalid pointer if what it
> was pointing to got moved.

Yes, I understood the nature of the problem.

> The way to avoid this small chance is to register the value with the
> garbage collector, which is essentially what the CAMLparam* and
> CAMLlocal* macros do.  So if the GC needs to move that object, it will
> update the pointer for you.
> 
> If your function never allocates (and never calls anything which
> allocates), then you don't need to register values, because no
> allocation => they can't be moved.  [In fact there are some other
> exceptions as well where you can prove that an allocation won't move
> your pointer, eg. if you only allocate one thing and immediately
> return the value.]

I've been looking at the pcre bindings, and these bindings make minimal 
usage of CAMLparam, CAMLlocal and CAMLreturn.

For instance, here is the piece of code that executes R code ad catches 
errors. I've tried to follow guidelines available on the net, and 
inspired myself from pcre.

> CAMLprim value r_eval_sxp (value sexp_list) {
>   CAMLparam0();
>   CAMLlocal2(ml_error_call, ml_error_message);
>   SEXP e;
>   int error = 0;
>   PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
>   UNPROTECT(1);
>   if (error) {
>     ml_error_call = Val_sexp(error_call);
>     error_call = NULL;
>     ml_error_message = caml_copy_string(error_message);
>     error_message = NULL;
>     value error_result = caml_alloc_small(2, 0);
>     Store_field(error_result, 0, ml_error_call);
>     Store_field(error_result, 1, ml_error_message);
>     raise_with_arg(*caml_named_value("OCaml-R generic error"), error_result);
>   }
>   CAMLreturn(Val_sexp(e));
> }

Do you see GC / allocation / threading problems with it?

Would it be legitimate to include CAMLlocal2 inside the error-handling 
braces?

> You might find my series on the garbage collector interesting if you
> want to look into this further:
> 
> http://rwmj.wordpress.com/?s=ocaml+internals

These are very interesting. Could not find part 6, though...

> Also if you are calling C functions which don't allocate from OCaml
> code, you might want to read about noalloc:
> 
> http://camltastic.blogspot.com/2008/08/tip-calling-c-functions-directly-with.html

Two comments on this:

-1- I remember a post by Jon Harrop concerning external mathematical 
functions such as the exponential in Pervasives. He was arguing that it 
could be done directly from the .ml file by using such "tags". Where can 
I find a list of all these tags for external functions? There's "float", 
but are there others?

-2- If I understand this post well, the following function

> CAMLprim value init_r (value argv, value sigs) {
> 
>   /* -1- argv is an OCaml array of strings, which gives the command line
>      arguments used to invoke the R interpreter. Code segfaults if
>      the array does not contain a first element, which is the name of
>      the program, typically "R", or "OCaml-R". Other arguments typically
>      are "--vanilla", "--slave"...
> 
>      -2- sigs is an OCaml int. When set to 0, R signal handlers are not
>      removed. When set to, say, 1, R signal handlers are removed. It is
>      very useful to remove signal handlers when embedding R. */
> 
>   int length = Wosize_val(argv);
>   char* argv2[length];
>   int i;
> 
>   // We duplicate the OCaml array into a C array.
>   for (i=0; i<length; i++) argv2[i]=String_val(Field(argv, i));
> 
>   /* Don't let R set up its own signal handlers when sigs = 1.
>      This requires R >= 2.3.1. */
>   if (Int_val(sigs)) R_SignalHandlers = 0;
> 
>   // This is the libR.so function.
>   i = Rf_initEmbeddedR(length, argv2);
> 
>   // Returns 1 if R is correctly initialised.
>   return Val_int(i);
> }

could be called with "noalloc"?

>> By the way, here's a question I've been wondering about this section. 
>> Rule 3: When I have a Abstract_tag block used to wrap a pointer in the C 
>> heap, it seems to me that you can just do it with a Field(v,0)= 
>> assignment. Do you need Store_field for that?
> 
> This is to do with the Remembered Set.  See part 5 of the above
> series.

The remembere set, in this context, explains why I would need 
Store_field when dealing with pure OCaml world. When wrapping pointers 
to the C heap in abstract blocks, I do not see the point of Store_field, 
and it seems to me that Field= assignment is fine. Am I mistaken?

All the best,

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


  parent reply	other threads:[~2010-01-09 19:29 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-30 17:48 rouanvd
2009-12-30 23:30 ` [Caml-list] " Guillaume Yziquel
2010-01-05 13:04   ` Damien Doligez
2010-01-08 23:38     ` Guillaume Yziquel
2010-01-08 23:54       ` Basile STARYNKEVITCH
2010-01-09  0:11         ` Guillaume Yziquel
2010-01-09  7:58           ` David Allsopp
2010-01-09 11:33             ` Guillaume Yziquel
2010-01-09 12:52               ` Richard Jones
2010-01-09 14:00                 ` Daniel Bünzli
2010-01-09 14:02                   ` Daniel Bünzli
2010-01-09 14:21                     ` Joel Reymont
2010-01-09 19:36                   ` Guillaume Yziquel
2010-01-10  2:11                     ` Daniel Bünzli
2010-01-11 17:14                       ` Guillaume Yziquel
2010-01-10 13:31                     ` ygrek
2010-01-11 18:01                       ` Guillaume Yziquel
2010-01-09 19:29                 ` Guillaume Yziquel [this message]
2010-01-11 12:18                   ` Gerd Stolpmann
2010-01-11 17:11                     ` Guillaume Yziquel
2010-01-20 14:42                   ` Damien Doligez

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=4B48D912.8090602@citycable.ch \
    --to=guillaume.yziquel@citycable.ch \
    --cc=caml-list@yquem.inria.fr \
    --cc=dra-news@metastack.com \
    --cc=rich@annexia.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