[pypy-commit] stmgc c8-private-pages: switch back to using an extra segment (seg0) for malloc-things and later for optimizing memory usage

Raemi noreply at buildbot.pypy.org
Tue Jan 13 11:33:53 CET 2015


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: c8-private-pages
Changeset: r1520:f78d4b6f968e
Date: 2015-01-13 10:43 +0100
http://bitbucket.org/pypy/stmgc/changeset/f78d4b6f968e/

Log:	switch back to using an extra segment (seg0) for malloc-things and
	later for optimizing memory usage

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -132,7 +132,7 @@
     /* find who has the most recent revision of our page */
     int copy_from_segnum = -1;
     uint64_t most_recent_rev = 0;
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    for (i = 1; i < NB_SEGMENTS; i++) {
         if (i == my_segnum)
             continue;
 
@@ -350,7 +350,7 @@
             /* XXX: this optimization fails in test_basic.py, bug3 */
             /* OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS)); */
             /* int segnum; */
-            /* for (segnum = 0; segnum < NB_SEGMENTS; segnum++) { */
+            /* for (segnum = 1; segnum < NB_SEGMENTS; segnum++) { */
             /*     if (segment_really_copied_from & (1UL << segnum)) { */
             /*         /\* here we can actually have our own modified version, so */
             /*            make sure to only copy things that are not modified in our */
@@ -1030,6 +1030,7 @@
         ssize_t frag_size = STM_PSEGMENT->sq_fragsizes[j];
 
         char *src = REAL_ADDRESS(STM_SEGMENT->segment_base, frag);
+        /* XXX: including the sharing segment? */
         for (i = 0; i < NB_SEGMENTS; i++) {
             if (i == myself)
                 continue;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -17,7 +17,7 @@
 
 
 #define NB_PAGES            (2500*256)    // 2500MB
-#define NB_SEGMENTS         STM_NB_SEGMENTS
+#define NB_SEGMENTS         (STM_NB_SEGMENTS+1) /* +1 for sharing seg 0 */
 #define NB_SEGMENTS_MAX     240    /* don't increase NB_SEGMENTS past this */
 #define NB_NURSERY_PAGES    (STM_GC_NURSERY/4)
 
@@ -215,7 +215,7 @@
 {
 #ifndef NDEBUG
     long l;
-    for (l = 0; l < NB_SEGMENTS; l++) {
+    for (l = 1; l < NB_SEGMENTS; l++) {
         if (!get_priv_segment(l)->privatization_lock)
             return false;
     }
@@ -228,7 +228,7 @@
 static inline void acquire_all_privatization_locks()
 {
     long l;
-    for (l = 0; l < NB_SEGMENTS; l++) {
+    for (l = 1; l < NB_SEGMENTS; l++) {
         acquire_privatization_lock(l);
     }
 }
@@ -236,7 +236,7 @@
 static inline void release_all_privatization_locks()
 {
     long l;
-    for (l = NB_SEGMENTS-1; l >= 0; l--) {
+    for (l = NB_SEGMENTS-1; l >= 1; l--) {
         release_privatization_lock(l);
     }
 }
@@ -268,7 +268,7 @@
 
     /* acquire locks in global order */
     int i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    for (i = 1; i < NB_SEGMENTS; i++) {
         if ((seg_set & (1 << i)) == 0)
             continue;
 
@@ -282,7 +282,7 @@
     OPT_ASSERT(seg_set < (1 << NB_SEGMENTS));
 
     int i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    for (i = 1; i < NB_SEGMENTS; i++) {
         if ((seg_set & (1 << i)) == 0)
             continue;
 
diff --git a/c8/stm/fprintcolor.c b/c8/stm/fprintcolor.c
--- a/c8/stm/fprintcolor.c
+++ b/c8/stm/fprintcolor.c
@@ -8,7 +8,8 @@
     char buffer[2048];
     va_list ap;
     int result;
-    int size = (int)sprintf(buffer, "\033[%dm[%d,%lx] ", dprintfcolor(),
+    int size = (int)sprintf(buffer, "\033[%dm[%d,%d,%lx] ",
+                            dprintfcolor(), STM_SEGMENT->segment_num,
                             (int)getpid(), (long)pthread_self());
     assert(size >= 0);
 
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -16,10 +16,7 @@
 static void setup_N_pages(char *pages_addr, uint64_t num)
 {
     /* initialize to |N|P|N|N| */
-    long i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
-        acquire_privatization_lock(i);
-    }
+    acquire_all_privatization_locks();
 
     uintptr_t p = (pages_addr - stm_object_pages) / 4096UL;
     dprintf(("setup_N_pages(%p, %lu): pagenum %lu\n", pages_addr, num, p));
@@ -27,9 +24,7 @@
         page_mark_accessible(STM_SEGMENT->segment_num, p + num);
     }
 
-    for (i = NB_SEGMENTS-1; i >= 0; i--) {
-        release_privatization_lock(i);
-    }
+    release_all_privatization_locks();
 }
 
 
@@ -68,7 +63,8 @@
 {
     /* only for tests xxx but stm_setup_prebuilt() uses this now too */
     stm_char *p = allocate_outside_nursery_large(size_rounded_up);
-    memset(stm_object_pages + (uintptr_t)p, 0, size_rounded_up);
+    /* hardcode segment 1 */
+    memset(get_virtual_address(STM_SEGMENT->segment_num, (object_t *)p), 0, size_rounded_up);
 
     object_t *o = (object_t *)p;
     o->stm_flags = GCFLAG_WRITE_BARRIER;
diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -15,7 +15,7 @@
 
 char *_stm_get_segment_base(long index)
 {
-    return get_segment_base(index);
+    return get_segment_base(index+1);
 }
 
 struct stm_priv_segment_info_s *_stm_segment(void)
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -18,8 +18,10 @@
     assert(_STM_FAST_ALLOC <= NURSERY_SIZE);
     _stm_nursery_start = NURSERY_START;
 
-    long i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    long i = 0;
+    get_segment(i)->nursery_current = (stm_char *)-1;
+    get_segment(i)->nursery_end = -1;
+    for (i = 1; i < NB_SEGMENTS; i++) {
         get_segment(i)->nursery_current = (stm_char *)NURSERY_START;
         get_segment(i)->nursery_end = NURSERY_END;
     }
@@ -91,14 +93,13 @@
         realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
         size = stmcb_size_rounded_up((struct object_s *)realobj);
 
-        if (true /*size > GC_LAST_SMALL_SIZE*/) {
+        if (true || size > GC_LAST_SMALL_SIZE) {
             /* case 1: object is not small enough.
                Ask gcpage.c for an allocation via largemalloc. */
             nobj = (object_t *)allocate_outside_nursery_large(size);
         }
         else {
             /* case "small enough" */
-            abort();
             nobj = (object_t *)allocate_outside_nursery_small(size);
         }
 
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -50,6 +50,11 @@
     return get_segment_base(segnum) + pagenum * 4096;
 }
 
+static inline char *get_virtual_address(long segnum, object_t *obj)
+{
+    return get_segment_base(segnum) + (uintptr_t)obj;
+}
+
 static inline bool get_page_status_in(long segnum, uintptr_t pagenum)
 {
     OPT_ASSERT(segnum < 8 * sizeof(struct page_shared_s));
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -74,6 +74,7 @@
     setup_signal_handler();
 
     long i;
+    /* including seg0 */
     for (i = 0; i < NB_SEGMENTS; i++) {
         char *segment_base = get_segment_base(i);
 
@@ -195,22 +196,21 @@
     if (stm_all_thread_locals == NULL) {
         stm_all_thread_locals = tl->next = tl->prev = tl;
         num = 0;
-    }
-    else {
+    } else {
         tl->next = stm_all_thread_locals;
         tl->prev = stm_all_thread_locals->prev;
         stm_all_thread_locals->prev->next = tl;
         stm_all_thread_locals->prev = tl;
-        num = (tl->prev->associated_segment_num + 1) % NB_SEGMENTS;
+        num = (tl->prev->associated_segment_num) % (NB_SEGMENTS-1);
     }
 
     /* assign numbers consecutively, but that's for tests; we could also
        assign the same number to all of them and they would get their own
        numbers automatically. */
-    tl->associated_segment_num = num;
+    tl->associated_segment_num = num + 1;
     *_get_cpth(tl) = pthread_self();
     _init_shadow_stack(tl);
-    set_gs_register(get_segment_base(num));
+    set_gs_register(get_segment_base(num + 1));
     s_mutex_unlock();
 
     DEBUG_EXPECT_SEGFAULT(true);
diff --git a/c8/stm/smallmalloc.c b/c8/stm/smallmalloc.c
--- a/c8/stm/smallmalloc.c
+++ b/c8/stm/smallmalloc.c
@@ -284,7 +284,7 @@
         small_page_lists[szword] = NULL;
 
         /* process the pages that the various segments are busy filling */
-        for (i = 0; i < NB_SEGMENTS; i++) {
+        for (i = 1; i < NB_SEGMENTS; i++) {
             struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
             struct small_free_loc_s **fl =
                     &pseg->small_malloc_data.loc_free[szword];
diff --git a/c8/stm/sync.c b/c8/stm/sync.c
--- a/c8/stm/sync.c
+++ b/c8/stm/sync.c
@@ -13,7 +13,7 @@
         pthread_mutex_t global_mutex;
         pthread_cond_t cond[_C_TOTAL];
         /* some additional pieces of global state follow */
-        uint8_t in_use1[NB_SEGMENTS];   /* 1 if running a pthread */
+        uint8_t in_use1[NB_SEGMENTS];   /* 1 if running a pthread, idx=0 unused */
     };
     char reserved[192];
 } sync_ctl __attribute__((aligned(64)));
@@ -110,28 +110,29 @@
     assert(_has_mutex());
     assert(_is_tl_registered(tl));
 
-    int num = tl->associated_segment_num;
-    if (sync_ctl.in_use1[num] == 0) {
+    int num = tl->associated_segment_num - 1; // 0..NB_SEG-1
+    OPT_ASSERT(num >= 0);
+    if (sync_ctl.in_use1[num+1] == 0) {
         /* fast-path: we can get the same segment number than the one
            we had before.  The value stored in GS is still valid. */
 #ifdef STM_TESTS
         /* that can be optimized away, except during tests, because
            they use only one thread */
-        set_gs_register(get_segment_base(num));
+        set_gs_register(get_segment_base(num+1));
 #endif
-        dprintf(("acquired same segment: %d\n", num));
+        dprintf(("acquired same segment: %d\n", num+1));
         goto got_num;
     }
     /* Look for the next free segment.  If there is none, wait for
        the condition variable. */
     int retries;
-    for (retries = 0; retries < NB_SEGMENTS; retries++) {
-        num = num % NB_SEGMENTS;
-        if (sync_ctl.in_use1[num] == 0) {
+    for (retries = 0; retries < NB_SEGMENTS-1; retries++) {
+        num = (num+1) % (NB_SEGMENTS-1);
+        if (sync_ctl.in_use1[num+1] == 0) {
             /* we're getting 'num', a different number. */
-            dprintf(("acquired different segment: %d->%d\n", tl->associated_segment_num, num));
-            tl->associated_segment_num = num;
-            set_gs_register(get_segment_base(num));
+            dprintf(("acquired different segment: %d->%d\n", tl->associated_segment_num, num+1));
+            tl->associated_segment_num = num+1;
+            set_gs_register(get_segment_base(num+1));
             goto got_num;
         }
     }
@@ -142,8 +143,9 @@
     /* Return false to the caller, which will call us again */
     return false;
  got_num:
-    sync_ctl.in_use1[num] = 1;
-    assert(STM_SEGMENT->segment_num == num);
+    OPT_ASSERT(num >= 0 && num < NB_SEGMENTS-1);
+    sync_ctl.in_use1[num+1] = 1;
+    assert(STM_SEGMENT->segment_num == num+1);
     assert(STM_SEGMENT->running_thread == NULL);
     STM_SEGMENT->running_thread = tl;
     return true;
@@ -171,7 +173,7 @@
 bool _stm_in_transaction(stm_thread_local_t *tl)
 {
     int num = tl->associated_segment_num;
-    assert(0 <= num && num < NB_SEGMENTS);
+    assert(1 <= num && num < NB_SEGMENTS);
     return get_segment(num)->running_thread == tl;
 }
 
@@ -184,7 +186,7 @@
 
 void _stm_test_switch_segment(int segnum)
 {
-    set_gs_register(get_segment_base(segnum));
+    set_gs_register(get_segment_base(segnum+1));
 }
 
 #if STM_TESTS
@@ -219,7 +221,7 @@
     assert(_has_mutex());
 
     long i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    for (i = 1; i < NB_SEGMENTS; i++) {
         if (get_segment(i)->nursery_end == NURSERY_END)
             get_segment(i)->nursery_end = NSE_SIGPAUSE;
     }
@@ -235,7 +237,7 @@
     long result = 0;
     int my_num = STM_SEGMENT->segment_num;
 
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    for (i = 1; i < NB_SEGMENTS; i++) {
         if (i != my_num && get_priv_segment(i)->safe_point == SP_RUNNING) {
             assert(get_segment(i)->nursery_end <= _STM_NSE_SIGNAL_MAX);
             result++;
@@ -252,7 +254,7 @@
     assert((_safe_points_requested = false, 1));
 
     long i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
+    for (i = 1; i < NB_SEGMENTS; i++) {
         assert(get_segment(i)->nursery_end != NURSERY_END);
         if (get_segment(i)->nursery_end == NSE_SIGPAUSE)
             get_segment(i)->nursery_end = NURSERY_END;
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -1,4 +1,3 @@
-import os
 import cffi, weakref
 from common import parent_dir, source_files
 


More information about the pypy-commit mailing list