[pypy-commit] stmgc default: some refactoring

Raemi noreply at buildbot.pypy.org
Thu Sep 4 17:31:34 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: 
Changeset: r1351:419893208d27
Date: 2014-09-04 16:11 +0200
http://bitbucket.org/pypy/stmgc/changeset/419893208d27/

Log:	some refactoring

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -29,7 +29,8 @@
        calls page_copy() and traps */
     /* XXX: mprotect is not reentrant and interruptible by signals,
        so it needs additional synchronisation.*/
-    mprotect(seg_base + pagenum * 4096UL, 4096, PROT_READ|PROT_WRITE);
+    pages_set_protection(segnum, pagenum, 1, PROT_READ|PROT_WRITE);
+
     page_privatize(pagenum);
 
     /* XXX: ... what can go wrong when we abort from inside
@@ -74,6 +75,7 @@
     volatile struct stm_commit_log_entry_s *cl = (volatile struct stm_commit_log_entry_s *)
         STM_PSEGMENT->last_commit_log_entry;
 
+    bool needs_abort = false;
     /* Don't check 'cl'. This entry is already checked */
     while ((cl = cl->next)) {
         size_t i = 0;
@@ -81,12 +83,10 @@
 
         object_t *obj;
         while ((obj = cl->written[i])) {
-
             _update_obj_from(cl->segment_num, obj);
 
-            if (_stm_was_read(obj)) {
-                free(free_if_abort);
-                stm_abort_transaction();
+            if (!needs_abort &&_stm_was_read(obj)) {
+                needs_abort = true;
             }
 
             i++;
@@ -95,6 +95,11 @@
         /* last fully validated entry */
         STM_PSEGMENT->last_commit_log_entry = (struct stm_commit_log_entry_s *)cl;
     }
+
+    if (needs_abort) {
+        free(free_if_abort);
+        stm_abort_transaction();
+    }
 }
 
 static struct stm_commit_log_entry_s *_create_commit_log_entry()
@@ -156,22 +161,27 @@
     char *realobj;
     size_t obj_size;
     uintptr_t i, end_page;
+    int my_segnum = STM_SEGMENT->segment_num;
 
     realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
     end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
 
     for (i = 0; i < NB_SEGMENTS; i++) {
-        if (i == STM_SEGMENT->segment_num)
+        if (i == my_segnum)
+            continue;
+        if (!is_readable_page(i, first_page))
             continue;
         /* XXX: only do it if not already PROT_NONE */
         char *segment_base = get_segment_base(i);
-        mprotect(segment_base + first_page * 4096,
-                 (end_page - first_page + 1) * 4096, PROT_NONE);
+        pages_set_protection(i, first_page, end_page - first_page + 1,
+                             PROT_NONE);
         dprintf(("prot %lu, len=%lu in seg %lu\n", first_page, (end_page - first_page + 1), i));
     }
 
+    acquire_modified_objs_lock(my_segnum);
     tree_insert(STM_PSEGMENT->modified_old_objects, (uintptr_t)obj, 0);
+    release_modified_objs_lock(my_segnum);
 
     LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
     obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
@@ -261,7 +271,9 @@
     minor_collection(1);
 
     struct stm_commit_log_entry_s* entry = _validate_and_add_to_commit_log();
+    acquire_modified_objs_lock(STM_SEGMENT->segment_num);
     /* XXX:discard backup copies */
+    release_modified_objs_lock(STM_SEGMENT->segment_num);
 
     s_mutex_lock();
 
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -48,6 +48,7 @@
 struct stm_priv_segment_info_s {
     struct stm_segment_info_s pub;
 
+    uint8_t modified_objs_lock;
     struct tree_s *modified_old_objects;
     struct list_s *objects_pointing_to_nursery;
     uint8_t privatization_lock;
@@ -127,3 +128,17 @@
                                             &STM_PSEGMENT->privatization_lock);
     spinlock_release(*lock);
 }
