Commits

Remi Meier committed 4fb6332

move some more code

Comments (0)

Files changed (6)

 
 #include "core.h"
 #include "list.h"
-#include "pagecopy.h"
 #include "reader_writer_lock.h"
 #include "nursery.h"
 #include "pages.h"
 
 
 
-#if defined(__i386__) || defined(__x86_64__)
-#  define HAVE_FULL_EXCHANGE_INSN
-#endif
-
-
-
 char *object_pages;
 static int num_threads_started;
 uint8_t write_locks[READMARKER_END - READMARKER_START];
 
 
-/************************************************************/
-
-
-static void spin_loop(void)
-{
-    asm("pause" : : : "memory");
-}
-
-
-static void write_fence(void)
-{
-#if defined(__amd64__) || defined(__i386__)
-    asm("" : : : "memory");
-#else
-#  error "Define write_fence() for your architecture"
-#endif
-}
-
-/************************************************************/
 
 
 /* a multi-reader, single-writer lock: transactions normally take a reader
 
 
 
-static void _stm_privatize(uintptr_t pagenum)
-{
-    if (flag_page_private[pagenum] == PRIVATE_PAGE)
-        return;
-
-#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);
-    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_TL->thread_num;
-    ssize_t otherpgoff = pgoff1 + NB_PAGES * (1 - _STM_TL->thread_num);
-
-    void *localpg = object_pages + localpgoff * 4096UL;
-    void *otherpg = 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);
-    if (res < 0) {
-        perror("remap_file_pages");
-        abort();
-    }
-    pagecopy(localpg, otherpg);
-    write_fence();
-    assert(flag_page_private[pagenum] == REMAPPING_PAGE);
-    flag_page_private[pagenum] = PRIVATE_PAGE;
-}
-
-
-
-
-
 
 char *_stm_real_address(object_t *o)
 {
     
     /* for old objects from the same transaction we don't need
        to privatize the page */
-    if ((flag_page_private[pagenum] == UNCOMMITTED_SHARED_PAGE)
+    if ((stm_get_page_flag(pagenum) == UNCOMMITTED_SHARED_PAGE)
         || (obj->stm_flags & GCFLAG_NOT_COMMITTED)) {
         obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
         return;
     }
 
     /* privatize if SHARED_PAGE */
-    /* xxx stmcb_size() is probably too slow */
+    /* xxx stmcb_size() is probably too slow, maybe add a GCFLAG_LARGE for
+       objs with more than 1 page */
     int pages = stmcb_size(real_address(obj)) / 4096;
     for (; pages >= 0; pages--)
-        _stm_privatize(pagenum + pages);
+        stm_pages_privatize(pagenum + pages);
 
     /* claim the write-lock for this object */
     uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - READMARKER_START;
     }
 
     for (i = FIRST_NURSERY_PAGE; i < FIRST_AFTER_NURSERY_PAGE; i++)
-        flag_page_private[i] = PRIVATE_PAGE; /* nursery is private.
+        stm_set_page_flag(i, PRIVATE_PAGE); /* nursery is private.
                                                 or should it be UNCOMMITTED??? */
     
     num_threads_started = 0;
 void _stm_teardown(void)
 {
     munmap(object_pages, TOTAL_MEMORY);
-    memset(flag_page_private, 0, sizeof(flag_page_private));
+    _stm_reset_page_flags();
     memset(write_locks, 0, sizeof(write_locks));
     object_pages = NULL;
 }
     return object_pages + thread_num * (NB_PAGES * 4096UL);
 }
 
+static inline void spin_loop(void)
+{
+    asm("pause" : : : "memory");
+}
+
+
+static inline void write_fence(void)
+{
+#if defined(__amd64__) || defined(__i386__)
+    asm("" : : : "memory");
+#else
+#  error "Define write_fence() for your architecture"
+#endif
+}
+
 
 /* ==================== API ==================== */
