diff options
Diffstat (limited to 'memory_view.c')
| -rw-r--r-- | memory_view.c | 163 |
1 files changed, 77 insertions, 86 deletions
diff --git a/memory_view.c b/memory_view.c index 5d6ef14b3a..2de756d681 100644 --- a/memory_view.c +++ b/memory_view.c @@ -9,8 +9,9 @@ #include "internal.h" #include "internal/hash.h" #include "internal/variable.h" -#include "internal/util.h" #include "ruby/memory_view.h" +#include "ruby/util.h" +#include "vm_sync.h" #if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG # define INTPTR2NUM LL2NUM @@ -30,6 +31,7 @@ // Exported Object Registry +static st_table *exported_object_table = NULL; VALUE rb_memory_view_exported_object_registry = Qundef; static int @@ -42,55 +44,35 @@ exported_object_registry_mark_key_i(st_data_t key, st_data_t value, st_data_t da static void exported_object_registry_mark(void *ptr) { - st_table *table = ptr; - st_foreach(table, exported_object_registry_mark_key_i, 0); + // Don't use RB_VM_LOCK_ENTER here. It is unnecessary during GC. + st_foreach(exported_object_table, exported_object_registry_mark_key_i, 0); } static void exported_object_registry_free(void *ptr) { - st_table *table = ptr; - st_clear(table); - st_free_table(table); + RB_VM_LOCKING() { + st_clear(exported_object_table); + st_free_table(exported_object_table); + exported_object_table = NULL; + } } const rb_data_type_t rb_memory_view_exported_object_registry_data_type = { "memory_view/exported_object_registry", { - exported_object_registry_mark, - exported_object_registry_free, - 0, + exported_object_registry_mark, + exported_object_registry_free, + 0, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED }; -static void -init_exported_object_registry(void) -{ - if (rb_memory_view_exported_object_registry != Qundef) { - return; - } - - st_table *table = rb_init_identtable(); - VALUE obj = TypedData_Wrap_Struct( - 0, &rb_memory_view_exported_object_registry_data_type, table); - rb_gc_register_mark_object(obj); - rb_memory_view_exported_object_registry = obj; -} - -static inline st_table * -get_exported_object_table(void) -{ - st_table *table; - TypedData_Get_Struct(rb_memory_view_exported_object_registry, st_table, - &rb_memory_view_exported_object_registry_data_type, - table); - return table; -} - static int -update_exported_object_ref_count(st_data_t *key, st_data_t *val, st_data_t arg, int existing) +exported_object_add_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing) { + ASSERT_vm_locking(); + if (existing) { *val += 1; } @@ -100,38 +82,35 @@ update_exported_object_ref_count(st_data_t *key, st_data_t *val, st_data_t arg, return ST_CONTINUE; } +static int +exported_object_dec_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing) +{ + ASSERT_vm_locking(); + + if (existing) { + *val -= 1; + if (*val == 0) { + return ST_DELETE; + } + } + return ST_CONTINUE; +} + static void register_exported_object(VALUE obj) { - if (rb_memory_view_exported_object_registry == Qundef) { - init_exported_object_registry(); + RB_VM_LOCKING() { + st_update(exported_object_table, (st_data_t)obj, exported_object_add_ref, 0); + RB_OBJ_WRITTEN(rb_memory_view_exported_object_registry, Qundef, obj); } - - st_table *table = get_exported_object_table(); - - st_update(table, (st_data_t)obj, update_exported_object_ref_count, 0); } static void unregister_exported_object(VALUE obj) { - if (rb_memory_view_exported_object_registry == Qundef) { - return; - } - - st_table *table = get_exported_object_table(); - - st_data_t count; - if (!st_lookup(table, (st_data_t)obj, &count)) { - return; - } - - if (--count == 0) { - st_data_t key = (st_data_t)obj; - st_delete(table, &key, &count); - } - else { - st_insert(table, (st_data_t)obj, count); + RB_VM_LOCKING() { + if (exported_object_table) + st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0); } } @@ -142,16 +121,17 @@ static ID id_memory_view; static const rb_data_type_t memory_view_entry_data_type = { "memory_view/entry", { - 0, - 0, - 0, + 0, + 0, + 0, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; /* Register memory view functions for the given class */ bool -rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry) { +rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry) +{ Check_Type(klass, T_CLASS); VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil); if (! NIL_P(entry_obj)) { @@ -217,12 +197,12 @@ rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_si } /* Initialize view to expose a simple byte array */ -int +bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly) { view->obj = obj; view->data = data; - view->len = len; + view->byte_size = len; view->readonly = readonly; view->format = NULL; view->item_size = 1; @@ -232,9 +212,9 @@ rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, view->shape = NULL; view->strides = NULL; view->sub_offsets = NULL; - *((void **)&view->private) = NULL; + view->private_data = NULL; - return 1; + return true; } #ifdef HAVE_TRUE_LONG_LONG @@ -395,7 +375,8 @@ get_format_size(const char *format, bool *native_p, ssize_t *alignment, endianne } static inline ssize_t -calculate_padding(ssize_t total, ssize_t alignment_size) { +calculate_padding(ssize_t total, ssize_t alignment_size) +{ if (alignment_size > 1) { ssize_t res = total % alignment_size; if (res > 0) { @@ -419,7 +400,7 @@ rb_memory_view_parse_item_format(const char *format, ssize_t max_alignment_size = 0; const char *p = format; - if (*p == '|') { // alginment specifier + if (*p == '|') { // alignment specifier alignment = true; ++format; ++p; @@ -694,7 +675,7 @@ extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *m return LL2NUM(val.ll); } else { -#if SIZEOF_INT64_t == SIZEOF_LONG +#if SIZEOF_INT64_T == SIZEOF_LONG return LONG2NUM(val.i64); #else return LL2NUM(val.i64); @@ -706,7 +687,7 @@ extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *m return ULL2NUM(val.ull); } else { -#if SIZEOF_UINT64_t == SIZEOF_LONG +#if SIZEOF_UINT64_T == SIZEOF_LONG return ULONG2NUM(val.u64); #else return ULL2NUM(val.u64); @@ -771,7 +752,9 @@ rb_memory_view_prepare_item_desc(rb_memory_view_t *view) { if (view->item_desc.components == NULL) { const char *err; - ssize_t n = rb_memory_view_parse_item_format(view->format, &view->item_desc.components, &view->item_desc.length, &err); + rb_memory_view_item_component_t **p_components = + (rb_memory_view_item_component_t **)&view->item_desc.components; + ssize_t n = rb_memory_view_parse_item_format(view->format, p_components, &view->item_desc.length, &err); if (n < 0) { rb_raise(rb_eRuntimeError, "Unable to parse item format at %"PRIdSIZE" in \"%s\"", @@ -802,7 +785,7 @@ lookup_memory_view_entry(VALUE klass) { VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil); while (NIL_P(entry_obj)) { - klass = rb_class_get_superclass(klass); + klass = rb_class_superclass(klass); if (klass == rb_cBasicObject || klass == rb_cObject) return NULL; @@ -817,7 +800,7 @@ lookup_memory_view_entry(VALUE klass) } /* Examine whether the given object supports memory view. */ -int +bool rb_memory_view_available_p(VALUE obj) { VALUE klass = CLASS_OF(obj); @@ -825,56 +808,64 @@ rb_memory_view_available_p(VALUE obj) if (entry) return (* entry->available_p_func)(obj); else - return 0; + return false; } /* Obtain a memory view from obj, and substitute the information to view. */ -int +bool rb_memory_view_get(VALUE obj, rb_memory_view_t* view, int flags) { VALUE klass = CLASS_OF(obj); const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass); if (entry) { if (!(*entry->available_p_func)(obj)) { - return 0; + return false; } - int rv = (*entry->get_func)(obj, view, flags); + bool rv = (*entry->get_func)(obj, view, flags); if (rv) { + view->_memory_view_entry = entry; register_exported_object(view->obj); } return rv; } else - return 0; + return false; } /* Release the memory view obtained from obj. */ -int +bool rb_memory_view_release(rb_memory_view_t* view) { - VALUE klass = CLASS_OF(view->obj); - const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass); + const rb_memory_view_entry_t *entry = view->_memory_view_entry; if (entry) { - int rv = 1; + bool rv = true; if (entry->release_func) { rv = (*entry->release_func)(view->obj, view); } if (rv) { unregister_exported_object(view->obj); view->obj = Qnil; - if (view->item_desc.components) { - xfree(view->item_desc.components); - } + SIZED_FREE_N((rb_memory_view_item_component_t *)view->item_desc.components, view->item_desc.length); } return rv; } else - return 0; + return false; } void Init_MemoryView(void) { + exported_object_table = rb_init_identtable(); + + // exported_object_table is referred through rb_memory_view_exported_object_registry + // in -test-/memory_view extension. + VALUE obj = TypedData_Wrap_Struct( + 0, &rb_memory_view_exported_object_registry_data_type, + exported_object_table); + rb_vm_register_global_object(obj); + rb_memory_view_exported_object_registry = obj; + id_memory_view = rb_intern_const("__memory_view__"); } |