+
+static inline void acquire_modified_objs_lock(int segnum)
+{
+    uint8_t *lock = (uint8_t *)REAL_ADDRESS(get_segment_base(segnum),
+                                            &STM_PSEGMENT->modified_objs_lock);
+    spinlock_acquire(*lock);
+}
+
+static inline void release_modified_objs_lock(int segnum)
+{
+    uint8_t *lock = (uint8_t *)REAL_ADDRESS(get_segment_base(segnum),
+                                            &STM_PSEGMENT->modified_objs_lock);
+    spinlock_release(*lock);
+}
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -1,7 +1,7 @@
 #ifndef _STM_CORE_H_
 # error "must be compiled via stmgc.c"
 #endif
-
+#include <signal.h>
 
 /************************************************************/
 
@@ -67,12 +67,28 @@
         d_remap_file_pages(segment_base + pagenum * 4096UL,
                            count * 4096UL, pagenum);
     }
+
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        uint64_t bitmask = 1UL << i;
+        uintptr_t amount = count;
+        while (amount-->0) {
+            volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
+                &pages_readable[pagenum + amount - PAGE_FLAG_START];
+            if (i == 0) {
+                /* readable */
+                ps->by_segment |= bitmask;
+            } else {
+                /* not readable (ensured in setup.c) */
+                ps->by_segment &= ~bitmask;
+            }
+        }
+    }
 }
 
 static void page_privatize(uintptr_t pagenum)
 {
     /* check this thread's 'pages_privatized' bit */
-    uint64_t bitmask = 1UL << (STM_SEGMENT->segment_num - 1);
+    uint64_t bitmask = 1UL << STM_SEGMENT->segment_num;
     volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
         &pages_privatized[pagenum - PAGE_FLAG_START];
     if (ps->by_segment & bitmask) {
@@ -103,3 +119,27 @@
         spinlock_release(get_priv_segment(i)->privatization_lock);
     }
 }
+
+static void pages_set_protection(int segnum, uintptr_t pagenum,
+                                 uintptr_t count, int prot)
+{
+    char *addr = get_segment_base(segnum) + pagenum * 4096UL;
+    mprotect(addr, count * 4096UL, prot);
+
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        uint64_t bitmask = 1UL << i;
+        uintptr_t amount = count;
+        while (amount-->0) {
+            volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
+                &pages_readable[pagenum + amount - PAGE_FLAG_START];
+            if (prot == PROT_NONE) {
+                /* not readable */
+                ps->by_segment &= ~bitmask;
+            } else {
+                assert(prot == (PROT_READ|PROT_WRITE));
+                ps->by_segment |= bitmask;
+            }
+        }
+    }
+}
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -19,10 +19,12 @@
 };
 
 static struct page_shared_s pages_privatized[PAGE_FLAG_END - PAGE_FLAG_START];
+static struct page_shared_s pages_readable[PAGE_FLAG_END - PAGE_FLAG_START];
 
 static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
 static void page_privatize(uintptr_t pagenum);
-
+static void pages_set_protection(int segnum, uintptr_t pagenum,
+                                 uintptr_t count, int prot);
 
 static inline bool is_private_page(long segnum, uintptr_t pagenum)
 {
@@ -30,3 +32,10 @@
     uint64_t bitmask = 1UL << segnum;
     return (pages_privatized[pagenum - PAGE_FLAG_START].by_segment & bitmask);
 }
+
+static inline bool is_readable_page(long segnum, uintptr_t pagenum)
+{
+    assert(pagenum >= PAGE_FLAG_START);
+    uint64_t bitmask = 1UL << segnum;
+    return (pages_readable[pagenum - PAGE_FLAG_START].by_segment & bitmask);
+}
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -75,6 +75,8 @@
             mprotect(segment_base + END_NURSERY_PAGE * 4096,
                      (NB_PAGES - END_NURSERY_PAGE) * 4096,
                      PROT_NONE);
+            /* pages_initialize_shared() makes sure pages_readable
+               is initialized correctly */
         }
     }
 }


More information about the pypy-commit mailing list