Mark `mono_g_hash_table_max_chain_length` as known and accepted data race (#5520)
authorArmin Hasitzka <cherusker@users.noreply.github.com>
Wed, 20 Sep 2017 20:01:03 +0000 (22:01 +0200)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 20 Sep 2017 20:01:03 +0000 (22:01 +0200)
[TSan] Unlock mono_g_hash_table_max_chain_length

I would suggest using `Unlocked* ()` here. `mono_g_hash_table_find_slot ()` is called relatively often and, unlike increment or add operations, read and write operations (without a global surrounding lock) do not gain much (if anything) by being interlocked as long as they can be read and written by one instruction. That should be true for 32-bit integers and Mono's supported platforms.

mono/metadata/mono-hash.c
mono/metadata/mono-hash.h

index 1b558370d02c12c4bfc3ce7d7394a0ffff774f8d..4ef79e7385c5d70efaeddd8d5aa7109d53675382 100644 (file)
@@ -34,8 +34,9 @@
 #include "metadata/gc-internals.h"
 #include <mono/utils/checked-build.h>
 #include <mono/utils/mono-threads-coop.h>
+#include <mono/utils/unlocked.h>
 
-int mono_g_hash_table_max_chain_length;
+gint32 mono_g_hash_table_max_chain_length;
 
 #ifdef HAVE_BOEHM_GC
 #define mg_new0(type,n)  ((type *) GC_MALLOC(sizeof(type) * (n)))
@@ -136,10 +137,12 @@ static inline int mono_g_hash_table_find_slot (MonoGHashTable *hash, const MonoO
                }
        }
 
-       if (i > start && (i - start) > mono_g_hash_table_max_chain_length)
-               mono_g_hash_table_max_chain_length = i - start;
-       else if (i < start && (hash->table_size - (start - i)) > mono_g_hash_table_max_chain_length)
-               mono_g_hash_table_max_chain_length = hash->table_size - (start - i);
+       gint32 max_length = UnlockedRead (&mono_g_hash_table_max_chain_length);
+       if (i > start && (i - start) > max_length)
+               UnlockedWrite (&mono_g_hash_table_max_chain_length, i - start);
+       else if (i < start && (hash->table_size - (start - i)) > max_length)
+               UnlockedWrite (&mono_g_hash_table_max_chain_length, hash->table_size - (start - i));
+
        return i;
 }
 
index 7f778e50bd10445a9413a184e4f9683235358af2..10e3ca390eda833103f4c7b5d8787a631e0f7d2b 100644 (file)
@@ -22,7 +22,7 @@ typedef enum {
        MONO_HASH_KEY_VALUE_GC = MONO_HASH_KEY_GC | MONO_HASH_VALUE_GC,
 } MonoGHashGCType;
 
-extern int mono_g_hash_table_max_chain_length;
+extern gint32 mono_g_hash_table_max_chain_length;
 
 typedef struct _MonoGHashTable MonoGHashTable;