Author: Armin Rigo <ar...@tunes.org>
Branch: stmgc-c7
Changeset: r76450:3a58a18e3204
Date: 2015-03-18 09:57 +0100
http://bitbucket.org/pypy/pypy/changeset/3a58a18e3204/

Log:    import stmgc/a4fc9f31f925

diff --git a/rpython/translator/stm/src_stm/revision 
b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-b26fe28d6f2b
+a4fc9f31f925
diff --git a/rpython/translator/stm/src_stm/stm/core.c 
b/rpython/translator/stm/src_stm/stm/core.c
--- a/rpython/translator/stm/src_stm/stm/core.c
+++ b/rpython/translator/stm/src_stm/stm/core.c
@@ -833,7 +833,6 @@
 
 void stm_commit_transaction(void)
 {
- restart_all:
     exec_local_finalizers();
 
     assert(!_has_mutex());
@@ -853,11 +852,6 @@
        Important: we should not call cond_wait() in the meantime. */
     synchronize_all_threads(STOP_OTHERS_UNTIL_MUTEX_UNLOCK);
 
-    if (any_local_finalizers()) {
-        s_mutex_unlock();
-        goto restart_all;
-    }
-
     /* detect conflicts */
     if (detect_write_read_conflicts())
         goto restart;
diff --git a/rpython/translator/stm/src_stm/stm/extra.c 
b/rpython/translator/stm/src_stm/stm/extra.c
--- a/rpython/translator/stm/src_stm/stm/extra.c
+++ b/rpython/translator/stm/src_stm/stm/extra.c
@@ -6,15 +6,24 @@
 static long register_callbacks(stm_thread_local_t *tl,
                                void *key, void callback(void *), long index)
 {
-    if (!_stm_in_transaction(tl)) {
-        /* check that the current thread-local is really running a
+    dprintf(("register_callbacks: tl=%p key=%p callback=%p index=%ld\n",
+             tl, key, callback, index));
+    if (tl->associated_segment_num == -1) {
+        /* check that the provided thread-local is really running a
            transaction, and do nothing otherwise. */
+        dprintf(("  NOT IN TRANSACTION\n"));
         return -1;
     }
-
-    if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
+    /* The tl was only here to check that.  We're really using
+       STM_PSEGMENT below, which is often but not always the
+       segment corresponding to the tl.  One case where it's not
+       the case is if this gets called from stmcb_light_finalizer()
+       from abort_finalizers() from major collections or contention.
+    */
+    if (STM_PSEGMENT->transaction_state != TS_REGULAR) {
         /* ignore callbacks if we're in an inevitable transaction
-           (which cannot abort) */
+           (which cannot abort) or no transaction at all in this segment */
+        dprintf(("  STATE = %d\n", (int)STM_PSEGMENT->transaction_state));
         return -1;
     }
 
@@ -23,10 +32,13 @@
 
     if (callback == NULL) {
         /* double-unregistering works, but return 0 */
-        return tree_delete_item(callbacks, (uintptr_t)key);
+        long res = tree_delete_item(callbacks, (uintptr_t)key);
+        dprintf(("  DELETED %ld\n", res));
+        return res;
     }
     else {
         /* double-registering the same key will crash */
+        dprintf(("  INSERTING\n"));
         tree_insert(callbacks, (uintptr_t)key, (uintptr_t)callback);
         return 1;
     }
@@ -39,6 +51,7 @@
     if (result < 0 && callback != NULL) {
         /* no regular transaction running, invoke the callback
            immediately */
+        dprintf(("stm_call_on_commit calls now: %p(%p)\n", callback, key));
         callback(key);
     }
     return result;
@@ -72,8 +85,11 @@
         assert(key != NULL);
         assert(callback != NULL);
 
-        /* The callback may call stm_call_on_abort(key, NULL).  It is ignored,
-           because 'callbacks_on_commit_and_abort' was cleared already. */
+        /* The callback may call stm_call_on_abort(key, NULL)
+           (so with callback==NULL).  It is ignored, because
+           'callbacks_on_commit_and_abort' was cleared already. */
+        dprintf(("invoke_and_clear_user_callbacks(%ld): %p(%p)\n",
+                 index, callback, key));
         callback(key);
 
     } TREE_LOOP_END;
diff --git a/rpython/translator/stm/src_stm/stm/forksupport.c 
b/rpython/translator/stm/src_stm/stm/forksupport.c
--- a/rpython/translator/stm/src_stm/stm/forksupport.c
+++ b/rpython/translator/stm/src_stm/stm/forksupport.c
@@ -220,9 +220,8 @@
             if (endpagenum == NB_PAGES)
                 break;   /* done */
             pagenum = (uninitialized_page_stop - stm_object_pages) / 4096UL;
+            pagenum--;    /* contains data from largemalloc */
             endpagenum = NB_PAGES;
-            if (endpagenum == NB_PAGES)
-                break;   /* done */
         }
 
         struct page_shared_s ps = pages_privatized[pagenum - PAGE_FLAG_START];
