Author: Remi Meier
Branch: c7-weakref
Changeset: r988:e21afc419f0a
Date: 2014-03-12 17:55 +0100
http://bitbucket.org/pypy/stmgc/changeset/e21afc419f0a/

Log:    fix some multi-threading issues

diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -54,11 +54,6 @@
        after the object. */
     GCFLAG_HAS_SHADOW = 0x04,
 
-    /* This flag is set on weakref objects. Weakref objects have a
-       reference to the referenced object at the byte-offset
-           stmcb_size_rounded_up(obj) - sizeof(void*) */
-    GCFLAG_WEAKREF = 0x08,
-
     /* All remaining bits of the 32-bit 'stm_flags' field are taken by
        the "overflow number".  This is a number that identifies the
        "overflow objects" from the current transaction among all old
@@ -66,7 +61,7 @@
        current transaction that have been flushed out of the nursery,
        which occurs if the same transaction allocates too many objects.
     */
-    GCFLAG_OVERFLOW_NUMBER_bit0 = 0x10   /* must be last */
+    GCFLAG_OVERFLOW_NUMBER_bit0 = 0x8   /* must be last */
 };
 
 
diff --git a/c7/stm/weakref.c b/c7/stm/weakref.c
--- a/c7/stm/weakref.c
+++ b/c7/stm/weakref.c
@@ -7,7 +7,9 @@
 {
     OPT_ASSERT(size_rounded_up > sizeof(struct object_s));
     object_t *obj = stm_allocate(size_rounded_up);
-    obj->stm_flags |= GCFLAG_WEAKREF;
+
+    assert(_is_in_nursery(obj)); /* see assert(0) which depends on it */
+
     LIST_APPEND(STM_PSEGMENT->young_weakrefs, obj);
     return obj;
 }
@@ -38,13 +40,16 @@
                 item = pforwarded_array[1]; /* moved location */
             }
             else {
-                /* young outside nursery object */
-                if (tree_contains(STM_PSEGMENT->young_outside_nursery,
-                                  (uintptr_t)item)) {
-                    /* still in the tree -> wasn't seen by the minor 
collection,
-                       so it doesn't survive */
-                    continue;
-                }
+                /* tell me if we need this (requires synchronizing in case
+                   of private pages) */
+                assert(0);
+                /* /\* young outside nursery object *\/ */
+                /* if (tree_contains(STM_PSEGMENT->young_outside_nursery, */
+                /*                   (uintptr_t)item)) { */
+                /*     /\* still in the tree -> wasn't seen by the minor 
collection, */
+                /*        so it doesn't survive *\/ */
+                /*     continue; */
+                /* } */
             }
             assert(!_is_young(item));
 
@@ -109,7 +114,11 @@
             object_t *pointing_to = *WEAKREF_PTR(weakref, size);
             assert(pointing_to != NULL);
             if (!mark_visited_test(pointing_to)) {
+                //assert(flag_page_private[(uintptr_t)weakref / 4096UL] != 
PRIVATE_PAGE);
                 *WEAKREF_PTR(weakref, size) = NULL;
+                if (flag_page_private[(uintptr_t)weakref / 4096UL] == 
PRIVATE_PAGE) {
+                    synchronize_overflow_object_now(weakref);
+                }
 
                 /* we don't need it in this list anymore */
                 list_set_item(lst, n, list_pop_item(lst));
diff --git a/c7/test/test_weakref.py b/c7/test/test_weakref.py
--- a/c7/test/test_weakref.py
+++ b/c7/test/test_weakref.py
@@ -113,6 +113,37 @@
             self.abort_transaction()
 
 
+    def test_multiple_threads(self):
+        self.start_transaction()
+        lp0 = stm_allocate(1024)
+        self.push_root(lp0)
+        self.commit_transaction()
+
+        self.start_transaction()
+        lp0 = self.pop_root()
+        self.push_root(lp0)
+        stm_write(lp0) # privatize page
+
+        self.push_root_no_gc()
+        lp2 = stm_allocate(48)
+        lp1 = stm_allocate_weakref(lp2)    # no collection here
+        self.pop_root()
+
+        self.push_root(lp0)
+        self.push_root(lp1)
+        self.commit_transaction()
+        # lp2 dies
+        lp1 = self.pop_root()
+        self.push_root(lp1)
+
+        assert stm_get_weakref(lp1) == ffi.NULL
+
+        self.switch(1)
+
+        assert stm_get_weakref(lp1) == ffi.NULL
+
+
+
 
 class TestMajorCollection(BaseTest):
     def test_simple(self):
@@ -188,3 +219,35 @@
         lp1 = self.pop_root()
         # lp2 died
         assert stm_get_weakref(lp1) == ffi.NULL
+
+    def test_multiple_threads(self):
+        self.start_transaction()
+        lp0 = stm_allocate(48)
+        lp1 = stm_allocate_weakref(lp0)    # no collection here
+        self.push_root(lp1)
+        self.push_root(lp0)
+        self.commit_transaction()
+
+        self.start_transaction()
+        lp0 = self.pop_root()
+        lp1 = self.pop_root()
+        self.push_root(lp1)
+
+        stm_write(lp0) # privatize page with weakref in it too
+
+        assert stm_get_page_flag(stm_get_obj_pages(lp1)[0]) == PRIVATE_PAGE
+        assert stm_get_weakref(lp1) == lp0
+
+        self.commit_transaction()
+        self.start_transaction()
+
+        # lp0 dies
+        stm_major_collect()
+
+        assert stm_get_weakref(lp1) == ffi.NULL
+        print stm_get_real_address(lp1)
+
+        self.switch(1)
+
+        assert stm_get_weakref(lp1) == ffi.NULL
+        print stm_get_real_address(lp1)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to