caml_{enter,leave}_blocking_section

What are caml_{enter,leave}_blocking_section? They are not documented in the OCaml reference manual, but are very important if you tweak C code in multi-thread OCaml environment:

Jacque Garrigue wrote:

With posix threads (or windows threads), every caml thread is mapped
to a posix thread, but there is a global mutex which any caml thread
must obtain before running. This makes sure for instance that memory
allocation and GC work properly.
So no more than one caml thread may run simultaneously, and you don't
gain from multiple CPUs.

However, contrary to vmthreads, this restriction only applies while
executing caml code. If you call some C function, you may choose to
first release the global lock (caml_enter_blocking_section), letting
other caml threads work while you are on the C side. Don't forget to
call lock again (caml_leave_blocking_section) when returning, or you
will crash very soon.

http://groups.google.com/group/fa.caml/browse_thread/thread/4029e626205820b9/3671a04944223bee?lnk=gst&q=caml_enter_blocking_section#3671a04944223bee

Sounds odd (a blocking section unblocks other threads!), but,

  • caml_enter_blocking_section : release the global lock in OCaml runtime.
  • caml_leave_blocking_section : lock it again.
  • In the section, some other threads may work simultaneously with the current thread.

Yes, it is true, but be careful, when your C code accesses OCaml values (alloc, reading pointers, etc) before entering the section. Once after the lock is released, some other OCaml threads are executed, and there is a chance of GC. This makes your OCaml related pointer values no longer reliable!!

Actually Francois Rouaix has pointed it out long ago:

When you want to be able to switch threads while in C-code, or handle
signals.
However, my understanding is that the code in the section must not
access anything in the Caml heap.

On Jan 16, 2006, at 7:33 AM, Bauer, Christoph wrote:

> Hi,
>
> when do I have to call the functions
> caml_enter_blocking_section ()
> and
> caml_leave_blocking_section ()
> in my C-stub code?
>
> Thanks,
>
> Christoph Bauer
> Dipl. Inf.

http://groups.google.com/group/fa.caml/browse_thread/thread/fd6c8ec4f51c0fc5/3ab73788b5f142a1?lnk=gst&q=caml_enter_blocking_section#3ab73788b5f142a1

Actually we can see such an example of caml_{enter,leave}_blocking_sections in byterun/sys.c

CAMLprim value caml_sys_open(value path, value vflags, value vperm)
{
  CAMLparam3(path, vflags, vperm);
  int fd, flags, perm;
  char * p;

  p = caml_stat_alloc(caml_string_length(path) + 1);
  strcpy(p, String_val(path));
  flags = caml_convert_flag_list(vflags, sys_open_flags);
  perm = Int_val(vperm);
  /* open on a named FIFO can block (PR#1533) */
  caml_enter_blocking_section();
  fd = open(p, flags, perm);
  caml_leave_blocking_section();
  caml_stat_free(p);
  if (fd == -1) caml_sys_error(path);
#if defined(F_SETFD) && defined(FD_CLOEXEC)
  fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
  CAMLreturn(Val_long(fd));
}

Here, the open syscall is in the section, so that it may not block the other thread; open is a lengthyoperation in certain circumstances. It uses the file path given from the OCaml(path), but since path is in the OCaml heap, we cannot use it safely. The code escapes the contents of path to p, a C-malloc'ed memory before entering the section. Beware, this code demonstrates even CAMLparam'ed pointers may become unreliable due to the GC once we enter the section!!

There may be some other informative posts found in caml-list:
http://groups.google.com/group/fa.caml/search?group=fa.caml&q=caml_enter_blocking_section&qt_g=Search+this+group