From 49546acac44bf389dc5bc74d45aa23c29937e850 Mon Sep 17 00:00:00 2001 From: cherusker Date: Wed, 16 Aug 2017 00:08:01 +0200 Subject: [PATCH 1/5] Update unlocked.h - add functions for upcoming commits --- mono/utils/unlocked.h | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/mono/utils/unlocked.h b/mono/utils/unlocked.h index b09ba492a683..19114ac61051 100644 --- a/mono/utils/unlocked.h +++ b/mono/utils/unlocked.h @@ -3,6 +3,12 @@ * Contains inline functions to explicitly mark data races that should not be changed. * This way, instruments like Clang's ThreadSanitizer can be told to ignore very specific instructions. * + * Please keep this file and its methods organised: + * * Increment, Decrement, Add, Subtract, Write, Read + * * gint32 (""), guint32 ("Unsigned"), + * gint64 ("64"), guint64 ("Unsigned64"), + * gsize ("Size"), gboolean ("Bool") + * * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ @@ -26,17 +32,10 @@ UnlockedIncrement (gint32 *val) } MONO_UNLOCKED_ATTRS -gint64 -UnlockedIncrement64 (gint64 *val) -{ - return ++*val; -} - -MONO_UNLOCKED_ATTRS -gsize -UnlockedIncrementSize (gsize *val) +gint32 +UnlockedAdd (gint32 *dest, gint32 add) { - return ++*val; + return *dest += add; } MONO_UNLOCKED_ATTRS @@ -53,6 +52,20 @@ UnlockedSubtract64 (gint64 *dest, gint64 sub) return *dest -= sub; } +MONO_UNLOCKED_ATTRS +void +UnlockedWrite (gint32 *dest, gint32 val) +{ + *dest = val; +} + +MONO_UNLOCKED_ATTRS +gint32 +UnlockedRead (gint32 *src) +{ + return *src; +} + MONO_UNLOCKED_ATTRS gint64 UnlockedRead64 (gint64 *src) From ccceee2d9e3871057d7bddaacc56fd3f832a2979 Mon Sep 17 00:00:00 2001 From: cherusker Date: Fri, 18 Aug 2017 19:20:44 +0200 Subject: [PATCH 2/5] Update atomic.h - add `InterlockedWriteBool ()` which will be used in an upcoming commit --- mono/utils/atomic.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mono/utils/atomic.h b/mono/utils/atomic.h index decab93c7a96..a3dd65a4dc28 100755 --- a/mono/utils/atomic.h +++ b/mono/utils/atomic.h @@ -464,4 +464,13 @@ extern void InterlockedWritePointer(volatile gpointer *dst, gpointer val); #define InterlockedAddP(p,add) InterlockedAdd64 ((volatile gint64*)p, (gint64)add) #endif +/* The following functions cannot be found on any platform, and thus they can be declared without further existence checks */ + +static inline void +InterlockedWriteBool (volatile gboolean *dest, gboolean val) +{ + /* both, gboolean and gint32, are int32_t; the purpose of these casts is to make things explicit */ + InterlockedWrite ((volatile gint32 *)dest, (gint32)val); +} + #endif /* _WAPI_ATOMIC_H_ */ From 2e829a42705d9c65196595933b53681b055df2bc Mon Sep 17 00:00:00 2001 From: cherusker Date: Wed, 16 Aug 2017 00:05:40 +0200 Subject: [PATCH 3/5] Tell TSan to ignore `MonoStats` - change field types from `size_t` to `gint32` - GLib types are preferably used throughout Mono - `Interlocked* ()` functions exist for `gint32` already - `gint32` is preferred to `gint64` when looking at 32-bit machines - the extra 2,147,483,648 (0 <= `size_t` <= 4,294,967,295; -2,147,483,648 <= `gint32` <= 2,147,483,647) don't seem to matter when looking at the average values of these variables - remove unused fields; some fields have been moved to GCStats (`*_gc_*`) - use `G_*_FORMAT` to correctly print `g*` types --- mono/metadata/class-internals.h | 58 ++++++++++++++------------------- mono/metadata/class.c | 14 ++++---- mono/metadata/jit-info.c | 7 ++-- mono/metadata/loader.c | 2 +- mono/metadata/object.c | 31 +++++++++--------- mono/mini/driver.c | 4 +-- mono/mini/mini-amd64.c | 3 +- mono/mini/mini-arm.c | 3 +- mono/mini/mini-mips.c | 3 +- mono/mini/mini-ppc.c | 3 +- mono/mini/mini-runtime.c | 58 ++++++++++++++++++--------------- mono/mini/mini-s390x.c | 3 +- mono/mini/mini-sparc.c | 3 +- mono/mini/mini-x86.c | 3 +- mono/mini/mini.c | 8 ++--- 15 files changed, 105 insertions(+), 98 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 909e950c6c93..67f360e975e3 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -756,39 +756,31 @@ typedef struct { #define MONO_SIZEOF_REMOTE_CLASS (sizeof (MonoRemoteClass) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P) typedef struct { - guint64 new_object_count; - gsize initialized_class_count; - gsize generic_vtable_count; - size_t used_class_count; - size_t method_count; - size_t class_vtable_size; - size_t class_static_data_size; - size_t generic_instance_count; - gsize generic_class_count; - gsize inflated_method_count; - size_t inflated_method_count_2; - gsize inflated_type_count; - size_t generics_metadata_size; - size_t delegate_creations; - size_t imt_tables_size; - size_t imt_number_of_tables; - size_t imt_number_of_methods; - size_t imt_used_slots; - size_t imt_slots_with_collisions; - size_t imt_max_collisions_in_slot; - size_t imt_method_count_when_max_collisions; - size_t imt_trampolines_size; - size_t jit_info_table_insert_count; - size_t jit_info_table_remove_count; - size_t jit_info_table_lookup_count; - size_t generics_sharable_methods; - size_t generics_unsharable_methods; - size_t generics_shared_methods; - size_t gsharedvt_methods; - size_t minor_gc_count; - size_t major_gc_count; - size_t minor_gc_time_usecs; - size_t major_gc_time_usecs; + gint32 initialized_class_count; + gint32 generic_vtable_count; + gint32 used_class_count; + gint32 method_count; + gint32 class_vtable_size; + gint32 class_static_data_size; + gint32 generic_class_count; + gint32 inflated_method_count; + gint32 inflated_type_count; + gint32 delegate_creations; + gint32 imt_tables_size; + gint32 imt_number_of_tables; + gint32 imt_number_of_methods; + gint32 imt_used_slots; + gint32 imt_slots_with_collisions; + gint32 imt_max_collisions_in_slot; + gint32 imt_method_count_when_max_collisions; + gint32 imt_trampolines_size; + gint32 jit_info_table_insert_count; + gint32 jit_info_table_remove_count; + gint32 jit_info_table_lookup_count; + gint32 generics_sharable_methods; + gint32 generics_unsharable_methods; + gint32 generics_shared_methods; + gint32 gsharedvt_methods; gboolean enabled; } MonoStats; diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 2e3dcd73856b..6492fd6ca214 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -865,7 +865,7 @@ mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, } } - UnlockedIncrementSize (&mono_stats.inflated_type_count); + UnlockedIncrement (&mono_stats.inflated_type_count); return inflated; } @@ -929,7 +929,7 @@ mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoG if (!inflated) return type; - UnlockedIncrementSize (&mono_stats.inflated_type_count); + UnlockedIncrement (&mono_stats.inflated_type_count); return inflated; } @@ -1090,7 +1090,7 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k return (MonoMethod*)cached; } - UnlockedIncrementSize (&mono_stats.inflated_method_count); + UnlockedIncrement (&mono_stats.inflated_method_count); inflated_methods_size += sizeof (MonoMethodInflated); @@ -3569,7 +3569,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup) return; } - UnlockedIncrementSize (&mono_stats.generic_vtable_count); + UnlockedIncrement (&mono_stats.generic_vtable_count); in_setup = g_list_prepend (in_setup, klass); if (mono_class_is_ginst (klass)) { @@ -4903,7 +4903,7 @@ mono_class_init (MonoClass *klass) goto leave; } - UnlockedIncrementSize (&mono_stats.initialized_class_count); + UnlockedIncrement (&mono_stats.initialized_class_count); if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) { MonoClass *gklass = mono_class_get_generic_class (klass)->container_class; @@ -5048,10 +5048,10 @@ mono_class_init (MonoClass *klass) return !mono_class_has_failure (klass); } - UnlockedIncrementSize (&mono_stats.initialized_class_count); + UnlockedIncrement (&mono_stats.initialized_class_count); if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) - UnlockedIncrementSize (&mono_stats.generic_class_count); + UnlockedIncrement (&mono_stats.generic_class_count); if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes)) klass->nested_classes_inited = TRUE; diff --git a/mono/metadata/jit-info.c b/mono/metadata/jit-info.c index 085fb67a3759..3344679e8123 100644 --- a/mono/metadata/jit-info.c +++ b/mono/metadata/jit-info.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -263,7 +264,7 @@ mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_ MonoJitInfo *ji, *module_ji; MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); - ++mono_stats.jit_info_table_lookup_count; + UnlockedIncrement (&mono_stats.jit_info_table_lookup_count); /* First we have to get the domain's jit_info_table. This is complicated by the fact that a writer might substitute a @@ -654,7 +655,7 @@ mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) mono_domain_lock (domain); - ++mono_stats.jit_info_table_insert_count; + UnlockedIncrement (&mono_stats.jit_info_table_insert_count); jit_info_table_add (domain, &domain->jit_info_table, ji); @@ -738,7 +739,7 @@ mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji) mono_domain_lock (domain); table = domain->jit_info_table; - ++mono_stats.jit_info_table_remove_count; + UnlockedIncrement (&mono_stats.jit_info_table_remove_count); jit_info_table_remove (table, ji); diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index bf35693b83b1..0cd4e07b7395 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -1658,7 +1658,7 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, methods_size += sizeof (MonoMethod); } - mono_stats.method_count ++; + InterlockedIncrement (&mono_stats.method_count); result->slot = -1; result->klass = klass; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index ad2a0e125879..4ebc52bca25f 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -49,6 +49,7 @@ #include #include "cominterop.h" #include +#include static void get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error); @@ -1217,12 +1218,12 @@ add_imt_builder_entry (MonoImtBuilderEntry **imt_builder, MonoMethod *method, gu if (imt_builder [imt_slot] != NULL) { entry->children = imt_builder [imt_slot]->children + 1; if (entry->children == 1) { - mono_stats.imt_slots_with_collisions++; + UnlockedIncrement (&mono_stats.imt_slots_with_collisions); *imt_collisions_bitmap |= (1 << imt_slot); } } else { entry->children = 0; - mono_stats.imt_used_slots++; + UnlockedIncrement (&mono_stats.imt_used_slots); } imt_builder [imt_slot] = entry; #if DEBUG_IMT @@ -1477,17 +1478,17 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* if (imt_builder [i] != NULL) { int methods_in_slot = imt_builder [i]->children + 1; - if (methods_in_slot > mono_stats.imt_max_collisions_in_slot) { - mono_stats.imt_max_collisions_in_slot = methods_in_slot; + if (methods_in_slot > UnlockedRead (&mono_stats.imt_max_collisions_in_slot)) { + UnlockedWrite (&mono_stats.imt_max_collisions_in_slot, methods_in_slot); record_method_count_for_max_collisions = TRUE; } method_count += methods_in_slot; } } - mono_stats.imt_number_of_methods += method_count; + UnlockedAdd (&mono_stats.imt_number_of_methods, method_count); if (record_method_count_for_max_collisions) { - mono_stats.imt_method_count_when_max_collisions = method_count; + UnlockedWrite (&mono_stats.imt_method_count_when_max_collisions, method_count); } for (i = 0; i < MONO_IMT_SIZE; i++) { @@ -1900,16 +1901,16 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro if (klass->interface_offsets_count) { imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE); - mono_stats.imt_number_of_tables++; - mono_stats.imt_tables_size += imt_table_bytes; + UnlockedIncrement (&mono_stats.imt_number_of_tables); + UnlockedAdd (&mono_stats.imt_tables_size, imt_table_bytes); } else { imt_table_bytes = 0; } vtable_size = imt_table_bytes + MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer); - mono_stats.used_class_count++; - mono_stats.class_vtable_size += vtable_size; + UnlockedIncrement (&mono_stats.used_class_count); + UnlockedAdd (&mono_stats.class_vtable_size, vtable_size); interface_offsets = alloc_vtable (domain, vtable_size, imt_table_bytes); vt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes); @@ -1961,7 +1962,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro vt->vtable [klass->vtable_size] = mono_domain_alloc0 (domain, class_size); } vt->has_static_fields = TRUE; - mono_stats.class_static_data_size += class_size; + UnlockedAdd (&mono_stats.class_static_data_size, class_size); } iter = NULL; @@ -2248,12 +2249,12 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono } imt_table_bytes = sizeof (gpointer) * MONO_IMT_SIZE; - mono_stats.imt_number_of_tables++; - mono_stats.imt_tables_size += imt_table_bytes; + UnlockedIncrement (&mono_stats.imt_number_of_tables); + UnlockedAdd (&mono_stats.imt_tables_size, imt_table_bytes); vtsize = imt_table_bytes + MONO_SIZEOF_VTABLE + klass->vtable_size * sizeof (gpointer); - mono_stats.class_vtable_size += vtsize + extra_interface_vtsize; + UnlockedAdd (&mono_stats.class_vtable_size, vtsize + extra_interface_vtsize); interface_offsets = alloc_vtable (domain, vtsize + extra_interface_vtsize, imt_table_bytes); pvt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes); @@ -7866,7 +7867,7 @@ mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle targ if (method) MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method); - mono_stats.delegate_creations++; + UnlockedIncrement (&mono_stats.delegate_creations); #ifndef DISABLE_REMOTING if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) { diff --git a/mono/mini/driver.c b/mono/mini/driver.c index f8d485292afd..297179bf86ca 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -1420,7 +1420,7 @@ mono_jit_parse_options (int argc, char * argv[]) opt->break_on_exc = TRUE; } else if (strcmp (argv [i], "--stats") == 0) { mono_counters_enable (-1); - mono_stats.enabled = TRUE; + InterlockedWriteBool (&mono_stats.enabled, TRUE); mono_jit_stats.enabled = TRUE; } else if (strcmp (argv [i], "--break") == 0) { if (i+1 >= argc){ @@ -1767,7 +1767,7 @@ mono_main (int argc, char* argv[]) mono_print_vtable = TRUE; } else if (strcmp (argv [i], "--stats") == 0) { mono_counters_enable (-1); - mono_stats.enabled = TRUE; + InterlockedWriteBool (&mono_stats.enabled, TRUE); mono_jit_stats.enabled = TRUE; #ifndef DISABLE_AOT } else if (strcmp (argv [i], "--aot") == 0) { diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 9653be3ff367..02f056f694d4 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "trace.h" #include "ir-emit.h" @@ -8011,7 +8012,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC } if (!fail_tramp) - mono_stats.imt_trampolines_size += code - start; + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_TRAMPOLINE_UNWINDINFO_SIZE(0))); diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 1f6b67f26fef..1e56345f03d2 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "mini-arm.h" #include "cpu-arm.h" @@ -7046,7 +7047,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC mono_arch_flush_icache ((guint8*)start, size); MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL)); - mono_stats.imt_trampolines_size += code - start; + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (DISTANCE (start, code) <= size); diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c index 3bf1147f7613..0a489649c86d 100644 --- a/mono/mini/mini-mips.c +++ b/mono/mini/mini-mips.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -5709,7 +5710,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC } if (!fail_tramp) - mono_stats.imt_trampolines_size += code - start; + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); mono_arch_flush_icache (start, size); diff --git a/mono/mini/mini-ppc.c b/mono/mini/mini-ppc.c index 97ded1bee40b..1a947639a241 100644 --- a/mono/mini/mini-ppc.c +++ b/mono/mini/mini-ppc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "mini-ppc.h" #ifdef TARGET_POWERPC64 @@ -5740,7 +5741,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC } if (!fail_tramp) - mono_stats.imt_trampolines_size += code - start; + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); mono_arch_flush_icache (start, size); diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 8f0f7dd5395b..3b74b398e1bf 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -4305,6 +4306,11 @@ register_icalls (void) MonoJitStats mono_jit_stats = {0}; +/** + * Counters of mono_stats can be read without locking here. + * MONO_NO_SANITIZE_THREAD tells Clang's ThreadSanitizer to hide all reports of these (known) races. + */ +MONO_NO_SANITIZE_THREAD static void print_jit_stats (void) { @@ -4315,36 +4321,36 @@ print_jit_stats (void) g_print ("Biggest method: %ld (%s)\n", mono_jit_stats.biggest_method_size, mono_jit_stats.biggest_method); - g_print ("Delegates created: %ld\n", mono_stats.delegate_creations); - g_print ("Initialized classes: %ld\n", mono_stats.initialized_class_count); - g_print ("Used classes: %ld\n", mono_stats.used_class_count); - g_print ("Generic vtables: %ld\n", mono_stats.generic_vtable_count); - g_print ("Methods: %ld\n", mono_stats.method_count); - g_print ("Static data size: %ld\n", mono_stats.class_static_data_size); - g_print ("VTable data size: %ld\n", mono_stats.class_vtable_size); + g_print ("Delegates created: %" G_GINT32_FORMAT "\n", mono_stats.delegate_creations); + g_print ("Initialized classes: %" G_GINT32_FORMAT "\n", mono_stats.initialized_class_count); + g_print ("Used classes: %" G_GINT32_FORMAT "\n", mono_stats.used_class_count); + g_print ("Generic vtables: %" G_GINT32_FORMAT "\n", mono_stats.generic_vtable_count); + g_print ("Methods: %" G_GINT32_FORMAT "\n", mono_stats.method_count); + g_print ("Static data size: %" G_GINT32_FORMAT "\n", mono_stats.class_static_data_size); + g_print ("VTable data size: %" G_GINT32_FORMAT "\n", mono_stats.class_vtable_size); g_print ("Mscorlib mempool size: %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool)); - g_print ("\nInitialized classes: %ld\n", mono_stats.generic_class_count); - g_print ("Inflated types: %ld\n", mono_stats.inflated_type_count); + g_print ("\nInitialized classes: %" G_GINT32_FORMAT "\n", mono_stats.generic_class_count); + g_print ("Inflated types: %" G_GINT32_FORMAT "\n", mono_stats.inflated_type_count); g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations); - g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods); - g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods); - g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods); - g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods); - - g_print ("IMT tables size: %ld\n", mono_stats.imt_tables_size); - g_print ("IMT number of tables: %ld\n", mono_stats.imt_number_of_tables); - g_print ("IMT number of methods: %ld\n", mono_stats.imt_number_of_methods); - g_print ("IMT used slots: %ld\n", mono_stats.imt_used_slots); - g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions); - g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot); - g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions); - g_print ("IMT trampolines size: %ld\n", mono_stats.imt_trampolines_size); - - g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count); - g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count); - g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count); + g_print ("Sharable generic methods: %" G_GINT32_FORMAT "\n", mono_stats.generics_sharable_methods); + g_print ("Unsharable generic methods: %" G_GINT32_FORMAT "\n", mono_stats.generics_unsharable_methods); + g_print ("Shared generic methods: %" G_GINT32_FORMAT "\n", mono_stats.generics_shared_methods); + g_print ("Shared vtype generic methods: %" G_GINT32_FORMAT "\n", mono_stats.gsharedvt_methods); + + g_print ("IMT tables size: %" G_GINT32_FORMAT "\n", mono_stats.imt_tables_size); + g_print ("IMT number of tables: %" G_GINT32_FORMAT "\n", mono_stats.imt_number_of_tables); + g_print ("IMT number of methods: %" G_GINT32_FORMAT "\n", mono_stats.imt_number_of_methods); + g_print ("IMT used slots: %" G_GINT32_FORMAT "\n", mono_stats.imt_used_slots); + g_print ("IMT colliding slots: %" G_GINT32_FORMAT "\n", mono_stats.imt_slots_with_collisions); + g_print ("IMT max collisions: %" G_GINT32_FORMAT "\n", mono_stats.imt_max_collisions_in_slot); + g_print ("IMT methods at max col: %" G_GINT32_FORMAT "\n", mono_stats.imt_method_count_when_max_collisions); + g_print ("IMT trampolines size: %" G_GINT32_FORMAT "\n", mono_stats.imt_trampolines_size); + + g_print ("JIT info table inserts: %" G_GINT32_FORMAT "\n", mono_stats.jit_info_table_insert_count); + g_print ("JIT info table removes: %" G_GINT32_FORMAT "\n", mono_stats.jit_info_table_remove_count); + g_print ("JIT info table lookups: %" G_GINT32_FORMAT "\n", mono_stats.jit_info_table_lookup_count); g_free (mono_jit_stats.max_ratio_method); mono_jit_stats.max_ratio_method = NULL; diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 5760bfb8672d..28aa4dcb2d05 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -268,6 +268,7 @@ if (ins->inst_target_bb->native_offset) { \ #include #include #include +#include #include "mini-s390x.h" #include "cpu-s390x.h" @@ -6678,7 +6679,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL)); if (!fail_tramp) - mono_stats.imt_trampolines_size += (code - start); + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); diff --git a/mono/mini/mini-sparc.c b/mono/mini/mini-sparc.c index 7f5f68091e4a..75868b976111 100644 --- a/mono/mini/mini-sparc.c +++ b/mono/mini/mini-sparc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "mini-sparc.h" #include "trace.h" @@ -2359,7 +2360,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC mono_arch_flush_icache ((guint8*)start, (code - start) * 4); - mono_stats.imt_trampolines_size += (code - start) * 4; + UnlockedAdd (&mono_stats.imt_trampolines_size, (code - start) * 4); g_assert (code - start <= size); mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain); diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 86ddb4142789..f6b61bae8cc0 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "trace.h" #include "mini-x86.h" @@ -5641,7 +5642,7 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTC } if (!fail_tramp) - mono_stats.imt_trampolines_size += code - start; + UnlockedAdd (&mono_stats.imt_trampolines_size, code - start); g_assert (code - start <= size); #if DEBUG_IMT diff --git a/mono/mini/mini.c b/mono/mini/mini.c index ee3c3754ae28..608b4a32a000 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -3125,9 +3125,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl if (opts & MONO_OPT_GSHARED) { if (try_generic_shared) - mono_stats.generics_sharable_methods++; + InterlockedIncrement (&mono_stats.generics_sharable_methods); else if (mono_method_is_generic_impl (method)) - mono_stats.generics_unsharable_methods++; + InterlockedIncrement (&mono_stats.generics_unsharable_methods); } #ifdef ENABLE_LLVM @@ -4236,9 +4236,9 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in code = cfg->native_code; if (cfg->gshared && mono_method_is_generic_sharable (method, FALSE)) - mono_stats.generics_shared_methods++; + InterlockedIncrement (&mono_stats.generics_shared_methods); if (cfg->gsharedvt) - mono_stats.gsharedvt_methods++; + InterlockedIncrement (&mono_stats.gsharedvt_methods); } jinfo = cfg->jit_info; From 35d14709605ab1ad14bb77b3b95bdd780dcd1e69 Mon Sep 17 00:00:00 2001 From: cherusker Date: Wed, 16 Aug 2017 00:12:12 +0200 Subject: [PATCH 4/5] Tell TSan to ignore `GCStats` - `minor_gc_count` and `major_gc_count`: use `gint32` as the `binary_protocol_collection* ()` and `sgen_debug_dump_heap ()` functions cast these values to `int` anyways - `*_gc_time_*`: use `gint64` since 300 years seem like a fair amount of time and `Interlocked*64 ()` can be used - adjust the logic of `sgen_gc_collection_count ()` to enhance its readability - parameter `size` of `sgen_client_degraded_allocation` is unused and can be removed - use `Interlocked* ()` for static variables of `sgen_client_degraded_allocation ()` - use `G_*_FORMAT` to correctly print `g*` types --- mono/metadata/boehm-gc.c | 4 ++-- mono/metadata/gc.c | 8 +++---- mono/metadata/sgen-mono.c | 17 ++++++++------- mono/sgen/gc-internal-agnostic.h | 10 ++++----- mono/sgen/sgen-alloc.c | 2 +- mono/sgen/sgen-client.h | 2 +- mono/sgen/sgen-gc.c | 37 ++++++++++++++++---------------- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 03d5147c782e..a93f04a867d0 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -458,7 +458,7 @@ on_gc_notification (GC_EventType event) if (mono_perfcounters) mono_perfcounters->gc_collections0++; #endif - gc_stats.major_gc_count ++; + InterlockedIncrement (&gc_stats.major_gc_count); gc_start_time = mono_100ns_ticks (); break; @@ -482,7 +482,7 @@ on_gc_notification (GC_EventType event) mono_perfcounters->gc_gen0size = heap_size; } #endif - gc_stats.major_gc_time += mono_100ns_ticks () - gc_start_time; + InterlockedAdd64 (&gc_stats.major_gc_time, mono_100ns_ticks () - gc_start_time); mono_trace_message (MONO_TRACE_GC, "gc took %" G_GINT64_FORMAT " usecs", (mono_100ns_ticks () - gc_start_time) / 10); break; default: diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 467a9239d19c..4b1a56f4c0fe 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -933,11 +933,11 @@ mono_gc_init (void) mono_coop_mutex_init_recursive (&finalizer_mutex); mono_coop_mutex_init_recursive (&reference_queue_mutex); - mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.minor_gc_count); - mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.major_gc_count); + mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.minor_gc_count); + mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.major_gc_count); mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time); - mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time); - mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent); + mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time); + mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent); mono_gc_base_init (); diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 93bdb1fb5c7e..8604d9321a0a 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -2799,18 +2799,19 @@ mono_gc_add_memory_pressure (gint64 value) */ void -sgen_client_degraded_allocation (size_t size) +sgen_client_degraded_allocation (void) { - static int last_major_gc_warned = -1; - static int num_degraded = 0; + static gint32 last_major_gc_warned = -1; + static gint32 num_degraded = 0; - if (last_major_gc_warned < (int)gc_stats.major_gc_count) { - ++num_degraded; - if (num_degraded == 1 || num_degraded == 3) + gint32 major_gc_count = InterlockedRead (&gc_stats.major_gc_count); + if (InterlockedRead (&last_major_gc_warned) < major_gc_count) { + gint32 num = InterlockedIncrement (&num_degraded); + if (num == 1 || num == 3) mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "Warning: Degraded allocation. Consider increasing nursery-size if the warning persists."); - else if (num_degraded == 10) + else if (num == 10) mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "Warning: Repeated degraded allocation. Consider increasing nursery-size."); - last_major_gc_warned = gc_stats.major_gc_count; + InterlockedWrite (&last_major_gc_warned, major_gc_count); } } diff --git a/mono/sgen/gc-internal-agnostic.h b/mono/sgen/gc-internal-agnostic.h index 0367d145774d..fef115796dd1 100644 --- a/mono/sgen/gc-internal-agnostic.h +++ b/mono/sgen/gc-internal-agnostic.h @@ -63,11 +63,11 @@ typedef enum { #define MONO_GC_HANDLE(slot, type) (((slot) << MONO_GC_HANDLE_TYPE_SHIFT) | (((type) & MONO_GC_HANDLE_TYPE_MASK) + 1)) typedef struct { - guint minor_gc_count; - guint major_gc_count; - guint64 minor_gc_time; - guint64 major_gc_time; - guint64 major_gc_time_concurrent; + gint32 minor_gc_count; + gint32 major_gc_count; + gint64 minor_gc_time; + gint64 major_gc_time; + gint64 major_gc_time_concurrent; } GCStats; extern GCStats gc_stats; diff --git a/mono/sgen/sgen-alloc.c b/mono/sgen/sgen-alloc.c index 2e1178ad3926..6c21c466f3fa 100644 --- a/mono/sgen/sgen-alloc.c +++ b/mono/sgen/sgen-alloc.c @@ -69,7 +69,7 @@ alloc_degraded (GCVTable vtable, size_t size, gboolean for_mature) GCObject *p; if (!for_mature) { - sgen_client_degraded_allocation (size); + sgen_client_degraded_allocation (); SGEN_ATOMIC_ADD_P (degraded_mode, size); sgen_ensure_free_space (size, GENERATION_OLD); } else { diff --git a/mono/sgen/sgen-client.h b/mono/sgen/sgen-client.h index a492ad74a977..99d778579356 100644 --- a/mono/sgen/sgen-client.h +++ b/mono/sgen/sgen-client.h @@ -122,7 +122,7 @@ void sgen_client_pinned_los_object (GCObject *obj); /* * Called for every degraded allocation. No action is necessary. */ -void sgen_client_degraded_allocation (size_t size); +void sgen_client_degraded_allocation (void); /* * Called whenever the amount of memory allocated for the managed heap changes. No action diff --git a/mono/sgen/sgen-gc.c b/mono/sgen/sgen-gc.c index 49c630f03f37..54ff725b22b3 100644 --- a/mono/sgen/sgen-gc.c +++ b/mono/sgen/sgen-gc.c @@ -177,6 +177,7 @@ #include #include #include +#include #include "mono/sgen/sgen-gc.h" #include "mono/sgen/sgen-cardtable.h" @@ -1701,7 +1702,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ TV_GETTIME (last_minor_collection_start_tv); atv = last_minor_collection_start_tv; - binary_protocol_collection_begin (gc_stats.minor_gc_count, GENERATION_NURSERY); + binary_protocol_collection_begin (InterlockedRead (&gc_stats.minor_gc_count), GENERATION_NURSERY); object_ops_nopar = sgen_concurrent_collection_in_progress () ? &sgen_minor_collector.serial_ops_with_concurrent_major @@ -1729,7 +1730,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ degraded_mode = 0; objects_pinned = 0; - SGEN_LOG (1, "Start nursery collection %d %p-%p, size: %d", gc_stats.minor_gc_count, nursery_section->data, nursery_section->end_data, (int)(nursery_section->end_data - nursery_section->data)); + SGEN_LOG (1, "Start nursery collection %" G_GINT32_FORMAT " %p-%p, size: %d", InterlockedRead (&gc_stats.minor_gc_count), nursery_section->data, nursery_section->end_data, (int)(nursery_section->end_data - nursery_section->data)); /* world must be stopped already */ TV_GETTIME (btv); @@ -1744,7 +1745,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ init_gray_queue (&gc_thread_gray_queue); ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops_nopar, &gc_thread_gray_queue); - gc_stats.minor_gc_count ++; + InterlockedIncrement (&gc_stats.minor_gc_count); sgen_process_fin_stage_entries (); @@ -1861,9 +1862,9 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ major_collector.finish_nursery_collection (); TV_GETTIME (last_minor_collection_end_tv); - gc_stats.minor_gc_time += TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv); + InterlockedAdd64 (&gc_stats.minor_gc_time, TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv)); - sgen_debug_dump_heap ("minor", gc_stats.minor_gc_count - 1, NULL); + sgen_debug_dump_heap ("minor", InterlockedRead (&gc_stats.minor_gc_count) - 1, NULL); /* prepare the pin queue for the next collection */ sgen_finish_pinning (); @@ -1896,7 +1897,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ time_minor_scan_los - los_scan_start, time_minor_finish_gray_stack - finish_gray_start); - binary_protocol_collection_end (gc_stats.minor_gc_count - 1, GENERATION_NURSERY, 0, 0); + binary_protocol_collection_end (InterlockedRead (&gc_stats.minor_gc_count) - 1, GENERATION_NURSERY, 0, 0); if (check_nursery_objects_pinned && !sgen_minor_collector.is_split) sgen_check_nursery_objects_pinned (unpin_queue != NULL); @@ -2147,7 +2148,7 @@ major_start_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason, { SgenObjectOperations *object_ops_nopar, *object_ops_par = NULL; - binary_protocol_collection_begin (gc_stats.major_gc_count, GENERATION_OLD); + binary_protocol_collection_begin (InterlockedRead (&gc_stats.major_gc_count), GENERATION_OLD); current_collection_generation = GENERATION_OLD; @@ -2178,8 +2179,8 @@ major_start_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason, check_scan_starts (); degraded_mode = 0; - SGEN_LOG (1, "Start major collection %d", gc_stats.major_gc_count); - gc_stats.major_gc_count ++; + SGEN_LOG (1, "Start major collection %" G_GINT32_FORMAT, InterlockedRead (&gc_stats.major_gc_count)); + InterlockedIncrement (&gc_stats.major_gc_count); if (major_collector.start_major_collection) major_collector.start_major_collection (); @@ -2295,7 +2296,7 @@ major_finish_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason TV_GETTIME (atv); time_major_sweep += TV_ELAPSED (btv, atv); - sgen_debug_dump_heap ("major", gc_stats.major_gc_count - 1, reason); + sgen_debug_dump_heap ("major", InterlockedRead (&gc_stats.major_gc_count) - 1, reason); if (sgen_have_pending_finalizers ()) { SGEN_LOG (4, "Finalizer-thread wakeup"); @@ -2327,7 +2328,7 @@ major_finish_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason time_major_scan_mod_union_los - los_scan_start, time_major_finish_gray_stack - finish_gray_start); - binary_protocol_collection_end (gc_stats.major_gc_count - 1, GENERATION_OLD, counts.num_scanned_objects, counts.num_unique_scanned_objects); + binary_protocol_collection_end (InterlockedRead (&gc_stats.major_gc_count) - 1, GENERATION_OLD, counts.num_scanned_objects, counts.num_unique_scanned_objects); } static gboolean @@ -2355,7 +2356,7 @@ major_do_collection (const char *reason, gboolean is_overflow, gboolean forced) sgen_gray_object_queue_dispose (&gc_thread_gray_queue); TV_GETTIME (time_end); - gc_stats.major_gc_time += TV_ELAPSED (time_start, time_end); + InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (time_start, time_end)); /* FIXME: also report this to the user, preferably in gc-end. */ if (major_collector.get_and_reset_num_major_objects_marked) @@ -2391,7 +2392,7 @@ major_start_concurrent_collection (const char *reason) num_objects_marked = major_collector.get_and_reset_num_major_objects_marked (); TV_GETTIME (time_end); - gc_stats.major_gc_time += TV_ELAPSED (time_start, time_end); + InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (time_start, time_end)); current_collection_generation = -1; } @@ -2419,7 +2420,7 @@ major_update_concurrent_collection (void) sgen_los_update_cardtable_mod_union (); TV_GETTIME (total_end); - gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end); + InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (total_start, total_end)); } static void @@ -2441,7 +2442,7 @@ major_finish_concurrent_collection (gboolean forced) sgen_workers_stop_all_workers (GENERATION_OLD); SGEN_TV_GETTIME (time_major_conc_collection_end); - gc_stats.major_gc_time_concurrent += SGEN_TV_ELAPSED (time_major_conc_collection_start, time_major_conc_collection_end); + InterlockedAdd64 (&gc_stats.major_gc_time_concurrent, SGEN_TV_ELAPSED (time_major_conc_collection_start, time_major_conc_collection_end)); major_collector.update_cardtable_mod_union (); sgen_los_update_cardtable_mod_union (); @@ -2456,7 +2457,7 @@ major_finish_concurrent_collection (gboolean forced) sgen_gray_object_queue_dispose (&gc_thread_gray_queue); TV_GETTIME (total_end); - gc_stats.major_gc_time += TV_ELAPSED (total_start, total_end); + InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (total_start, total_end)); current_collection_generation = -1; } @@ -3053,9 +3054,7 @@ sgen_gc_collect (int generation) int sgen_gc_collection_count (int generation) { - if (generation == 0) - return gc_stats.minor_gc_count; - return gc_stats.major_gc_count; + return InterlockedRead (generation == GENERATION_NURSERY ? &gc_stats.minor_gc_count : &gc_stats.major_gc_count); } size_t From 441a6f68fae64070368eaf41b308c971d6649c35 Mon Sep 17 00:00:00 2001 From: cherusker Date: Wed, 16 Aug 2017 00:15:14 +0200 Subject: [PATCH 5/5] Tell TSan to ignore `JITGCStats` - change the field types from `int` to `gint32` --- mono/mini/mini-gc.c | 81 +++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/mono/mini/mini-gc.c b/mono/mini/mini-gc.c index 3b5463e80fb1..ae9204f82601 100644 --- a/mono/mini/mini-gc.c +++ b/mono/mini/mini-gc.c @@ -42,6 +42,7 @@ get_provenance_func (void) #include #include #include +#include #define SIZEOF_SLOT ((int)sizeof (mgreg_t)) @@ -254,27 +255,27 @@ static gboolean precise_frame_limit_inited; /* Stats */ typedef struct { - int scanned_stacks; - int scanned; - int scanned_precisely; - int scanned_conservatively; - int scanned_registers; - int scanned_native; - int scanned_other; + gint32 scanned_stacks; + gint32 scanned; + gint32 scanned_precisely; + gint32 scanned_conservatively; + gint32 scanned_registers; + gint32 scanned_native; + gint32 scanned_other; - int all_slots; - int noref_slots; - int ref_slots; - int pin_slots; - - int gc_maps_size; - int gc_callsites_size; - int gc_callsites8_size; - int gc_callsites16_size; - int gc_callsites32_size; - int gc_bitmaps_size; - int gc_map_struct_size; - int tlsdata_size; + gint32 all_slots; + gint32 noref_slots; + gint32 ref_slots; + gint32 pin_slots; + + gint32 gc_maps_size; + gint32 gc_callsites_size; + gint32 gc_callsites8_size; + gint32 gc_callsites16_size; + gint32 gc_callsites32_size; + gint32 gc_bitmaps_size; + gint32 gc_map_struct_size; + gint32 tlsdata_size; } JITGCStats; static JITGCStats stats; @@ -601,7 +602,7 @@ thread_attach_func (void) tls = g_new0 (TlsData, 1); tls->tid = mono_native_thread_id_get (); tls->info = mono_thread_info_current (); - stats.tlsdata_size += sizeof (TlsData); + UnlockedAdd (&stats.tlsdata_size, sizeof (TlsData)); return tls; } @@ -762,7 +763,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) /* tls == NULL can happen during startup */ if (mono_thread_internal_current () == NULL || !tls) { mono_gc_conservatively_scan_area (stack_start, stack_end); - stats.scanned_stacks += stack_end - stack_start; + UnlockedAdd (&stats.scanned_stacks, stack_end - stack_start); return; } @@ -993,7 +994,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) /* This scans the previously skipped frames as well */ DEBUG (fprintf (logfile, "\tscan area %p-%p (%d).\n", stack_limit, real_frame_start, (int)(real_frame_start - stack_limit))); mono_gc_conservatively_scan_area (stack_limit, real_frame_start); - stats.scanned_other += real_frame_start - stack_limit; + UnlockedAdd (&stats.scanned_other, real_frame_start - stack_limit); } /* Mark stack slots */ @@ -1119,16 +1120,16 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end) if (stack_limit < stack_end) { DEBUG (fprintf (logfile, "\tscan remaining stack %p-%p (%d).\n", stack_limit, stack_end, (int)(stack_end - stack_limit))); mono_gc_conservatively_scan_area (stack_limit, stack_end); - stats.scanned_native += stack_end - stack_limit; + UnlockedAdd (&stats.scanned_native, stack_end - stack_limit); } DEBUG (fprintf (logfile, "Marked %d bytes, p=%d,c=%d out of %d.\n", scanned, scanned_precisely, scanned_conservatively, (int)(stack_end - stack_start))); - stats.scanned_stacks += stack_end - stack_start; - stats.scanned += scanned; - stats.scanned_precisely += scanned_precisely; - stats.scanned_conservatively += scanned_conservatively; - stats.scanned_registers += scanned_registers; + UnlockedAdd (&stats.scanned_stacks, stack_end - stack_start); + UnlockedAdd (&stats.scanned, scanned); + UnlockedAdd (&stats.scanned_precisely, scanned_precisely); + UnlockedAdd (&stats.scanned_conservatively, scanned_conservatively); + UnlockedAdd (&stats.scanned_registers, scanned_registers); //mono_gc_conservatively_scan_area (stack_start, stack_end); } @@ -2423,17 +2424,17 @@ create_map (MonoCompile *cfg) guint8 *offsets = p; for (i = 0; i < ncallsites; ++i) offsets [i] = callsites [i]->pc_offset; - stats.gc_callsites8_size += ncallsites * sizeof (guint8); + UnlockedAdd (&stats.gc_callsites8_size, ncallsites * sizeof (guint8)); } else if (map->callsite_entry_size == 2) { guint16 *offsets = (guint16*)p; for (i = 0; i < ncallsites; ++i) offsets [i] = callsites [i]->pc_offset; - stats.gc_callsites16_size += ncallsites * sizeof (guint16); + UnlockedAdd (&stats.gc_callsites16_size, ncallsites * sizeof (guint16)); } else { guint32 *offsets = (guint32*)p; for (i = 0; i < ncallsites; ++i) offsets [i] = callsites [i]->pc_offset; - stats.gc_callsites32_size += ncallsites * sizeof (guint32); + UnlockedAdd (&stats.gc_callsites32_size, ncallsites * sizeof (guint32)); } p += ncallsites * map->callsite_entry_size; @@ -2443,10 +2444,10 @@ create_map (MonoCompile *cfg) g_assert ((guint8*)p - (guint8*)emap <= alloc_size); - stats.gc_maps_size += alloc_size; - stats.gc_callsites_size += ncallsites * map->callsite_entry_size; - stats.gc_bitmaps_size += bitmaps_size; - stats.gc_map_struct_size += sizeof (GCEncodedMap) + encoded_size; + UnlockedAdd (&stats.gc_maps_size, alloc_size); + UnlockedAdd (&stats.gc_callsites_size, ncallsites * map->callsite_entry_size); + UnlockedAdd (&stats.gc_bitmaps_size, bitmaps_size); + UnlockedAdd (&stats.gc_map_struct_size, sizeof (GCEncodedMap) + encoded_size); cfg->jit_info->gc_info = emap; @@ -2454,10 +2455,10 @@ create_map (MonoCompile *cfg) cfg->gc_map_size = alloc_size; } - stats.all_slots += nslots; - stats.ref_slots += ntypes [SLOT_REF]; - stats.noref_slots += ntypes [SLOT_NOREF]; - stats.pin_slots += ntypes [SLOT_PIN]; + UnlockedAdd (&stats.all_slots, nslots); + UnlockedAdd (&stats.ref_slots, ntypes [SLOT_REF]); + UnlockedAdd (&stats.noref_slots, ntypes [SLOT_NOREF]); + UnlockedAdd (&stats.pin_slots, ntypes [SLOT_PIN]); } void