From 906ed413f5de1a387f679bb2db759af7cbe6d479 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Fri, 20 Jan 2017 03:28:22 -0500 Subject: [PATCH] [runtime] Fix locking issues while accessing MonoClass bitfields. (#4275) --- mono/metadata/class-accessors.c | 10 ++++++++++ mono/metadata/class-internals.h | 9 +++++---- mono/metadata/class.c | 23 +++++++++++++---------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/mono/metadata/class-accessors.c b/mono/metadata/class-accessors.c index 90ab1a35cf9..db74d5ac5c8 100644 --- a/mono/metadata/class-accessors.c +++ b/mono/metadata/class-accessors.c @@ -374,3 +374,13 @@ mono_class_set_declsec_flags (MonoClass *class, guint32 value) prop->value = value; mono_property_bag_add (&class->infrequent_data, prop); } + +void +mono_class_set_is_com_object (MonoClass *klass) +{ +#ifndef DISABLE_COM + mono_loader_lock (); + klass->is_com_object = 1; + mono_loader_unlock (); +#endif +} diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index e92756ed58a..57a9a145e9f 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -276,8 +276,8 @@ struct _MonoClass { * to 1, because we know the instance size now. After that we * initialise all static fields. */ - /* size_inited is accessed without locks, so it needs a memory barrier */ - /* All flag bits should be written while holding the loader lock */ + + /* ALL BITFIELDS SHOULD BE WRITTEN WHILE HOLDING THE LOADER LOCK */ guint size_inited : 1; guint valuetype : 1; /* derives from System.ValueType */ guint enumtype : 1; /* derives from System.Enum */ @@ -434,10 +434,8 @@ int mono_class_interface_match (const uint8_t *bitmap, int id); #ifdef DISABLE_COM #define mono_class_is_com_object(klass) (FALSE) -#define mono_class_set_is_com_object(klass) do {} while (0) #else #define mono_class_is_com_object(klass) ((klass)->is_com_object) -#define mono_class_set_is_com_object(klass) do { (klass)->is_com_object = 1; } while (0) #endif @@ -1514,6 +1512,9 @@ mono_class_get_declsec_flags (MonoClass *class); void mono_class_set_declsec_flags (MonoClass *class, guint32 value); +void +mono_class_set_is_com_object (MonoClass *klass); + /*Now that everything has been defined, let's include the inline functions */ #include diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 27b3729fbc8..fd9f2e98987 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -1651,6 +1651,7 @@ static void init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info) { if (cached_info) { + mono_loader_lock (); klass->instance_size = cached_info->instance_size; klass->sizes.class_size = cached_info->class_size; klass->packing_size = cached_info->packing_size; @@ -1659,6 +1660,7 @@ init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info) klass->has_references = cached_info->has_references; klass->has_static_refs = cached_info->has_static_refs; klass->no_special_static_fields = cached_info->no_special_static_fields; + mono_loader_unlock (); } else { if (!klass->size_inited) @@ -5080,16 +5082,14 @@ mono_class_has_finalizer (MonoClass *klass) } } - mono_image_lock (klass->image); - + mono_loader_lock (); if (!klass->has_finalize_inited) { klass->has_finalize = has_finalize ? 1 : 0; mono_memory_barrier (); klass->has_finalize_inited = TRUE; } - - mono_image_unlock (klass->image); + mono_loader_unlock (); return klass->has_finalize; } @@ -5742,6 +5742,7 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd) mono_error_cleanup (&error); } } + mono_loader_lock (); if (klass->parent) mono_class_setup_parent (klass, klass->parent); @@ -5749,6 +5750,7 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd) klass->cast_class = gtd->cast_class; klass->element_class = gtd->element_class; } + mono_loader_unlock (); } gboolean @@ -9215,8 +9217,12 @@ setup_nested_types (MonoClass *klass) if (klass->nested_classes_inited) return; - if (!klass->type_token) + if (!klass->type_token) { + mono_loader_lock (); klass->nested_classes_inited = TRUE; + mono_loader_unlock (); + return; + } i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1); classes = NULL; @@ -10435,8 +10441,7 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) interfaces = NULL; } - mono_image_lock (klass->image); - + mono_loader_lock (); if (!klass->interfaces_inited) { klass->interface_count = interface_count; klass->interfaces = interfaces; @@ -10445,8 +10450,7 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error) klass->interfaces_inited = TRUE; } - - mono_image_unlock (klass->image); + mono_loader_unlock (); } static void @@ -10527,7 +10531,6 @@ mono_field_resolve_flags (MonoClassField *field) MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL; int field_idx = field - klass->fields; - if (gtd) { MonoClassField *gfield = >d->fields [field_idx]; return mono_field_get_flags (gfield); -- 2.11.4.GIT