[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