Author: Remi Meier <remi.me...@inf.ethz.ch> Branch: c8-new-page-handling Changeset: r1427:f8b04d5bb3a2 Date: 2014-09-26 10:34 +0200 http://bitbucket.org/pypy/stmgc/changeset/f8b04d5bb3a2/
Log: remove go_to_the_future() diff --git a/c8/stm/core.c b/c8/stm/core.c --- a/c8/stm/core.c +++ b/c8/stm/core.c @@ -57,6 +57,7 @@ import_objects(-1, pagenum, undo, end); } + static void go_to_the_past(uintptr_t pagenum, struct stm_commit_log_entry_s *from, struct stm_commit_log_entry_s *to) @@ -78,49 +79,6 @@ } -static void go_to_the_future(uintptr_t pagenum, - struct stm_commit_log_entry_s *from, - struct stm_commit_log_entry_s *to) -{ - assert(from->rev_num <= to->rev_num); - if (from == to) - return; - - /* XXX: specialize. We now go to the HEAD revision, and back again - to where we want. Otherwise, we have to look at backup copies in - the log entries, modified objs, page content and their revisions... - - Same logic as _stm_validate() */ - - /* XXXXXXXXXXXXXXXX CORRECT LOCKING NEEDED XXXXXXXXXXXXXXXXXXXXXX */ - struct stm_commit_log_entry_s *cl = from; - struct stm_commit_log_entry_s *next_cl; - - uint64_t segment_copied_from = 0; - while ((next_cl = cl->next) != NULL) { - if (next_cl == (void *)-1) - break; - - cl = next_cl; - - struct stm_undo_s *undo = cl->written; - struct stm_undo_s *end = cl->written + cl->written_count; - - segment_copied_from |= (1UL << cl->segment_num); - import_objects(cl->segment_num, -1, undo, end); - } - - /* XXXXXXXXXXXXXXXX CORRECT LOCKING NEEDED XXXXXXXXXXXXXXXXXXXXXX */ - int segnum; - for (segnum = 0; segment_copied_from != 0; segnum++) { - if (segment_copied_from & (1UL << segnum)) { - segment_copied_from &= ~(1UL << segnum); - copy_bk_objs_in_page_from(segnum, -1); - } - } - - go_to_the_past(pagenum, cl, to); -} static void handle_segfault_in_page(uintptr_t pagenum) { @@ -137,49 +95,63 @@ assert(get_page_status_in(my_segnum, pagenum) == PAGE_NO_ACCESS); - /* find who has the PAGE_SHARED */ + /* find who has the most recent revision of our page */ int shared_page_holder = -1; int shared_ref_count = 0; + int copy_from_segnum = -1; + uint64_t most_recent_rev = 0; for (i = 0; i < NB_SEGMENTS; i++) { if (i == my_segnum) continue; + if (get_page_status_in(i, pagenum) == PAGE_SHARED) { + /* mostly for debugging now: */ shared_page_holder = i; shared_ref_count++; } + + struct stm_commit_log_entry_s *log_entry; + log_entry = get_priv_segment(i)->last_commit_log_entry; + if (get_page_status_in(i, pagenum) != PAGE_NO_ACCESS + && (copy_from_segnum == -1 || log_entry->rev_num > most_recent_rev)) { + copy_from_segnum = i; + most_recent_rev = log_entry->rev_num; + } } - assert(shared_page_holder != -1); + OPT_ASSERT(shared_page_holder != -1); + OPT_ASSERT(copy_from_segnum != -1 && copy_from_segnum != my_segnum); /* XXX: for now, we don't try to get the single shared page. We simply regard it as private for its holder. */ /* this assert should be true for now... */ assert(shared_ref_count == 1); - /* acquire this lock, so that we know we should get a view - of the page we're about to copy that is consistent with the - backup copies in the other thread's 'modified_old_objects'. */ - acquire_modified_objs_lock(shared_page_holder); - /* make our page private */ page_privatize_in(STM_SEGMENT->segment_num, pagenum); assert(get_page_status_in(my_segnum, pagenum) == PAGE_PRIVATE); + acquire_modified_objs_lock(copy_from_segnum); + pagecopy((char*)(get_virt_page_of(my_segnum, pagenum) * 4096UL), + (char*)(get_virt_page_of(copy_from_segnum, pagenum) * 4096UL)); + /* if there were modifications in the page, revert them. */ - copy_bk_objs_in_page_from(shared_page_holder, pagenum); + copy_bk_objs_in_page_from(copy_from_segnum, pagenum); /* we need to go from 'src_version' to 'target_version'. This - might need a walk into the past or the future. */ + might need a walk into the past. */ struct stm_commit_log_entry_s *src_version, *target_version; - src_version = get_priv_segment(shared_page_holder)->last_commit_log_entry; + src_version = get_priv_segment(copy_from_segnum)->last_commit_log_entry; + OPT_ASSERT(src_version->rev_num == most_recent_rev); target_version = STM_PSEGMENT->last_commit_log_entry; - release_modified_objs_lock(shared_page_holder); + release_modified_objs_lock(copy_from_segnum); release_all_privatization_locks(); - /* adapt revision of page to our revision: */ - if (src_version->rev_num < target_version->rev_num) - go_to_the_future(pagenum, src_version, target_version); - else if (src_version->rev_num > target_version->rev_num) + /* adapt revision of page to our revision: + if our rev is higher than the page we copy from, everything + is fine as we never read/modified the page anyway + */ + if (src_version->rev_num > target_version->rev_num) go_to_the_past(pagenum, src_version, target_version); } diff --git a/c8/test/test_basic.py b/c8/test/test_basic.py --- a/c8/test/test_basic.py +++ b/c8/test/test_basic.py @@ -339,6 +339,30 @@ py.test.raises(Conflict, self.commit_transaction) # + def test_read_write_17(self): + lp1 = stm_allocate_old(16) # allocated in seg0 + stm_get_real_address(lp1)[HDR] = 'a' #setchar + # S|P|P|P|P + # + # NO_ACCESS in all segments except seg0 (shared page holder) + # + # all seg at R0 + # + # + self.switch(1) # with private page + self.start_transaction() + stm_set_char(lp1, 'C') + self.commit_transaction() # R1 + assert last_commit_log_entries() == [lp1] # commit 'C' + self.start_transaction() + stm_set_char(lp1, 'c') # bk_copy + # + self.switch(3, validate=False) + self.start_transaction() # validate + assert stm_get_char(lp1) == 'C' # R1 + self.commit_transaction() + # + def test_commit_fresh_objects(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit