Author: Armin Rigo <ar...@tunes.org>
Branch: finalizer
Changeset: r1467:45014eae5453
Date: 2014-10-07 10:33 +0200
http://bitbucket.org/pypy/stmgc/changeset/45014eae5453/

Log:    Don't run a light finalizer in a segment where the object is not
        visible yet.

diff --git a/c7/stm/finalizer.c b/c7/stm/finalizer.c
--- a/c7/stm/finalizer.c
+++ b/c7/stm/finalizer.c
@@ -42,6 +42,8 @@
 static void deal_with_old_objects_with_finalizers(void)
 {
     /* for light finalizers */
+    int old_gs_register = STM_SEGMENT->segment_num;
+    int current_gs_register = old_gs_register;
     long j;
     for (j = 1; j <= NB_SEGMENTS; j++) {
         struct stm_priv_segment_info_s *pseg = get_priv_segment(j);
@@ -53,10 +55,21 @@
             object_t* obj = (object_t *)list_item(lst, i);
             if (!mark_visited_test(obj)) {
                 /* not marked: object dies */
-                /* we're calling the light finalizer in a random thread,
-                   but it should work, because it was dead already at the
-                   start of that thread's transaction, so any thread should
-                   see the same, old content */
+                /* we're calling the light finalizer in the same
+                   segment as where it was originally registered.  For
+                   objects that existed since a long time, it doesn't
+                   change anything: any thread should see the same old
+                   content (because if it wasn't the case, the object
+                   would be in a 'modified_old_objects' list
+                   somewhere, and so it wouldn't be dead).  But it's
+                   important if the object was created by the same
+                   transaction: then only that segment sees valid
+                   content.
+                */
+                if (j != current_gs_register) {
+                    set_gs_register(get_segment_base(j));
+                    current_gs_register = j;
+                }
                 stmcb_light_finalizer(obj);
             }
             else {
@@ -65,6 +78,8 @@
             }
         }
     }
+    if (old_gs_register != current_gs_register)
+        set_gs_register(get_segment_base(old_gs_register));
 }
 
 
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -63,6 +63,7 @@
 bool _check_become_inevitable(stm_thread_local_t *tl);
 bool _check_become_globally_unique_transaction(stm_thread_local_t *tl);
 int stm_is_inevitable(void);
+long current_segment_num(void);
 
 void _set_type_id(object_t *obj, uint32_t h);
 uint32_t _get_type_id(object_t *obj);
@@ -374,6 +375,11 @@
 void stmcb_commit_soon()
 {
 }
+
+long current_segment_num(void)
+{
+    return STM_SEGMENT->segment_num;
+}
 ''', sources=source_files,
      define_macros=[('STM_TESTS', '1'),
                     ('STM_NO_AUTOMATIC_SETJMP', '1'),
diff --git a/c7/test/test_finalizer.py b/c7/test/test_finalizer.py
--- a/c7/test/test_finalizer.py
+++ b/c7/test/test_finalizer.py
@@ -9,13 +9,22 @@
         #
         @ffi.callback("void(object_t *)")
         def light_finalizer(obj):
-            self.light_finalizers_called.append(obj)
+            segnum = lib.current_segment_num()
+            tlnum = '?'
+            for n, tl in enumerate(self.tls):
+                if tl.associated_segment_num == segnum:
+                    tlnum = n
+                    break
+            self.light_finalizers_called.append((obj, tlnum))
         self.light_finalizers_called = []
         lib.stmcb_light_finalizer = light_finalizer
         self._light_finalizer_keepalive = light_finalizer
 
-    def expect_finalized(self, objs):
-        assert self.light_finalizers_called == objs
+    def expect_finalized(self, objs, from_tlnum=None):
+        assert [obj for (obj, tlnum) in self.light_finalizers_called] == objs
+        if from_tlnum is not None:
+            for obj, tlnum in self.light_finalizers_called:
+                assert tlnum == from_tlnum
         self.light_finalizers_called = []
 
     def test_no_finalizer(self):
@@ -30,7 +39,7 @@
         lib.stm_enable_light_finalizer(lp1)
         self.expect_finalized([])
         self.commit_transaction()
-        self.expect_finalized([lp1])
+        self.expect_finalized([lp1], from_tlnum=0)
 
     def test_young_light_finalizer_survives(self):
         self.start_transaction()
@@ -50,7 +59,7 @@
         self.commit_transaction()
         self.expect_finalized([])
 
-    def test_old_light_finalizer(self):
+    def test_old_light_finalizer_2(self):
         self.start_transaction()
         lp1 = stm_allocate(48)
         lib.stm_enable_light_finalizer(lp1)
@@ -74,6 +83,22 @@
         self.commit_transaction()
         self.expect_finalized([])
 
+    def test_old_light_finalizer_segment(self):
+        self.start_transaction()
+        #
+        self.switch(1)
+        self.start_transaction()
+        lp1 = stm_allocate(48)
+        lib.stm_enable_light_finalizer(lp1)
+        self.push_root(lp1)
+        stm_minor_collect()
+        lp1 = self.pop_root()
+        #
+        self.switch(0)
+        self.expect_finalized([])
+        stm_major_collect()
+        self.expect_finalized([lp1], from_tlnum=1)
+
 
 class TestRegularFinalizer(BaseTest):
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to