[pypy-commit] stmgc c8-gil-like: in-progress

arigo noreply at buildbot.pypy.org
Thu Jun 11 22:32:40 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: c8-gil-like
Changeset: r1805:ea72e4a504fd
Date: 2015-06-11 16:22 +0200
http://bitbucket.org/pypy/stmgc/changeset/ea72e4a504fd/

Log:	in-progress

diff --git a/c8/demo/demo_random.c b/c8/demo/demo_random.c
--- a/c8/demo/demo_random.c
+++ b/c8/demo/demo_random.c
@@ -57,9 +57,16 @@
 }
 
 
+long check_size(long size)
+{
+    assert(size >= sizeof(struct node_s));
+    assert(size <= sizeof(struct node_s) + 4096*70);
+    return size;
+}
+
 ssize_t stmcb_size_rounded_up(struct object_s *ob)
 {
-    return ((struct node_s*)ob)->my_size;
+    return check_size(((struct node_s*)ob)->my_size);
 }
 
 void stmcb_trace(struct object_s *obj, void visit(object_t **))
@@ -69,7 +76,8 @@
 
     /* and the same value at the end: */
     /* note, ->next may be the same as last_next */
-    nodeptr_t *last_next = (nodeptr_t*)((char*)n + n->my_size - sizeof(void*));
+    nodeptr_t *last_next = (nodeptr_t*)((char*)n + check_size(n->my_size)
+                                        - sizeof(void*));
 
     assert(n->next == *last_next);
 
@@ -113,36 +121,36 @@
     }
 }
 
-void reload_roots()
-{
-    int i;
-    assert(td.num_roots == td.num_roots_at_transaction_start);
-    for (i = td.num_roots_at_transaction_start - 1; i >= 0; i--) {
-        if (td.roots[i])
-            STM_POP_ROOT(stm_thread_local, td.roots[i]);
-    }
-
-    for (i = 0; i < td.num_roots_at_transaction_start; i++) {
-        if (td.roots[i])
-            STM_PUSH_ROOT(stm_thread_local, td.roots[i]);
-    }
-}
-
 void push_roots()
 {
     int i;
+    assert(td.num_roots_at_transaction_start <= td.num_roots);
     for (i = td.num_roots_at_transaction_start; i < td.num_roots; i++) {
         if (td.roots[i])
             STM_PUSH_ROOT(stm_thread_local, td.roots[i]);
     }
+    STM_SEGMENT->no_safe_point_here = 0;
 }
 
 void pop_roots()
 {
     int i;
-    for (i = td.num_roots - 1; i >= td.num_roots_at_transaction_start; i--) {
-        if (td.roots[i])
+    STM_SEGMENT->no_safe_point_here = 1;
+
+    assert(td.num_roots_at_transaction_start <= td.num_roots);
+    for (i = td.num_roots - 1; i >= 0; i--) {
+        if (td.roots[i]) {
             STM_POP_ROOT(stm_thread_local, td.roots[i]);
+            assert(td.roots[i]);
+        }
+    }
+
+    fprintf(stderr, "stm_is_inevitable() = %d\n", (int)stm_is_inevitable());
+    for (i = 0; i < td.num_roots_at_transaction_start; i++) {
+        if (td.roots[i]) {
+            fprintf(stderr, "root %d: %p\n", i, td.roots[i]);
+            STM_PUSH_ROOT(stm_thread_local, td.roots[i]);
+        }
     }
 }
 
@@ -150,6 +158,7 @@
 {
     int i;
     assert(idx >= td.num_roots_at_transaction_start);
+    assert(idx < td.num_roots);
 
     for (i = idx; i < td.num_roots - 1; i++)
         td.roots[i] = td.roots[i + 1];
@@ -158,6 +167,7 @@
 
 void add_root(objptr_t r)
 {
+    assert(td.num_roots_at_transaction_start <= td.num_roots);
     if (r && td.num_roots < MAXROOTS) {
         td.roots[td.num_roots++] = r;
     }
@@ -184,7 +194,8 @@
         nodeptr_t n = (nodeptr_t)p;
 
         /* and the same value at the end: */
-        nodeptr_t TLPREFIX *last_next = (nodeptr_t TLPREFIX *)((stm_char*)n + n->my_size - sizeof(void*));
+        nodeptr_t TLPREFIX *last_next = (nodeptr_t TLPREFIX *)((stm_char*)n +
+                                       check_size(n->my_size) - sizeof(void*));
         assert(n->next == *last_next);
         n->next = (nodeptr_t)v;
         *last_next = (nodeptr_t)v;
@@ -196,7 +207,8 @@
     nodeptr_t n = (nodeptr_t)p;
 
     /* and the same value at the end: */
-    nodeptr_t TLPREFIX *last_next = (nodeptr_t TLPREFIX *)((stm_char*)n + n->my_size - sizeof(void*));
+    nodeptr_t TLPREFIX *last_next = (nodeptr_t TLPREFIX *)((stm_char*)n +
+                                       check_size(n->my_size) - sizeof(void*));
     OPT_ASSERT(n->next == *last_next);
 
     return n->next;
@@ -229,7 +241,7 @@
                            sizeof(struct node_s) + (get_rand(100000) & ~15),
                            sizeof(struct node_s) + 4096,
                            sizeof(struct node_s) + 4096*70};
-        size_t size = sizes[get_rand(4)];
+        size_t size = check_size(sizes[get_rand(4)]);
         p = stm_allocate(size);
         nodeptr_t n = (nodeptr_t)p;
         n->sig = SIGNATURE;
@@ -240,7 +252,6 @@
         n->next = NULL;
         *last_next = NULL;
         pop_roots();
-        /* reload_roots not necessary, all are old after start_transaction */
         break;
     case 4:  // read and validate 'p'
         read_barrier(p);
@@ -306,7 +317,9 @@
         stm_become_inevitable(&stm_thread_local, "please");
         pop_roots();
         return NULL;
-    } else if (get_rand(240) == 1) {
+    } else if (0 &&            // XXXXXXXXXXXXXXXXXXXXX
+                                                       
+               get_rand(240) == 1) {
         push_roots();
         stm_become_globally_unique_transaction(&stm_thread_local, "really");
         fprintf(stderr, "[GUT/%d]", (int)STM_SEGMENT->segment_num);
@@ -352,13 +365,16 @@
     td.num_roots = td.num_roots_at_transaction_start;
     p = NULL;
     pop_roots();                /* does nothing.. */
-    reload_roots();
 
     while (td.steps_left-->0) {
         if (td.steps_left % 8 == 0)
             fprintf(stdout, "#");
 
-        assert(p == NULL || ((nodeptr_t)p)->sig == SIGNATURE);
+        int local_seg = STM_SEGMENT->segment_num;
+        int p_sig = p == NULL ? 0 : ((nodeptr_t)p)->sig;
+
+        assert(p == NULL || p_sig == SIGNATURE);
+        (void)local_seg;
 
         p = do_step(p);
 
@@ -366,7 +382,9 @@
             push_roots();
 
             long call_fork = (arg != NULL && *(long *)arg);
-            if (call_fork == 0) {   /* common case */
+            if (1 ||   // XXXXXXXXXXXXXXXX
+                                          
+                call_fork == 0) {   /* common case */
                 if (get_rand(100) < 50) {
                     stm_leave_transactional_zone(&stm_thread_local);
                     /* Nothing here; it's unlikely that a different thread
@@ -386,7 +404,6 @@
                 td.num_roots = td.num_roots_at_transaction_start;
                 p = NULL;
                 pop_roots();
-                reload_roots();
             }
             else {
                 /* run a fork() inside the transaction */
diff --git a/c8/stm/detach.c b/c8/stm/detach.c
--- a/c8/stm/detach.c
+++ b/c8/stm/detach.c
@@ -32,6 +32,7 @@
 
 void _stm_leave_noninevitable_transactional_zone(void)
 {
+    dprintf(("leave_noninevitable_transactional_zone\n"));
     _stm_become_inevitable(MSG_INEV_DONT_SLEEP);
 
     /* did it work? */
@@ -61,11 +62,13 @@
        disappear.  XXX could be done even earlier, as soon as we have
        read the shadowstack inside the minor collection. */
     STM_SEGMENT->running_thread = NULL;
+
+    _core_commit_transaction();
+
+
     write_fence();
     assert(_stm_detached_inevitable_from_thread == -1);
     _stm_detached_inevitable_from_thread = 0;
-
-    _core_commit_transaction();
 }
 
 void _stm_reattach_transaction(intptr_t old, stm_thread_local_t *tl)
@@ -75,6 +78,7 @@
         if (old == -1) {
             /* busy-loop: wait until _stm_detached_inevitable_from_thread
                is reset to a value different from -1 */
+            dprintf(("reattach_transaction: busy wait...\n"));
             while (_stm_detached_inevitable_from_thread == -1)
                 spin_loop();
 
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -309,6 +309,7 @@
     else
         assert(finalbase <= ssbase && ssbase <= current);
 
+    dprintf(("collect_roots_in_nursery:\n"));
     while (current > ssbase) {
         --current;
         uintptr_t x = (uintptr_t)current->ss;
@@ -320,6 +321,7 @@
         else {
             /* it is an odd-valued marker, ignore */
         }
+        dprintf(("    %p: %p -> %p\n", current, (void *)x, current->ss));
     }
 
     minor_trace_if_young(&tl->thread_local_obj);
@@ -519,6 +521,7 @@
 static void _do_minor_collection(bool commit)
 {
     dprintf(("minor_collection commit=%d\n", (int)commit));
+    assert(!STM_SEGMENT->no_safe_point_here);
 
     STM_PSEGMENT->minor_collect_will_commit_now = commit;
 
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -137,6 +137,9 @@
     setup_detach();
 
     set_gs_register(get_segment_base(0));
+
+    dprintf(("nursery: %p -> %p\n", (void *)NURSERY_START,
+                                    (void *)NURSERY_END));
 }
 
 void stm_teardown(void)
diff --git a/c8/stm/sync.c b/c8/stm/sync.c
--- a/c8/stm/sync.c
+++ b/c8/stm/sync.c
@@ -383,6 +383,7 @@
             break;    /* no safe point requested */
 
         dprintf(("enter safe point\n"));
+        assert(!STM_SEGMENT->no_safe_point_here);
         assert(STM_SEGMENT->nursery_end == NSE_SIGPAUSE);
         assert(pause_signalled);
 
@@ -397,6 +398,7 @@
         cond_wait(C_REQUEST_REMOVED);
         STM_PSEGMENT->safe_point = SP_RUNNING;
         timing_event(STM_SEGMENT->running_thread, STM_WAIT_DONE);
+        assert(!STM_SEGMENT->no_safe_point_here);
         dprintf(("left safe point\n"));
     }
 }
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -40,6 +40,7 @@
 
 struct stm_segment_info_s {
     uint8_t transaction_read_version;
+    uint8_t no_safe_point_here;    /* set from outside, triggers an assert */
     int segment_num;
     char *segment_base;
     stm_char *nursery_current;
@@ -420,10 +421,12 @@
    far more efficient than constantly starting and committing
    transactions.
 */
+#include <stdio.h>
 static inline void stm_enter_transactional_zone(stm_thread_local_t *tl) {
     intptr_t old;
     atomic_exchange(&_stm_detached_inevitable_from_thread, old, -1);
     if (old == (intptr_t)tl) {
+        fprintf(stderr, "stm_enter_transactional_zone fast path\n");
         _stm_detached_inevitable_from_thread = 0;
     }
     else {
@@ -434,10 +437,13 @@
 }
 static inline void stm_leave_transactional_zone(stm_thread_local_t *tl) {
     assert(STM_SEGMENT->running_thread == tl);
-    if (stm_is_inevitable())
+    if (stm_is_inevitable()) {
+        fprintf(stderr, "stm_leave_transactional_zone fast path\n");
         _stm_detach_inevitable_transaction(tl);
-    else
+    }
+    else {
         _stm_leave_noninevitable_transactional_zone();
+    }
 }
 
 /* stm_force_transaction_break() is in theory equivalent to
@@ -461,8 +467,9 @@
     assert(STM_SEGMENT->running_thread == tl);
     if (!stm_is_inevitable())
         _stm_become_inevitable(msg);
-    /* now, we're running the inevitable transaction, so: */
-    assert(_stm_detached_inevitable_from_thread == 0);
+    /* now, we're running the inevitable transaction, so this var should
+       be 0 (but can occasionally be -1 for a tiny amount of time) */
+    assert(((_stm_detached_inevitable_from_thread + 1) & ~1) == 0);
 }
 
 /* Forces a safe-point if needed.  Normally not needed: this is
diff --git a/duhton-c8/duhton.c b/duhton-c8/duhton.c
--- a/duhton-c8/duhton.c
+++ b/duhton-c8/duhton.c
@@ -41,7 +41,8 @@
             printf("))) ");
             fflush(stdout);
         }
-        stm_start_inevitable_transaction(&stm_thread_local);
+        stm_enter_transactional_zone(&stm_thread_local);
+        stm_become_inevitable(&stm_thread_local, "starting point");
         DuObject *code = Du_Compile(filename, interactive);
 
         if (code == NULL) {
@@ -58,7 +59,7 @@
         //stm_collect(0);   /* hack... */
         //_du_restore1(stm_thread_local_obj);
 
-        stm_commit_transaction();
+        stm_leave_transactional_zone(&stm_thread_local);
 
         Du_TransactionRun();
         if (!interactive)
diff --git a/duhton-c8/glob.c b/duhton-c8/glob.c
--- a/duhton-c8/glob.c
+++ b/duhton-c8/glob.c
@@ -713,11 +713,12 @@
     //stm_collect(0);       /* hack... */
     //_du_restore1(stm_thread_local_obj);
 
-    stm_commit_transaction();
+    stm_leave_transactional_zone(&stm_thread_local);
 
     Du_TransactionRun();
 
-    stm_start_inevitable_transaction(&stm_thread_local);
+    stm_enter_transactional_zone(&stm_thread_local);
+    stm_become_inevitable(&stm_thread_local, "run-transactions finished");
     return Du_None;
 }
 
@@ -809,7 +810,8 @@
     /* prebuilt objs stay on the shadowstack forever */
 
     stm_register_thread_local(&stm_thread_local);
-    stm_start_inevitable_transaction(&stm_thread_local);
+    stm_enter_transactional_zone(&stm_thread_local);
+    stm_become_inevitable(&stm_thread_local, "initialization");
 
     all_threads_count = num_threads;
     all_threads = (pthread_t*)malloc(sizeof(pthread_t) * num_threads);
@@ -857,7 +859,7 @@
     DuFrame_SetBuiltinMacro(Du_Globals, "pair?", du_pair);
     DuFrame_SetBuiltinMacro(Du_Globals, "assert", du_assert);
     DuFrame_SetSymbolStr(Du_Globals, "None", Du_None);
-    stm_commit_transaction();
+    stm_leave_transactional_zone(&stm_thread_local);
 }
 
 void Du_Finalize(void)
diff --git a/duhton-c8/transaction.c b/duhton-c8/transaction.c
--- a/duhton-c8/transaction.c
+++ b/duhton-c8/transaction.c
@@ -58,14 +58,14 @@
     if (TLOBJ == NULL)
         return;
 
-    stm_start_inevitable_transaction(&stm_thread_local);
+    stm_enter_transactional_zone(&stm_thread_local);
 
     DuConsObject *root = du_pending_transactions;
     _du_write1(root);
     root->cdr = TLOBJ;
 
     TLOBJ = NULL;
-    stm_commit_transaction();
+    stm_leave_transactional_zone(&stm_thread_local);
 
     run_all_threads();
 }


More information about the pypy-commit mailing list