Author: Armin Rigo <ar...@tunes.org> Branch: c7-refactor Changeset: r772:902061e5b47e Date: 2014-02-19 07:12 +0100 http://bitbucket.org/pypy/stmgc/changeset/902061e5b47e/
Log: _pages_privatize() with count > 1 diff --git a/c7/stm/pages.c b/c7/stm/pages.c --- a/c7/stm/pages.c +++ b/c7/stm/pages.c @@ -25,37 +25,8 @@ } } -static void _pages_privatize(uintptr_t pagenum, uintptr_t count) +static void privatize_range_and_unlock(uintptr_t pagenum, uintptr_t count) { - assert(count == 1); /* XXX */ - -#ifdef HAVE_FULL_EXCHANGE_INSN - /* use __sync_lock_test_and_set() as a cheaper alternative to - __sync_bool_compare_and_swap(). */ - int previous = __sync_lock_test_and_set(&flag_page_private[pagenum], - REMAPPING_PAGE); - assert(previous != FREE_PAGE); - if (previous == PRIVATE_PAGE) { - flag_page_private[pagenum] = PRIVATE_PAGE; - return; - } - bool was_shared = (previous == SHARED_PAGE); -#else - bool was_shared = __sync_bool_compare_and_swap(&flag_page_private[pagenum], - SHARED_PAGE, REMAPPING_PAGE); -#endif - if (!was_shared) { - while (1) { - uint8_t state = ((uint8_t volatile *)flag_page_private)[pagenum]; - if (state != REMAPPING_PAGE) { - assert(state == PRIVATE_PAGE); - break; - } - spin_loop(); - } - return; - } - ssize_t pgoff1 = pagenum; ssize_t pgoff2 = pagenum + NB_PAGES; ssize_t localpgoff = pgoff1 + NB_PAGES * STM_SEGMENT->segment_num; @@ -64,18 +35,71 @@ void *localpg = stm_object_pages + localpgoff * 4096UL; void *otherpg = stm_object_pages + otherpgoff * 4096UL; - // XXX should not use pgoff2, but instead the next unused page in - // thread 2, so that after major GCs the next dirty pages are the - // same as the old ones - int res = remap_file_pages(localpg, 4096, 0, pgoff2, 0); + int res = remap_file_pages(localpg, count * 4096, 0, pgoff2, 0); if (res < 0) { perror("remap_file_pages"); abort(); } - pagecopy(localpg, otherpg); + uintptr_t i; + for (i = 0; i < count; i++) { + pagecopy(localpg + 4096 * i, otherpg + 4096 * i); + } write_fence(); - assert(flag_page_private[pagenum] == REMAPPING_PAGE); - flag_page_private[pagenum] = PRIVATE_PAGE; + for (i = 0; i < count; i++) { + assert(flag_page_private[pagenum + i] == REMAPPING_PAGE); + flag_page_private[pagenum + i] = PRIVATE_PAGE; + } +} + +static void _pages_privatize(uintptr_t pagenum, uintptr_t count) +{ + uintptr_t page_start_range = pagenum; + uintptr_t pagestop = pagenum + count; + + while (flag_page_private[pagenum + count - 1] == PRIVATE_PAGE) { + if (!--count) + return; + } + + for (; pagenum < pagestop; pagenum++) { +#ifdef HAVE_FULL_EXCHANGE_INSN + /* use __sync_lock_test_and_set() as a cheaper alternative to + __sync_bool_compare_and_swap(). */ + int prev = __sync_lock_test_and_set(&flag_page_private[pagenum], + REMAPPING_PAGE); + assert(prev != FREE_PAGE); + if (prev == PRIVATE_PAGE) { + flag_page_private[pagenum] = PRIVATE_PAGE; + } + bool was_shared = (prev == SHARED_PAGE); +#else + bool was_shared = __sync_bool_compare_and_swap( + &flag_page_private[pagenum + cnt1], + SHARED_PAGE, REMAPPING_PAGE); +#endif + if (!was_shared) { + if (pagenum > page_start_range) { + privatize_range_and_unlock(page_start_range, + pagenum - page_start_range); + } + page_start_range = pagenum + 1; + + while (1) { + uint8_t state; + state = ((uint8_t volatile *)flag_page_private)[pagenum]; + if (state != REMAPPING_PAGE) { + assert(state == PRIVATE_PAGE); + break; + } + spin_loop(); + } + } + } + + if (pagenum > page_start_range) { + privatize_range_and_unlock(page_start_range, + pagenum - page_start_range); + } } static void set_creation_markers(stm_char *p, uint64_t size, int newvalue) diff --git a/c7/stm/pages.h b/c7/stm/pages.h --- a/c7/stm/pages.h +++ b/c7/stm/pages.h @@ -22,9 +22,10 @@ static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count); inline static void pages_privatize(uintptr_t pagenum, uintptr_t count) { - while (flag_page_private[pagenum + count - 1] == PRIVATE_PAGE) { + while (flag_page_private[pagenum] == PRIVATE_PAGE) { if (!--count) return; + pagenum++; } _pages_privatize(pagenum, count); } diff --git a/c7/test/support.py b/c7/test/support.py --- a/c7/test/support.py +++ b/c7/test/support.py @@ -320,13 +320,13 @@ stm_read(obj) return lib._get_ptr(obj, idx) -def stm_set_char(obj, c): +def stm_set_char(obj, c, offset=HDR): stm_write(obj) - stm_get_real_address(obj)[HDR] = c + stm_get_real_address(obj)[offset] = c -def stm_get_char(obj): +def stm_get_char(obj, offset=HDR): stm_read(obj) - return stm_get_real_address(obj)[HDR] + return stm_get_real_address(obj)[offset] def stm_get_real_address(obj): return lib._stm_real_address(ffi.cast('object_t*', obj)) diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py --- a/c7/test/test_basic.py +++ b/c7/test/test_basic.py @@ -158,7 +158,6 @@ # visible from the other thread. self.start_transaction() lpx = stm_allocate(16) - print lpx stm_set_char(lpx, '.') self.commit_transaction() @@ -168,9 +167,7 @@ self.start_transaction() lpy = stm_allocate(16) - print lpy stm_set_char(lpy, 'y') - print "LAST COMMIT" self.commit_transaction() self.switch(1) @@ -379,6 +376,32 @@ self.start_transaction() assert stm_get_char(lp1) == 'b' + def test_object_on_two_pages(self): + self.start_transaction() + lp1 = stm_allocate(4104) + stm_set_char(lp1, '0') + stm_set_char(lp1, '1', offset=4103) + self.commit_transaction() + # + self.start_transaction() + stm_set_char(lp1, 'a') + stm_set_char(lp1, 'b', offset=4103) + # + self.switch(1) + self.start_transaction() + assert stm_get_char(lp1) == '0' + assert stm_get_char(lp1, offset=4103) == '1' + self.commit_transaction() + # + self.switch(0) + self.commit_transaction() + # + self.switch(1) + self.start_transaction() + assert stm_get_char(lp1) == 'a' + assert stm_get_char(lp1, offset=4103) == 'b' + self.commit_transaction() + # def test_resolve_write_write_no_conflict(self): # self.start_transaction() # p1 = stm_allocate(16) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit