From e84347fd70918c7f7d4135223d185ffd667faea9 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Sat, 24 Jun 2023 08:49:04 +0200 Subject: [PATCH] Create term_from_resource API This is equivalent to `enif_make_resource` but without allocation, so callers can handle allocation failures. `enif_make_resource` is a thin wrapper around it. Signed-off-by: Paul Guyot --- src/libAtomVM/resources.c | 19 ++----------------- src/libAtomVM/term.h | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/libAtomVM/resources.c b/src/libAtomVM/resources.c index d8e891818..c2ee5c2f8 100644 --- a/src/libAtomVM/resources.c +++ b/src/libAtomVM/resources.c @@ -97,25 +97,10 @@ int enif_release_resource(void *resource) return true; } -static inline term resource_to_term(struct RefcBinary *refc, Heap *heap) -{ - term *boxed_value = memory_heap_alloc(heap, TERM_BOXED_REFC_BINARY_SIZE); - boxed_value[0] = ((TERM_BOXED_REFC_BINARY_SIZE - 1) << 6) | TERM_BOXED_REFC_BINARY; - boxed_value[1] = (term) 0; // binary size, this is pre ERTS 9.0 (OTP-20.0) behavior - boxed_value[2] = (term) RefcNoFlags; - term ret = ((term) boxed_value) | TERM_BOXED_VALUE_TAG; - boxed_value[3] = (term) refc; - // Increment ref count and add the resource to the mso list - refc_binary_increment_refcount(refc); - heap->root->mso_list = term_list_init_prepend(boxed_value + 4, ret, heap->root->mso_list); - return ret; -} - ERL_NIF_TERM enif_make_resource(ErlNifEnv *env, void *obj) { - struct RefcBinary *refc = refc_binary_from_data(obj); - if (UNLIKELY(memory_erl_nif_env_ensure_free(env, TERM_BOXED_REFC_BINARY_SIZE) != MEMORY_GC_OK)) { + if (UNLIKELY(memory_erl_nif_env_ensure_free(env, TERM_BOXED_RESOURCE_SIZE) != MEMORY_GC_OK)) { AVM_ABORT(); } - return resource_to_term(refc, &env->heap); + return term_from_resource(obj, &env->heap); } diff --git a/src/libAtomVM/term.h b/src/libAtomVM/term.h index 58fb8bfed..7aa2edb05 100644 --- a/src/libAtomVM/term.h +++ b/src/libAtomVM/term.h @@ -66,6 +66,7 @@ extern "C" { #define TERM_BOXED_REFC_BINARY_SIZE 6 #define TERM_BOXED_BIN_MATCH_STATE_SIZE 4 #define TERM_BOXED_SUB_BINARY_SIZE 4 +#define TERM_BOXED_RESOURCE_SIZE TERM_BOXED_REFC_BINARY_SIZE #if TERM_BYTES == 8 #define REFC_BINARY_MIN 64 #define SUB_BINARY_MIN 16 @@ -1664,6 +1665,32 @@ static inline term term_get_sub_binary_ref(term t) return boxed_value[3]; } +/** + * @brief Create a resource on the heap. + * @details This function creats a resource (obtained from `enif_alloc_resource`) + * on the heap which must have `TERM_BOXED_RESOURCE_SIZE` free terms. + * + * @param resource resource obtained from `enif_alloc_resource` + * @param heap the heap to allocate the resource in + * @return a term pointing to the resource + */ +static inline term term_from_resource(void *resource, Heap *heap) +{ + // Resources are currently refc binaries with a size of 0 but may be + // references in the future. + struct RefcBinary *refc = refc_binary_from_data(resource); + term *boxed_value = memory_heap_alloc(heap, TERM_BOXED_REFC_BINARY_SIZE); + boxed_value[0] = ((TERM_BOXED_REFC_BINARY_SIZE - 1) << 6) | TERM_BOXED_REFC_BINARY; + boxed_value[1] = (term) 0; // binary size, this is pre ERTS 9.0 (OTP-20.0) behavior + boxed_value[2] = (term) RefcNoFlags; + term ret = ((term) boxed_value) | TERM_BOXED_VALUE_TAG; + boxed_value[3] = (term) refc; + // Increment ref count and add the resource to the mso list + refc_binary_increment_refcount(refc); + heap->root->mso_list = term_list_init_prepend(boxed_value + 4, ret, heap->root->mso_list); + return ret; +} + #ifdef __cplusplus } #endif