+
 static inline void stm_read(object_t *obj)
 {
     ((read_marker_t *)(((uintptr_t)obj) >> 4))->rm =
 
 void mark_page_as_uncommitted(uintptr_t pagenum)
 {
-    flag_page_private[pagenum] = UNCOMMITTED_SHARED_PAGE;
+    stm_set_page_flag(pagenum, UNCOMMITTED_SHARED_PAGE);
     LIST_APPEND(_STM_TL->uncommitted_pages, (object_t*)pagenum);
 }
 
             item->stm_flags &= ~GCFLAG_NOT_COMMITTED;
             
             uintptr_t pagenum = ((uintptr_t)item) / 4096UL;
-            if (flag_page_private[pagenum] == PRIVATE_PAGE) {
+            if (stm_get_page_flag(pagenum) == PRIVATE_PAGE) {
                 /* page was privatized... */
                 char *src = REAL_ADDRESS(local_base, item);
                 char *dst = REAL_ADDRESS(remote_base, item);
                                    reset in case of an abort */
         
         uintptr_t pagenum = ((uintptr_t)(alloc->next - 1)) / 4096UL;
-        if (flag_page_private[pagenum] == UNCOMMITTED_SHARED_PAGE) {
+        if (stm_get_page_flag(pagenum) == UNCOMMITTED_SHARED_PAGE) {
             /* becomes a SHARED (done below) partially used page */
             alloc->flag_partial_page = 1;
         }
         _STM_TL->uncommitted_pages,
         ({
             uintptr_t pagenum = (uintptr_t)item;
-            flag_page_private[pagenum] = SHARED_PAGE;
+            stm_set_page_flag(pagenum, SHARED_PAGE);
         }));
     stm_list_clear(_STM_TL->uncommitted_pages);
 }
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 #include "core.h"
 #include "list.h"
 #include "pages.h"
+#include "pagecopy.h"
+
+
+#if defined(__i386__) || defined(__x86_64__)
+#  define HAVE_FULL_EXCHANGE_INSN
+#endif
+
+
 
 uint8_t flag_page_private[NB_PAGES];
 uintptr_t index_page_never_used;
 
+void _stm_reset_page_flags()
+{
+    memset(flag_page_private, 0, sizeof(flag_page_private));
+}
 
-uint8_t _stm_get_page_flag(int pagenum)
+uint8_t stm_get_page_flag(int pagenum)
 {
     return flag_page_private[pagenum];
 }
 
+void stm_set_page_flag(int pagenum, uint8_t flag)
+{
+    assert(flag_page_private[pagenum] != flag);
+    flag_page_private[pagenum] = flag;
+}
+
+
+
+void stm_pages_privatize(uintptr_t pagenum)
+{
+    if (flag_page_private[pagenum] == PRIVATE_PAGE)
+        return;
+
+#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);
+    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_TL->thread_num;
+    ssize_t otherpgoff = pgoff1 + NB_PAGES * (1 - _STM_TL->thread_num);
+
+    void *localpg = object_pages + localpgoff * 4096UL;
+    void *otherpg = 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);
+    if (res < 0) {
+        perror("remap_file_pages");
+        abort();
+    }
+    pagecopy(localpg, otherpg);
+    write_fence();
+    assert(flag_page_private[pagenum] == REMAPPING_PAGE);
+    flag_page_private[pagenum] = PRIVATE_PAGE;
+}
+
 
 uintptr_t stm_pages_reserve(int num)
 {
 };  /* flag_page_private */
 
 
+void stm_pages_privatize(uintptr_t pagenum);
 uintptr_t stm_pages_reserve(int num);
-uint8_t _stm_get_page_flag(int pagenum);
+uint8_t stm_get_page_flag(int pagenum);
+void stm_set_page_flag(int pagenum, uint8_t flag);
+void _stm_reset_page_flags(void);
 
-extern uint8_t flag_page_private[NB_PAGES];
 
 
+

c7/test/support.py

 extern void stmcb_trace(struct object_s *, void (object_t **));
 
 uint8_t _stm_get_flags(object_t *obj);
-uint8_t _stm_get_page_flag(int pagenum);
+uint8_t stm_get_page_flag(int pagenum);
 enum {
     SHARED_PAGE=0,
     REMAPPING_PAGE,
     lib._stm_minor_collect()
 
 def stm_get_page_flag(pagenum):
-    return lib._stm_get_page_flag(pagenum)
+    return lib.stm_get_page_flag(pagenum)
 
 def stm_get_obj_size(o):
     return lib.stmcb_size(stm_get_real_address(o))