diff --git a/rpython/translator/stm/src_stm/stm/gcpage.c 
b/rpython/translator/stm/src_stm/stm/gcpage.c
--- a/rpython/translator/stm/src_stm/stm/gcpage.c
+++ b/rpython/translator/stm/src_stm/stm/gcpage.c
@@ -418,12 +418,12 @@
 
     stm_thread_local_t *tl = stm_all_thread_locals;
     do {
-        /* If 'tl' is currently running, its 'associated_segment_num'
+        /* If 'tl' is currently running, its 'last_associated_segment_num'
            field is the segment number that contains the correct
            version of its overflowed objects.  If not, then the
            field is still some correct segment number, and it doesn't
            matter which one we pick. */
-        char *segment_base = get_segment_base(tl->associated_segment_num);
+        char *segment_base = get_segment_base(tl->last_associated_segment_num);
 
         struct stm_shadowentry_s *current = tl->shadowstack;
         struct stm_shadowentry_s *base = tl->shadowstack_base;
diff --git a/rpython/translator/stm/src_stm/stm/marker.c 
b/rpython/translator/stm/src_stm/stm/marker.c
--- a/rpython/translator/stm/src_stm/stm/marker.c
+++ b/rpython/translator/stm/src_stm/stm/marker.c
@@ -58,6 +58,7 @@
     */
     long i;
     int in_segment_num = out_marker->tl->associated_segment_num;
+    assert(in_segment_num >= 1);
     struct stm_priv_segment_info_s *pseg = get_priv_segment(in_segment_num);
     struct list_s *mlst = pseg->modified_old_objects;
     struct list_s *mlstm = pseg->modified_old_objects_markers;
diff --git a/rpython/translator/stm/src_stm/stm/nursery.c 
b/rpython/translator/stm/src_stm/stm/nursery.c
--- a/rpython/translator/stm/src_stm/stm/nursery.c
+++ b/rpython/translator/stm/src_stm/stm/nursery.c
@@ -263,9 +263,9 @@
     OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS
                || write_locks[first_card_index] == 255); /* see gcpage.c */
 
