[Mono-dev] do_rehash race

Neale Ferguson neale at sinenomine.net
Thu May 28 18:35:49 UTC 2015


Hi,
 When a hash table exceeds a threshold a rehash operation is triggered. At
the moment the new table is allocated and its address placed in the table
field of the structure. The do_rehash also then copies the entries from
the old table to the new. However, if there is another thread active that
is doing lookups then there is a window where the new table is still being
filled such that a lookup can fail. This is because the new table is made
active before it has been copied. This proposed patch will fill the new
table before swapping the old for the new table in the hash structure.

Neale

@@ -194,24 +196,24 @@ do_rehash (void *_data)
        Slot **table;
 
        /* printf ("Resizing diff=%d slots=%d\n", hash->in_use -
hash->last_rehash, hash->table_size); */
-       hash->last_rehash = hash->table_size;
        current_size = hash->table_size;
-       hash->table_size = data->new_size;
        /* printf ("New size: %d\n", hash->table_size); */
        table = hash->table;
-       hash->table = data->table;
 
        for (i = 0; i < current_size; i++){
                Slot *s, *next;
 
                for (s = table [i]; s != NULL; s = next){
-                       guint hashcode = ((*hash->hash_func) (s->key)) %
hash->table_size;
+                       guint hashcode = ((*hash->hash_func) (s->key)) %
data->new_size;
                        next = s->next;
 
-                       s->next = hash->table [hashcode];
-                       hash->table [hashcode] = s;
+                       s->next = data->table [hashcode];
+                       data->table [hashcode] = s;
                }
        }
+       hash->table_size = data->new_size;
+       hash->last_rehash = hash->table_size;
+       hash->table = data->table;
        return table;
 }
 

Neale



More information about the Mono-devel-list mailing list