[pypy-commit] stmgc c7-refactor: _pages_privatize() with count > 1
arigo
noreply at buildbot.pypy.org
Wed Feb 19 07:12:15 CET 2014
Author: Armin Rigo <arigo at 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)
More information about the pypy-commit
mailing list