-    dprintf(("mark cards of %p, size %lu with %d, all: %d\n",
+  /*dprintf(("mark cards of %p, size %lu with %d, all: %d\n",
              obj, size, mark_value, mark_all));
-    dprintf(("obj has %lu cards\n", last_card_index));
+    dprintf(("obj has %lu cards\n", last_card_index));*/
     while (card_index <= last_card_index) {
         uintptr_t card_lock_idx = first_card_index + card_index;
 
diff --git a/rpython/translator/stm/src_stm/stm/pages.c 
b/rpython/translator/stm/src_stm/stm/pages.c
--- a/rpython/translator/stm/src_stm/stm/pages.c
+++ b/rpython/translator/stm/src_stm/stm/pages.c
@@ -63,12 +63,12 @@
 
 static void d_remap_file_pages(char *addr, size_t size, ssize_t pgoff)
 {
-    dprintf(("remap_file_pages: 0x%lx bytes: (seg%ld %p) --> (seg%ld %p)\n",
+    /*dprintf(("remap_file_pages: 0x%lx bytes: (seg%ld %p) --> (seg%ld %p)\n",
              (long)size,
              (long)((addr - stm_object_pages) / 4096UL) / NB_PAGES,
              (void *)((addr - stm_object_pages) % (4096UL * NB_PAGES)),
              (long)pgoff / NB_PAGES,
-             (void *)((pgoff % NB_PAGES) * 4096UL)));
+             (void *)((pgoff % NB_PAGES) * 4096UL)));*/
     assert(size % 4096 == 0);
     assert(size <= TOTAL_MEMORY);
     assert(((uintptr_t)addr) % 4096 == 0);
diff --git a/rpython/translator/stm/src_stm/stm/setup.c 
b/rpython/translator/stm/src_stm/stm/setup.c
--- a/rpython/translator/stm/src_stm/stm/setup.c
+++ b/rpython/translator/stm/src_stm/stm/setup.c
@@ -255,7 +255,7 @@
         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;
+        num = tl->prev->last_associated_segment_num;
     }
     tl->thread_local_obj = NULL;
 
@@ -263,7 +263,8 @@
        assign the same number to all of them and they would get their own
        numbers automatically. */
     num = (num % NB_SEGMENTS) + 1;
-    tl->associated_segment_num = num;
+    tl->associated_segment_num = -1;
+    tl->last_associated_segment_num = num;
     tl->thread_local_counter = ++thread_local_counters;
     *_get_cpth(tl) = pthread_self();
     _init_shadow_stack(tl);
diff --git a/rpython/translator/stm/src_stm/stm/sync.c 
b/rpython/translator/stm/src_stm/stm/sync.c
--- a/rpython/translator/stm/src_stm/stm/sync.c
+++ b/rpython/translator/stm/src_stm/stm/sync.c
@@ -141,6 +141,27 @@
     }
 }
 
+void stm_wait_for_current_inevitable_transaction(void)
+{
+    long i;
+    for (i = 1; i <= NB_SEGMENTS; i++) {
+        struct stm_priv_segment_info_s *other_pseg = get_priv_segment(i);
+        if (other_pseg->transaction_state == TS_INEVITABLE) {
+            /* Asynchronously found out that there is an inevitable
+               transaction running.  Wait until it signals "done",
+               then return (even if another inev transaction started
+               in the meantime).
+             */
+            s_mutex_lock();
+            if (other_pseg->transaction_state == TS_INEVITABLE)
+                cond_wait(C_INEVITABLE);
+            /*else: this inev transaction finished just now */
+            s_mutex_unlock();
+            break;
+        }
+    }
+}
+
 static bool acquire_thread_segment(stm_thread_local_t *tl)
 {
     /* This function acquires a segment for the currently running thread,
@@ -148,7 +169,7 @@
     assert(_has_mutex());
     assert(_is_tl_registered(tl));
 
-    int num = tl->associated_segment_num;
+    int num = tl->last_associated_segment_num;
     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. */
@@ -167,8 +188,9 @@
         num = (num % 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;
+            dprintf(("acquired different segment: %d->%d\n",
+                     tl->last_associated_segment_num, num));
+            tl->last_associated_segment_num = num;
             set_gs_register(get_segment_base(num));
             goto got_num;
         }
@@ -186,6 +208,7 @@
     sync_ctl.in_use1[num - 1] = 1;
     assert(STM_SEGMENT->segment_num == num);
     assert(STM_SEGMENT->running_thread == NULL);
+    tl->associated_segment_num = tl->last_associated_segment_num;
     STM_SEGMENT->running_thread = tl;
     return true;
 }
@@ -204,10 +227,12 @@
     }
 
     assert(STM_SEGMENT->running_thread == tl);
+    assert(tl->associated_segment_num == tl->last_associated_segment_num);
+    tl->associated_segment_num = -1;
     STM_SEGMENT->running_thread = NULL;
 
-    assert(sync_ctl.in_use1[tl->associated_segment_num - 1] == 1);
-    sync_ctl.in_use1[tl->associated_segment_num - 1] = 0;
+    assert(sync_ctl.in_use1[tl->last_associated_segment_num - 1] == 1);
+    sync_ctl.in_use1[tl->last_associated_segment_num - 1] = 0;
 }
 
 __attribute__((unused))
@@ -218,9 +243,16 @@
 
 bool _stm_in_transaction(stm_thread_local_t *tl)
 {
-    int num = tl->associated_segment_num;
-    assert(1 <= num && num <= NB_SEGMENTS);
-    return get_segment(num)->running_thread == tl;
+    if (tl->associated_segment_num == -1) {
+        return false;
+    }
+    else {
+        int num = tl->associated_segment_num;
+        OPT_ASSERT(1 <= num && num <= NB_SEGMENTS);
+        OPT_ASSERT(num == tl->last_associated_segment_num);
+        OPT_ASSERT(get_segment(num)->running_thread == tl);
+        return true;
+    }
 }
 
 void _stm_test_switch(stm_thread_local_t *tl)
diff --git a/rpython/translator/stm/src_stm/stmgc.h 
b/rpython/translator/stm/src_stm/stmgc.h
--- a/rpython/translator/stm/src_stm/stmgc.h
+++ b/rpython/translator/stm/src_stm/stmgc.h
@@ -69,6 +69,7 @@
     long last_abort__bytes_in_nursery;
     /* the next fields are handled internally by the library */
     int associated_segment_num;
+    int last_associated_segment_num;
     int thread_local_counter;
     struct stm_thread_local_s *prev, *next;
     void *creating_pthread[2];
@@ -331,6 +332,10 @@
 void stm_start_inevitable_transaction(stm_thread_local_t *tl);
 void stm_commit_transaction(void);
 
+/* Temporary fix?  Call this outside a transaction.  If there is an
+   inevitable transaction running somewhere else, wait until it finishes. */
+void stm_wait_for_current_inevitable_transaction(void);
+
 /* Abort the currently running transaction.  This function never
    returns: it jumps back to the stm_start_transaction(). */
 void stm_abort_transaction(void) __attribute__((noreturn));
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to