Author: Armin Rigo <[email protected]>
Branch: bag
Changeset: r1584:3665ef15024d
Date: 2015-01-24 15:22 +0100
http://bitbucket.org/pypy/stmgc/changeset/3665ef15024d/

Log:    Test and fix

diff --git a/c7/stm/bag.c b/c7/stm/bag.c
--- a/c7/stm/bag.c
+++ b/c7/stm/bag.c
@@ -46,6 +46,7 @@
         uintptr_t *deque_left, *deque_middle, *deque_right;
         struct list_s *abort_list;
         uint64_t start_time;    /* the transaction's unique_start_time */
+        bool must_add_to_overflow_bags;
     };
     char alignment[64];   /* 64-bytes alignment, to prevent false sharing */
 } stm_bag_seg_t;
@@ -73,6 +74,7 @@
         bs->deque_right = &block->items[0];
         LIST_CREATE(bs->abort_list);
         bs->start_time = 0;
+        bs->must_add_to_overflow_bags = false;   /* currently young */
     }
     return bag;
 }
@@ -80,6 +82,18 @@
 void stm_bag_free(stm_bag_t *bag)
 {
     int i;
+
+    s_mutex_lock();
+    for (i = 0; i < STM_NB_SEGMENTS; i++) {
+        stm_bag_seg_t *bs = &bag->by_segment[i];
+        struct stm_segment_info_s *pub = get_segment(i + 1);
+        stm_thread_local_t *tl = pub->running_thread;
+        if (tl != NULL && tl->associated_segment_num == i + 1) {
+            stm_call_on_abort(tl, bs, NULL);
+        }
+    }
+    s_mutex_unlock();
+
     for (i = 0; i < STM_NB_SEGMENTS; i++) {
         stm_bag_seg_t *bs = &bag->by_segment[i];
         struct deque_block_s *block = deque_block(bs->deque_left);
@@ -91,17 +105,6 @@
         LIST_FREE(bs->abort_list);
     }
 
-    s_mutex_lock();
-    for (i = 0; i < STM_NB_SEGMENTS; i++) {
-        stm_bag_seg_t *bs = &bag->by_segment[i];
-        struct stm_segment_info_s *pub = get_segment(i + 1);
-        stm_thread_local_t *tl = pub->running_thread;
-        if (tl->associated_segment_num == i + 1) {
-            stm_call_on_abort(tl, bs, NULL);
-        }
-    }
-    s_mutex_unlock();
-
     free(bag);
 }
 
@@ -151,6 +154,8 @@
         bs->deque_middle = bs->deque_right;
         list_clear(bs->abort_list);
         bs->start_time = STM_PSEGMENT->unique_start_time;
+        bs->must_add_to_overflow_bags = false;    /* not current transaction
+                                                     any more */
 
         /* We're about to modify the bag, so register an abort
            callback now. */
@@ -166,6 +171,13 @@
 {
     stm_bag_seg_t *bs = bag_check_start_time(bag);
     bag_add(bs, newobj);
+
+    if (bs->must_add_to_overflow_bags) {
+        bs->must_add_to_overflow_bags = false;
+        if (STM_PSEGMENT->overflow_bags == NULL)
+            LIST_CREATE(STM_PSEGMENT->overflow_bags);
+        LIST_APPEND(STM_PSEGMENT->overflow_bags, bag);
+    }
 }
 
 object_t *stm_bag_try_pop(stm_bag_t *bag)
@@ -201,6 +213,10 @@
         stm_bag_seg_t *bs = &bag->by_segment[i];
 
         deque_trace(bs->deque_middle, bs->deque_right, trace);
+
+        /* this case should only be called if the bag is from the current
+           transaction (either in the nursery or already overflowed) */
+        bs->must_add_to_overflow_bags = true;
     }
     else {
         int i;
@@ -210,3 +226,10 @@
         }
     }
 }
+
+static void collect_overflow_bags(void)
+{
+    LIST_FOREACH_R(STM_PSEGMENT->overflow_bags, stm_bag_t *,
+                   stm_bag_tracefn(item, TRACE_FOR_MINOR_COLLECTION));
+    LIST_FREE(STM_PSEGMENT->overflow_bags);
+}
diff --git a/c7/stm/bag.h b/c7/stm/bag.h
new file mode 100644
--- /dev/null
+++ b/c7/stm/bag.h
@@ -0,0 +1,2 @@
+
+static void collect_overflow_bags(void);
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -205,6 +205,10 @@
 
     /* regular finalizers (objs from the current transaction only) */
     struct finalizers_s *finalizers;
+
+    /* list of bags that are overflow objects (current transaction but
+       outside the nursery) */
+    struct list_s *overflow_bags;
 };
 
 enum /* safe_point */ {
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -578,6 +578,9 @@
     if (STM_PSEGMENT->finalizers != NULL)
         collect_objs_still_young_but_with_finalizers();
 
+    if (STM_PSEGMENT->overflow_bags != NULL)
+        collect_overflow_bags();
+
     collect_oldrefs_to_nursery();
     assert(list_is_empty(STM_PSEGMENT->old_objects_with_cards));
 
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -130,6 +130,7 @@
         pr->callbacks_on_commit_and_abort[1] = tree_create();
         pr->young_objects_with_light_finalizers = list_create();
         pr->old_objects_with_light_finalizers = list_create();
+        pr->overflow_bags = NULL;
         pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * i;
         highest_overflow_number = pr->overflow_number;
         pr->pub.transaction_read_version = 0xff;
@@ -174,6 +175,7 @@
         tree_free(pr->callbacks_on_commit_and_abort[1]);
         list_free(pr->young_objects_with_light_finalizers);
         list_free(pr->old_objects_with_light_finalizers);
+        list_free(pr->overflow_bags);
     }
 
     munmap(stm_object_pages, TOTAL_MEMORY);
diff --git a/c7/stmgc.c b/c7/stmgc.c
--- a/c7/stmgc.c
+++ b/c7/stmgc.c
@@ -16,6 +16,7 @@
 #include "stm/weakref.h"
 #include "stm/marker.h"
 #include "stm/finalizer.h"
+#include "stm/bag.h"
 
 #include "stm/misc.c"
 #include "stm/list.c"
diff --git a/c7/test/test_bag.py b/c7/test/test_bag.py
--- a/c7/test/test_bag.py
+++ b/c7/test/test_bag.py
@@ -93,6 +93,15 @@
         assert lp1b != ffi.NULL
         assert stm_get_char(lp1b) == 'N'
         assert lp1b != lp1
+        #
+        lp2 = stm_allocate(16)
+        stm_set_char(lp2, 'M')
+        b_add(b, lp2)
+        stm_minor_collect()
+        lp2b = b_pop(b)
+        assert lp2b != ffi.NULL
+        assert stm_get_char(lp2b) == 'M'
+        assert lp2b != lp2
 
     def test_keepalive_major(self):
         self.start_transaction()
diff --git a/c7/test/test_hashtable.py b/c7/test/test_hashtable.py
--- a/c7/test/test_hashtable.py
+++ b/c7/test/test_hashtable.py
@@ -146,6 +146,16 @@
         assert lp1b != ffi.NULL
         assert stm_get_char(lp1b) == 'N'
         assert lp1b != lp1
+        #
+        lp2 = stm_allocate(16)
+        stm_set_char(lp2, 'M')
+        tl0 = self.tls[self.current_thread]
+        htset(h, 1235, lp2, tl0)
+        stm_minor_collect()
+        lp2b = htget(h, 1235)
+        assert lp2b != ffi.NULL
+        assert stm_get_char(lp2b) == 'M'
+        assert lp2b != lp2
 
     def test_keepalive_major(self):
         lp1 = stm_allocate_old(16)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to