[pypy-commit] stmgc c7-refactor: Fix the bug pointed out by test_commit_fresh_objects3

arigo noreply at buildbot.pypy.org
Mon Feb 17 19:19:58 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r763:e72de902728f
Date: 2014-02-17 19:19 +0100
http://bitbucket.org/pypy/stmgc/changeset/e72de902728f/

Log:	Fix the bug pointed out by test_commit_fresh_objects3

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -31,13 +31,14 @@
        only one page in total. */
     size_t obj_size = 0;
     uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
-    uintptr_t page_count = 1;
 
     /* If the object is in the uniform pages of small objects (outside the
        nursery), then it fits into one page.  Otherwise, we need to compute
        it based on its location and size. */
-    if ((obj->stm_flags & GCFLAG_SMALL_UNIFORM) == 0) {
-
+    if ((obj->stm_flags & GCFLAG_SMALL_UNIFORM) != 0) {
+        pages_privatize(first_page, 1);
+    }
+    else {
         /* get the size of the object */
         obj_size = stmcb_size_rounded_up(
             (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
@@ -45,9 +46,8 @@
         /* that's the page *following* the last page with the object */
         uintptr_t end_page = (((uintptr_t)obj) + obj_size + 4095) / 4096UL;
 
-        page_count = end_page - first_page;
+        pages_privatize(first_page, end_page - first_page);
     }
-    pages_privatize(first_page, page_count);
 
 
     /* do a read-barrier *before* the safepoints that may be issued in
@@ -246,12 +246,16 @@
     /* copy modified object versions to other threads */
     push_modified_to_other_segments();
 
+    /* reset the creation markers, and if necessary (i.e. if the page the
+       data is on is not SHARED) copy the data to other threads.  The
+       hope is that it's rarely necessary. */
+    reset_all_creation_markers_and_push_created_data();
+
     /* done */
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
     release_thread_segment(tl);
     STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
     STM_PSEGMENT->transaction_state = TS_NONE;
-    reset_all_creation_markers();
 
     mutex_unlock();
 }
diff --git a/c7/stm/pagecopy.c b/c7/stm/pagecopy.c
--- a/c7/stm/pagecopy.c
+++ b/c7/stm/pagecopy.c
@@ -1,30 +1,39 @@
+
+#define PAGECOPY_128(dest, src)                                         \
+        asm volatile("movdqa (%0), %%xmm0\n"                            \
+                     "movdqa 16(%0), %%xmm1\n"                          \
+                     "movdqa 32(%0), %%xmm2\n"                          \
+                     "movdqa 48(%0), %%xmm3\n"                          \
+                     "movdqa %%xmm0, (%1)\n"                            \
+                     "movdqa %%xmm1, 16(%1)\n"                          \
+                     "movdqa %%xmm2, 32(%1)\n"                          \
+                     "movdqa %%xmm3, 48(%1)\n"                          \
+                     "movdqa 64(%0), %%xmm0\n"                          \
+                     "movdqa 80(%0), %%xmm1\n"                          \
+                     "movdqa 96(%0), %%xmm2\n"                          \
+                     "movdqa 112(%0), %%xmm3\n"                         \
+                     "movdqa %%xmm0, 64(%1)\n"                          \
+                     "movdqa %%xmm1, 80(%1)\n"                          \
+                     "movdqa %%xmm2, 96(%1)\n"                          \
+                     "movdqa %%xmm3, 112(%1)\n"                         \
+                     :                                                  \
+                     : "r"(src), "r"(dest)                              \
+                     : "xmm0", "xmm1", "xmm2", "xmm3", "memory")
 
 static void pagecopy(void *dest, const void *src)
 {
     unsigned long i;
-    for (i=0; i<4096/128; i++) {
-        asm volatile("movdqa (%0), %%xmm0\n"
-                     "movdqa 16(%0), %%xmm1\n"
-                     "movdqa 32(%0), %%xmm2\n"
-                     "movdqa 48(%0), %%xmm3\n"
-                     "movdqa %%xmm0, (%1)\n"
-                     "movdqa %%xmm1, 16(%1)\n"
-                     "movdqa %%xmm2, 32(%1)\n"
-                     "movdqa %%xmm3, 48(%1)\n"
-                     "movdqa 64(%0), %%xmm0\n"
-                     "movdqa 80(%0), %%xmm1\n"
-                     "movdqa 96(%0), %%xmm2\n"
-                     "movdqa 112(%0), %%xmm3\n"
-                     "movdqa %%xmm0, 64(%1)\n"
-                     "movdqa %%xmm1, 80(%1)\n"
-                     "movdqa %%xmm2, 96(%1)\n"
-                     "movdqa %%xmm3, 112(%1)\n"
-                     :
-                     : "r"(src + 128*i), "r"(dest + 128*i)
-                     : "xmm0", "xmm1", "xmm2", "xmm3", "memory");
+    for (i = 0; i < 4096 / 128; i++) {
+        PAGECOPY_128(dest + 128*i, src + 128*i);
     }
 }
 
+static void pagecopy_256(void *dest, const void *src)
+{
+    PAGECOPY_128(dest,       src      );
+    PAGECOPY_128(dest + 128, src + 128);
+}
+
 #if 0   /* XXX enable if detected on the cpu */
 static void pagecopy_ymm8(void *dest, const void *src)
 {
diff --git a/c7/stm/pagecopy.h b/c7/stm/pagecopy.h
--- a/c7/stm/pagecopy.h
+++ b/c7/stm/pagecopy.h
@@ -1,2 +1,3 @@
 
-static void pagecopy(void *dest, const void *src);
+static void pagecopy(void *dest, const void *src);      // 4096 bytes
+static void pagecopy_256(void *dest, const void *src);  // 256 bytes
diff --git a/c7/stm/pages.c b/c7/stm/pages.c
--- a/c7/stm/pages.c
+++ b/c7/stm/pages.c
@@ -125,3 +125,51 @@
 
     list_clear(STM_PSEGMENT->creation_markers);
 }
+
+static void reset_all_creation_markers_and_push_created_data(void)
+{
+    /* This is like reset_all_creation_markers(), but additionally
+       it looks for markers in non-SHARED pages, and pushes the
+       corresponding data (in 256-bytes blocks) to other threads.
+    */
+#if NB_SEGMENTS != 2
+# error "The logic in this function only works with two segments"
+#endif
+
+    char *local_base = STM_SEGMENT->segment_base;
+    long remote_num = 1 - STM_SEGMENT->segment_num;
+    char *remote_base = get_segment_base(remote_num);
+
+    /* this logic assumes that creation markers are in 256-bytes blocks,
+       and pages are 4096 bytes, so creation markers are handled by groups
+       of 16 --- which is two 8-bytes uint64_t. */
+
+    LIST_FOREACH_R(
+        STM_PSEGMENT->creation_markers,
+        uintptr_t /*item*/,
+        ({
+            TLPREFIX uint64_t *p = (TLPREFIX uint64_t *)(item & ~15);
+            while (p[0] != 0 || p[1] != 0) {
+
+                uint64_t pagenum = ((uint64_t)p) >> 4;
+                if (flag_page_private[pagenum] != SHARED_PAGE) {
+                    /* copying needed */
+                    uint64_t dataofs = ((uint64_t)p) << 8;
+                    stm_char *start = (stm_char *)p;
+                    stm_char *stop = start + 16;
+                    while (start < stop) {
+                        if (*start++ != 0) {
+                            pagecopy_256(remote_base + dataofs,
+                                         local_base + dataofs);
+                        }
+                        dataofs += 256;
+                    }
+                }
+                p[0] = 0;
+                p[1] = 0;
+                p += 2;
+            }
+        }));
+
+    list_clear(STM_PSEGMENT->creation_markers);
+}
diff --git a/c7/stm/pages.h b/c7/stm/pages.h
--- a/c7/stm/pages.h
+++ b/c7/stm/pages.h
@@ -33,3 +33,4 @@
 static uint8_t get_single_creation_marker(stm_char *p);
 static void set_single_creation_marker(stm_char *p, int newvalue);
 static void reset_all_creation_markers(void);
+static void reset_all_creation_markers_and_push_created_data(void);


More information about the pypy-commit mailing list