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