From 4f574f6500440e36920ef052e990f93763ad3721 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Wed, 8 Jan 2025 11:03:35 +0000 Subject: [PATCH 1/2] Stub implementation of new custom memory API --- runtime/bigarray.c | 8 +++++--- runtime/caml/custom.h | 11 +++++++++++ runtime/caml/memory.h | 4 ++-- runtime/caml/mlvalues.h | 1 + runtime/custom.c | 6 ++++++ runtime/memory.c | 13 ++++--------- runtime4/caml/custom.h | 11 +++++++++++ runtime4/caml/memory.h | 4 ++-- runtime4/custom.c | 6 ++++++ runtime4/memory.c | 13 ++++--------- 10 files changed, 52 insertions(+), 25 deletions(-) diff --git a/runtime/bigarray.c b/runtime/bigarray.c index 6a3043b6d1b..8296e4e0bde 100644 --- a/runtime/bigarray.c +++ b/runtime/bigarray.c @@ -251,7 +251,7 @@ caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim) uses_resources = ((flags & CAML_BA_MANAGED_MASK) == CAML_BA_MANAGED) && !(flags & CAML_BA_SUBARRAY); - res = caml_alloc_custom_mem(&caml_ba_ops, asize, uses_resources ? size : 0); + res = caml_alloc_custom_dep(&caml_ba_ops, asize, uses_resources ? size : 0); b = Caml_ba_array_val(res); b->data = data; b->num_dims = num_dims; @@ -291,9 +291,11 @@ CAMLexport void caml_ba_finalize(value v) case CAML_BA_MANAGED: if (b->proxy == NULL) { free(b->data); + caml_free_dependent_memory(v, caml_ba_byte_size(b)); } else { if (caml_atomic_refcount_decr(&b->proxy->refcount) == 1) { free(b->proxy->data); + caml_free_dependent_memory(v, b->proxy->size); free(b->proxy); } } @@ -620,6 +622,7 @@ CAMLexport uintnat caml_ba_deserialize(void * dst) caml_deserialize_error("input_value: size overflow for bigarray"); /* Allocate room for data */ b->data = malloc(size); + caml_alloc_dependent_memory(Custom_val_data (dst), size); if (b->data == NULL) caml_deserialize_error("input_value: out of memory for bigarray"); /* Read data */ @@ -1138,8 +1141,7 @@ static void caml_ba_update_proxy(struct caml_ba_array * b1, caml_atomic_refcount_init(&proxy->refcount, 2); /* initial refcount: 2 = original array + sub array */ proxy->data = b1->data; - proxy->size = - b1->flags & CAML_BA_MAPPED_FILE ? caml_ba_byte_size(b1) : 0; + proxy->size = caml_ba_byte_size(b1); b1->proxy = proxy; b2->proxy = proxy; } diff --git a/runtime/caml/custom.h b/runtime/caml/custom.h index 127d8247abd..112260b700a 100644 --- a/runtime/caml/custom.h +++ b/runtime/caml/custom.h @@ -67,6 +67,17 @@ CAMLextern value caml_alloc_custom_mem(const struct custom_operations * ops, uintnat size, /*size in bytes*/ mlsize_t mem /*memory consumed*/); + /* [caml_alloc_custom_dep] allocates a custom block with dependent memory + (memory outside the heap that will be reclaimed when the block is + finalized). If [mem] is greater than [custom_minor_max_size] (see gc.mli) + the block is allocated directly in the major heap. + The program must call [caml_free_dependent_memory] when the memory is + reclaimed. + */ +CAMLextern value caml_alloc_custom_dep(const struct custom_operations * ops, + uintnat size, /*size in bytes*/ + mlsize_t mem /*dep memory in bytes*/); + CAMLextern void caml_register_custom_operations(const struct custom_operations * ops); diff --git a/runtime/caml/memory.h b/runtime/caml/memory.h index 7c3359b7e86..5d379876f4b 100644 --- a/runtime/caml/memory.h +++ b/runtime/caml/memory.h @@ -40,8 +40,8 @@ CAMLextern value caml_alloc_local(mlsize_t, tag_t); CAMLextern void caml_adjust_gc_speed (mlsize_t, mlsize_t); CAMLextern void caml_adjust_minor_gc_speed (mlsize_t, mlsize_t); -CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); -CAMLextern void caml_free_dependent_memory (mlsize_t bsz); +CAMLextern void caml_alloc_dependent_memory (value v, mlsize_t bsz); +CAMLextern void caml_free_dependent_memory (value v, mlsize_t bsz); CAMLextern void caml_modify (volatile value *, value); CAMLextern void caml_modify_local (value obj, intnat i, value val); CAMLextern void caml_initialize (volatile value *, value); diff --git a/runtime/caml/mlvalues.h b/runtime/caml/mlvalues.h index 6df439a30bd..7d4aab23e08 100644 --- a/runtime/caml/mlvalues.h +++ b/runtime/caml/mlvalues.h @@ -527,6 +527,7 @@ CAMLextern int caml_is_double_array (value); /* 0 is false, 1 is true */ See [custom.h] for operations on method suites. */ #define Custom_tag 255 #define Data_custom_val(v) ((void *) (Op_val(v) + 1)) +#define Custom_val_data(d) (Val_op((value *)d - 1)) struct custom_operations; /* defined in [custom.h] */ /* Int32.t, Int64.t and Nativeint.t are represented as custom blocks. */ diff --git a/runtime/custom.c b/runtime/custom.c index 80f1191c08f..c988bec8241 100644 --- a/runtime/custom.c +++ b/runtime/custom.c @@ -130,6 +130,12 @@ CAMLexport value caml_alloc_custom_mem(const struct custom_operations * ops, return v; } +CAMLexport value caml_alloc_custom_dep(const struct custom_operations * ops, + uintnat size, mlsize_t mem) +{ + return caml_alloc_custom_mem(ops, size, mem); +} + struct custom_operations_list { const struct custom_operations * ops; struct custom_operations_list * next; diff --git a/runtime/memory.c b/runtime/memory.c index fade3ec6c55..d9c8fe49a02 100644 --- a/runtime/memory.c +++ b/runtime/memory.c @@ -236,19 +236,14 @@ CAMLexport CAMLweakdef void caml_modify (volatile value *fp, value val) free it. In both cases, you pass as argument the size (in bytes) of the block being allocated or freed. */ -CAMLexport void caml_alloc_dependent_memory (mlsize_t nbytes) +CAMLexport void caml_alloc_dependent_memory (value v, mlsize_t nbytes) { - Caml_state->dependent_size += nbytes / sizeof (value); - Caml_state->dependent_allocated += nbytes / sizeof (value); + /* No-op for now */ } -CAMLexport void caml_free_dependent_memory (mlsize_t nbytes) +CAMLexport void caml_free_dependent_memory (value v, mlsize_t nbytes) { - if (Caml_state->dependent_size < nbytes / sizeof (value)){ - Caml_state->dependent_size = 0; - }else{ - Caml_state->dependent_size -= nbytes / sizeof (value); - } + /* No-op for now */ } /* Use this function to tell the major GC to speed up when you use diff --git a/runtime4/caml/custom.h b/runtime4/caml/custom.h index 62dec5c6302..a625578c9d8 100644 --- a/runtime4/caml/custom.h +++ b/runtime4/caml/custom.h @@ -65,6 +65,17 @@ CAMLextern value caml_alloc_custom_mem(struct custom_operations * ops, uintnat size, /*size in bytes*/ mlsize_t mem /*memory consumed*/); + /* [caml_alloc_custom_dep] allocates a custom block with dependent memory + (memory outside the heap that will be reclaimed when the block is + finalized). If [mem] is greater than [custom_minor_max_size] (see gc.mli) + the block is allocated directly in the major heap. + The program must call [caml_free_dependent_memory] when the memory is + reclaimed. + */ +CAMLextern value caml_alloc_custom_dep(struct custom_operations * ops, + uintnat size, /*size in bytes*/ + mlsize_t mem /*dep memory in bytes*/); + CAMLextern void caml_register_custom_operations(struct custom_operations * ops); /* Global variable moved to Caml_state in 4.10 */ diff --git a/runtime4/caml/memory.h b/runtime4/caml/memory.h index e5204f92f96..913ff656cc9 100644 --- a/runtime4/caml/memory.h +++ b/runtime4/caml/memory.h @@ -57,8 +57,8 @@ CAMLextern value caml_alloc_shr_for_minor_gc (mlsize_t, tag_t, header_t); CAMLextern value caml_alloc_local(mlsize_t, tag_t); CAMLextern void caml_adjust_gc_speed (mlsize_t, mlsize_t); -CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); -CAMLextern void caml_free_dependent_memory (mlsize_t bsz); +CAMLextern void caml_alloc_dependent_memory (value v, mlsize_t bsz); +CAMLextern void caml_free_dependent_memory (value v, mlsize_t bsz); CAMLextern void caml_modify (value *, value); CAMLextern void caml_modify_local (value obj, intnat i, value val); CAMLextern void caml_initialize (value *, value); diff --git a/runtime4/custom.c b/runtime4/custom.c index 37d88f48cdc..4b2653edfc7 100644 --- a/runtime4/custom.c +++ b/runtime4/custom.c @@ -108,6 +108,12 @@ CAMLexport value caml_alloc_custom_mem(struct custom_operations * ops, return v; } +CAMLexport value caml_alloc_custom_dep(struct custom_operations * ops, + uintnat size, mlsize_t mem) +{ + return caml_alloc_custom_mem(ops, size, mem); +} + struct custom_operations_list { struct custom_operations * ops; struct custom_operations_list * next; diff --git a/runtime4/memory.c b/runtime4/memory.c index 1d2081d0bfb..0c770c1902d 100644 --- a/runtime4/memory.c +++ b/runtime4/memory.c @@ -587,19 +587,14 @@ CAMLexport value caml_alloc_shr_no_track_noexc (mlsize_t wosize, tag_t tag) free it. In both cases, you pass as argument the size (in bytes) of the block being allocated or freed. */ -CAMLexport void caml_alloc_dependent_memory (mlsize_t nbytes) +CAMLexport void caml_alloc_dependent_memory (value v, mlsize_t nbytes) { - caml_dependent_size += nbytes / sizeof (value); - caml_dependent_allocated += nbytes / sizeof (value); + /* No-op for now */ } -CAMLexport void caml_free_dependent_memory (mlsize_t nbytes) +CAMLexport void caml_free_dependent_memory (value v, mlsize_t nbytes) { - if (caml_dependent_size < nbytes / sizeof (value)){ - caml_dependent_size = 0; - }else{ - caml_dependent_size -= nbytes / sizeof (value); - } + /* No-op for now */ } /* Use this function to tell the major GC to speed up when you use From ae0daf669b317879420f771ba648d6ca6b504007 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Tue, 14 Jan 2025 10:18:36 +0000 Subject: [PATCH 2/2] comment --- runtime/custom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/custom.c b/runtime/custom.c index c988bec8241..503edf488ab 100644 --- a/runtime/custom.c +++ b/runtime/custom.c @@ -133,6 +133,8 @@ CAMLexport value caml_alloc_custom_mem(const struct custom_operations * ops, CAMLexport value caml_alloc_custom_dep(const struct custom_operations * ops, uintnat size, mlsize_t mem) { + /* For now, alias caml_alloc_custom_mem, but this implementation + is to be replaced */ return caml_alloc_custom_mem(ops, size, mem); }