Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit