469 lines
14 KiB
Diff
469 lines
14 KiB
Diff
From f8b761c62f177176dfe154a95824576eef740827 Mon Sep 17 00:00:00 2001
|
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
Date: Wed, 21 Jun 2023 19:07:00 +0100
|
|
Subject: [PATCH 08/16] ocaml: Replace caml_leave_blocking_section with
|
|
caml_acquire_runtime_system
|
|
|
|
Replace:
|
|
|
|
caml_leave_blocking_section
|
|
...
|
|
caml_enter_blocking_section
|
|
|
|
with the more sensibly named (and equivalent):
|
|
|
|
caml_acquire_runtime_system
|
|
...
|
|
caml_release_runtime_system
|
|
|
|
In addition we must release the runtime system just after caml_startup
|
|
and only acquire it around callbacks into OCaml code. (The reason for
|
|
this is only apparent in a later commit.)
|
|
|
|
OCaml 5 is more strict than earlier versions of OCaml and actually
|
|
implements the locks using pthread_mutex_t. So in OCaml 5 you will
|
|
see a deadlock error:
|
|
|
|
Fatal error: Fatal error during lock: Resource deadlock avoided
|
|
|
|
which was caused by attempting to double lock (ie. trying to acquire
|
|
the lock, when we already held it from caml_startup).
|
|
|
|
Also because of additional strictness we must acquire the lock even
|
|
before creating the stack frame with CAMLparam* functions.
|
|
---
|
|
plugins/ocaml/plugin.h | 16 ++++-----
|
|
plugins/ocaml/plugin.c | 75 +++++++++++++++++++++++-------------------
|
|
2 files changed, 49 insertions(+), 42 deletions(-)
|
|
|
|
diff --git a/plugins/ocaml/plugin.h b/plugins/ocaml/plugin.h
|
|
index 572c43c04..3d6d27db1 100644
|
|
--- a/plugins/ocaml/plugin.h
|
|
+++ b/plugins/ocaml/plugin.h
|
|
@@ -47,18 +47,18 @@ caml_alloc_initialized_string (mlsize_t len, const char *p)
|
|
#endif
|
|
|
|
/* For functions which call into OCaml code, call
|
|
- * caml_leave_blocking_section() to prevent other threads running,
|
|
- * then caml_enter_blocking_section() on return to C code. This macro
|
|
- * ensures that the calls are paired properly.
|
|
+ * caml_acquire_runtime_system ... caml_release_runtime_system around
|
|
+ * the code. This prevents other threads in the same domain running.
|
|
+ * The macro ensures that the calls are paired properly.
|
|
*/
|
|
-#define LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE() \
|
|
- __attribute__ ((unused, cleanup (cleanup_enter_blocking_section))) \
|
|
+#define ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE() \
|
|
+ __attribute__ ((unused, cleanup (cleanup_release_runtime_system))) \
|
|
int _unused; \
|
|
- caml_leave_blocking_section ()
|
|
+ caml_acquire_runtime_system ()
|
|
static inline void
|
|
-cleanup_enter_blocking_section (int *unused)
|
|
+cleanup_release_runtime_system (int *unused)
|
|
{
|
|
- caml_enter_blocking_section ();
|
|
+ caml_release_runtime_system ();
|
|
}
|
|
|
|
#endif /* NBDKIT_OCAML_PLUGIN_H */
|
|
diff --git a/plugins/ocaml/plugin.c b/plugins/ocaml/plugin.c
|
|
index 722b95e49..fe781f9af 100644
|
|
--- a/plugins/ocaml/plugin.c
|
|
+++ b/plugins/ocaml/plugin.c
|
|
@@ -64,6 +64,12 @@ constructor (void)
|
|
|
|
/* Initialize OCaml runtime. */
|
|
caml_startup (argv);
|
|
+
|
|
+ /* We need to release the runtime system here so other threads may
|
|
+ * use it. Before we call any OCaml callbacks we must acquire the
|
|
+ * runtime system again.
|
|
+ */
|
|
+ caml_release_runtime_system ();
|
|
}
|
|
|
|
/* Instead of using the NBDKIT_REGISTER_PLUGIN macro, we construct the
|
|
@@ -113,7 +119,7 @@ plugin_init (void)
|
|
static void
|
|
load_wrapper (void)
|
|
{
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
caml_callback (load_fn, Val_unit);
|
|
}
|
|
|
|
@@ -123,8 +129,9 @@ load_wrapper (void)
|
|
static void
|
|
unload_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
+
|
|
if (unload_fn) {
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
caml_callback (unload_fn, Val_unit);
|
|
}
|
|
|
|
@@ -139,9 +146,9 @@ unload_wrapper (void)
|
|
static void
|
|
dump_plugin_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (dump_plugin_fn, Val_unit);
|
|
if (Is_exception_result (rv))
|
|
@@ -152,9 +159,9 @@ dump_plugin_wrapper (void)
|
|
static int
|
|
config_wrapper (const char *key, const char *val)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal3 (keyv, valv, rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
keyv = caml_copy_string (key);
|
|
valv = caml_copy_string (val);
|
|
@@ -171,9 +178,9 @@ config_wrapper (const char *key, const char *val)
|
|
static int
|
|
config_complete_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (config_complete_fn, Val_unit);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -187,9 +194,9 @@ config_complete_wrapper (void)
|
|
static int
|
|
thread_model_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (thread_model_fn, Val_unit);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -203,9 +210,9 @@ thread_model_wrapper (void)
|
|
static int
|
|
get_ready_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (get_ready_fn, Val_unit);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -219,9 +226,9 @@ get_ready_wrapper (void)
|
|
static int
|
|
after_fork_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (after_fork_fn, Val_unit);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -235,9 +242,9 @@ after_fork_wrapper (void)
|
|
static void
|
|
cleanup_wrapper (void)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (cleanup_fn, Val_unit);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -251,9 +258,9 @@ cleanup_wrapper (void)
|
|
static int
|
|
preconnect_wrapper (int readonly)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (preconnect_fn, Val_bool (readonly));
|
|
if (Is_exception_result (rv)) {
|
|
@@ -267,9 +274,9 @@ preconnect_wrapper (int readonly)
|
|
static int
|
|
list_exports_wrapper (int readonly, int is_tls, struct nbdkit_exports *exports)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal2 (rv, v);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback2_exn (list_exports_fn, Val_bool (readonly),
|
|
Val_bool (is_tls));
|
|
@@ -299,10 +306,10 @@ list_exports_wrapper (int readonly, int is_tls, struct nbdkit_exports *exports)
|
|
static const char *
|
|
default_export_wrapper (int readonly, int is_tls)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
const char *name;
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback2_exn (default_export_fn, Val_bool (readonly),
|
|
Val_bool (is_tls));
|
|
@@ -318,10 +325,10 @@ default_export_wrapper (int readonly, int is_tls)
|
|
static void *
|
|
open_wrapper (int readonly)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
value *ret;
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (open_fn, Val_bool (readonly));
|
|
if (Is_exception_result (rv)) {
|
|
@@ -341,9 +348,9 @@ open_wrapper (int readonly)
|
|
static void
|
|
close_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (close_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -360,10 +367,10 @@ close_wrapper (void *h)
|
|
static const char *
|
|
export_description_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
const char *desc;
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (export_description_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -378,10 +385,10 @@ export_description_wrapper (void *h)
|
|
static int64_t
|
|
get_size_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
int64_t r;
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (get_size_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -397,11 +404,11 @@ static int
|
|
block_size_wrapper (void *h,
|
|
uint32_t *minimum, uint32_t *preferred, uint32_t *maximum)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
int i;
|
|
int64_t i64;
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (block_size_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -439,9 +446,9 @@ block_size_wrapper (void *h,
|
|
static int
|
|
can_write_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_write_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -455,9 +462,9 @@ can_write_wrapper (void *h)
|
|
static int
|
|
can_flush_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_flush_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -471,9 +478,9 @@ can_flush_wrapper (void *h)
|
|
static int
|
|
is_rotational_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (is_rotational_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -487,9 +494,9 @@ is_rotational_wrapper (void *h)
|
|
static int
|
|
can_trim_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_trim_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -503,9 +510,9 @@ can_trim_wrapper (void *h)
|
|
static int
|
|
can_zero_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_zero_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -519,9 +526,9 @@ can_zero_wrapper (void *h)
|
|
static int
|
|
can_fua_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_fua_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -535,9 +542,9 @@ can_fua_wrapper (void *h)
|
|
static int
|
|
can_fast_zero_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_fast_zero_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -551,9 +558,9 @@ can_fast_zero_wrapper (void *h)
|
|
static int
|
|
can_cache_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_cache_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -567,9 +574,9 @@ can_cache_wrapper (void *h)
|
|
static int
|
|
can_extents_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_extents_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -583,9 +590,9 @@ can_extents_wrapper (void *h)
|
|
static int
|
|
can_multi_conn_wrapper (void *h)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal1 (rv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
rv = caml_callback_exn (can_multi_conn_fn, *(value *) h);
|
|
if (Is_exception_result (rv)) {
|
|
@@ -629,10 +636,10 @@ static int
|
|
pread_wrapper (void *h, void *buf, uint32_t count, uint64_t offset,
|
|
uint32_t flags)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal4 (rv, countv, offsetv, flagsv);
|
|
mlsize_t len;
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
countv = Val_int (count);
|
|
offsetv = caml_copy_int64 (offset);
|
|
@@ -659,9 +666,9 @@ static int
|
|
pwrite_wrapper (void *h, const void *buf, uint32_t count, uint64_t offset,
|
|
uint32_t flags)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal4 (rv, strv, offsetv, flagsv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
strv = caml_alloc_initialized_string (count, buf);
|
|
offsetv = caml_copy_int64 (offset);
|
|
@@ -680,9 +687,9 @@ pwrite_wrapper (void *h, const void *buf, uint32_t count, uint64_t offset,
|
|
static int
|
|
flush_wrapper (void *h, uint32_t flags)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal2 (rv, flagsv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
flagsv = Val_flags (flags);
|
|
|
|
@@ -698,9 +705,9 @@ flush_wrapper (void *h, uint32_t flags)
|
|
static int
|
|
trim_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal4 (rv, countv, offsetv, flagsv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
countv = caml_copy_int64 (count);
|
|
offsetv = caml_copy_int64 (offset);
|
|
@@ -719,9 +726,9 @@ trim_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags)
|
|
static int
|
|
zero_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal4 (rv, countv, offsetv, flagsv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
countv = caml_copy_int64 (count);
|
|
offsetv = caml_copy_int64 (offset);
|
|
@@ -741,9 +748,9 @@ static int
|
|
extents_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags,
|
|
struct nbdkit_extents *extents)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal5 (rv, countv, offsetv, flagsv, v);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
countv = caml_copy_int64 (count);
|
|
offsetv = caml_copy_int64 (offset);
|
|
@@ -781,9 +788,9 @@ extents_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags,
|
|
static int
|
|
cache_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags)
|
|
{
|
|
+ ACQUIRE_RUNTIME_FOR_CURRENT_SCOPE ();
|
|
CAMLparam0 ();
|
|
CAMLlocal4 (rv, countv, offsetv, flagsv);
|
|
- LEAVE_BLOCKING_SECTION_FOR_CURRENT_SCOPE ();
|
|
|
|
countv = caml_copy_int64 (count);
|
|
offsetv = caml_copy_int64 (offset);
|
|
--
|
|
2.41.0
|
|
|