OCaml 5.0 and C interface

Hello,

I have some code using 2 threads (one for openGL graphics, the other for computation) that
release the runtime lock in the EGL C mainloop and reacquire the lock when performing OCaml callback.
The two thread communicated via a queue protected by a mutex and a condition.

Visibly, juste replacing Thread.create with Domain.spawn is not sufficient. I get some errors as if two distinct system threads were doing OpenGL call (which is not permitted).

I also tried without success using

  • CAMLextern void caml_acquire_domain_lock(void);
  • CAMLextern void caml_release_domain_lock(void);

instead of acquiring the global lock.

What is the proper way to use OCaml 5.0 in this setting where all openGL call must be done by the same system thread?

Cheers,
Christophe

I don’t think we can say much without the code / a repro case. Is it available publicly somewhere/

What is the proper way to use OCaml 5.0 in this setting where all openGL call must be done by the same system thread?

I believe the answer is the same as with OCaml 4: if all OpenGL must be done by the same thread, you should ensure that only a single thread (and domain) runs OpenGL code.

But you had existing code that already provides this guarantee, and it’s not clear from your description why moving to OCaml 5 would suddenly break it.

Thanks for the answer, if there should be no change, I will try to investigate in that direction. May be there is already a bug but which is not triggered when using thread.

Still it is not clear to me what is the semantics and differences of the two functions releasing/acquiring lock?

Strange: I could not reproduce the problem and the change only involves 2 lines in ML and removing library threads in dune. Maybe I did a silly thing at the first try…

However, Unix.times returns the combined time of all children … And I would like only the time of the current domain.
Is this available?

Still it is not clear to me what is the semantics and differences of the two functions releasing/acquiring lock?

My understanding:

  • domains are mappd to pthread threads running OCaml code in parallel
  • threads are also mapped to pthread threads, and each thread belong to a given domain; for a given domain, only one of its threads can run OCaml code at a given point in time, and this is ensured by having threads take and release the “domain lock”

Compared to OCaml 4:

  • “domain locks” generalize the “runtime lock”, but now there is one lock per domain
  • when there is a single domain (but possibly several threads) you have exactly the same behavior as before

The specification of the domain lock is exactly the same as for the runtime lock in OCaml 4: you can release it before blocking C calls, but you must ensure that no OCaml code (or FFI access to the OCaml runtime) happens before you take the lock again.

I read the doc in caml/*.h ;-). From what I see, one should call
caml_acquire_runtime_system/caml_release_runtime_system declared in threads.h both on OCaml 4 and OCaml 5.

and the undocumented functions in domain.h

CAMLextern void caml_bt_enter_ocaml(void);
CAMLextern void caml_bt_exit_ocaml(void);
CAMLextern void caml_acquire_domain_lock(void);
CAMLextern void caml_release_domain_lock(void);

do not need to be called by the user ?

The user should never call functions from domain.h. In fact those are protected with the CAML_INTERNALS guard.

The question is on which domain your thread runs. Currently this is decided once and for all at thread creation, and the only way to create threads on domains non-zero is from OCaml code (no caml_register_c_thread).

1 Like