[sgen] Support cementing from multiple workers
[mono.git] / mono / sgen / sgen-pinning.c
index 6b2b2e33547f2c2009616a0d628c00a4fd6fa14b..be803daffa7a53f3d09596b1a0b51c4261620033 100644 (file)
@@ -321,8 +321,11 @@ sgen_cement_lookup_or_register (GCObject *obj)
        SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Can only cement pointers to nursery objects");
 
        if (!hash [i].obj) {
-               SGEN_ASSERT (5, !hash [i].count, "Cementing hash inconsistent");
-               hash [i].obj = obj;
+               GCObject *old_obj;
+               old_obj = InterlockedCompareExchangePointer ((gpointer*)&hash [i].obj, obj, NULL);
+               /* Check if the slot was occupied by some other object */
+               if (old_obj != NULL && old_obj != obj)
+                       return FALSE;
        } else if (hash [i].obj != obj) {
                return FALSE;
        }
@@ -330,8 +333,7 @@ sgen_cement_lookup_or_register (GCObject *obj)
        if (hash [i].count >= SGEN_CEMENT_THRESHOLD)
                return TRUE;
 
-       ++hash [i].count;
-       if (hash [i].count == SGEN_CEMENT_THRESHOLD) {
+       if (InterlockedIncrement ((gint32*)&hash [i].count) == SGEN_CEMENT_THRESHOLD) {
                SGEN_ASSERT (9, sgen_get_current_collection_generation () >= 0, "We can only cement objects when we're in a collection pause.");
                SGEN_ASSERT (9, SGEN_OBJECT_IS_PINNED (obj), "Can only cement pinned objects");
                SGEN_CEMENT_OBJECT (obj);