[pypy-commit] stmgc bag: in-progress

arigo noreply at buildbot.pypy.org
Sat Jan 24 10:56:51 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: bag
Changeset: r1581:22510e2df160
Date: 2015-01-24 10:57 +0100
http://bitbucket.org/pypy/stmgc/changeset/22510e2df160/

Log:	in-progress

diff --git a/c7/stm/bag.c b/c7/stm/bag.c
--- a/c7/stm/bag.c
+++ b/c7/stm/bag.c
@@ -104,16 +104,34 @@
         return NULL;
     }
     struct deque_block_s *block = deque_block(bs->deque_left);
+    bool any_old_item_to_pop = (bs->deque_left != bs->deque_middle);
     uintptr_t result = *bs->deque_left++;
 
     if (bs->deque_left == &block->items[DEQUE_BLOCK_SIZE]) {
         bs->deque_left = &block->next->items[0];
         deque_free_block(block);
     }
+    if (!any_old_item_to_pop) {
+        bs->deque_middle = bs->deque_left;
+    }
     return (object_t *)result;
 }
 
-void stm_bag_tracefn(stm_bag_t *bag, void visit(object_t **))
+void stm_bag_tracefn(stm_bag_t *bag, void trace(object_t **))
 {
-    abort();
+    if (trace == TRACE_FOR_MINOR_COLLECTION) {
+        /* only trace the items added in the current transaction;
+           the rest is already old and cannot point into the nursery. */
+        int i = STM_SEGMENT->segment_num - 1;
+        struct stm_bag_seg_s *bs = &bag->by_segment[i];
+
+        deque_trace(bs->deque_middle, bs->deque_right, trace);
+    }
+    else {
+        int i;
+        for (i = 0; i < NB_SEGMENTS; i++) {
+            struct stm_bag_seg_s *bs = &bag->by_segment[i];
+            deque_trace(bs->deque_left, bs->deque_right, trace);
+        }
+    }
 }
diff --git a/c7/stm/list.c b/c7/stm/list.c
--- a/c7/stm/list.c
+++ b/c7/stm/list.c
@@ -212,3 +212,29 @@
     db->next = NULL;
     return db;
 }
+
+static void deque_trace(uintptr_t *start, uintptr_t *stop,
+                        void trace(object_t **))
+{
+    struct deque_block_s *block = deque_block(start);
+    struct deque_block_s *last_block = deque_block(stop);
+    uintptr_t *end;
+
+    while (1) {
+        if (block == last_block)
+            end = stop;
+        else
+            end = &block->items[DEQUE_BLOCK_SIZE];
+
+        while (start != end) {
+            trace((object_t **)start);
+            start++;
+        }
+
+        if (block == last_block)
+            break;
+
+        block = block->next;
+        start = &block->items[0];
+    }
+}
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -246,3 +246,5 @@
     struct deque_block_s *block = deque_block(inner_ptr);
     return (inner_ptr == &block->items[index]);
 }
+
+static void deque_trace(uintptr_t *start, uintptr_t *stop, void (object_t **));
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
@@ -79,3 +79,55 @@
             assert got == lp
         py.test.raises(BagLooksEmpty, b_pop, q)
         py.test.raises(BagLooksEmpty, b_pop, q)
+
+    def test_keepalive_minor(self):
+        self.start_transaction()
+        b = self.allocate_bag()
+        self.push_root(b)
+        lp1 = stm_allocate(16)
+        stm_set_char(lp1, 'N')
+        b_add(b, lp1)
+        stm_minor_collect()
+        b = self.pop_root()
+        lp1b = b_pop(b)
+        assert lp1b != ffi.NULL
+        assert stm_get_char(lp1b) == 'N'
+        assert lp1b != lp1
+
+    def test_keepalive_major(self):
+        self.start_transaction()
+        b = self.allocate_bag()
+        self.push_root(b)
+        lp1 = stm_allocate(16)
+        stm_set_char(lp1, 'N')
+        b_add(b, lp1)
+        stm_major_collect()
+        b = self.pop_root()
+        lp1b = b_pop(b)
+        assert lp1b != ffi.NULL
+        assert stm_get_char(lp1b) == 'N'
+        assert lp1b != lp1
+
+    def test_transaction_local(self):
+        self.start_transaction()
+        q = self.allocate_bag()
+        self.push_root(q)
+        self.commit_transaction()
+        q = self.pop_root()
+        #
+        self.start_transaction()
+        lp1 = stm_allocate(16)
+        b_add(q, lp1)
+        #
+        self.switch(1)
+        self.start_transaction()
+        lp2 = stm_allocate(16)
+        b_add(q, lp2)
+        got = b_pop(q)
+        assert got == lp2
+        #
+        self.switch(0)
+        got = b_pop(q)
+        assert got == lp1
+        #
+        stm_major_collect()       # to get rid of the bag object


More information about the pypy-commit mailing list