Author: Remi Meier <[email protected]>
Branch: 
Changeset: r1568:d24560f5557a
Date: 2015-01-21 17:26 +0100
http://bitbucket.org/pypy/stmgc/changeset/d24560f5557a/

Log:    free the commit log as part of major gcs

diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -154,7 +154,7 @@
     size_t written_count;
     struct stm_undo_s written[];
 };
-static struct stm_commit_log_entry_s commit_log_root = {NULL, -1, 0, 0};
+static struct stm_commit_log_entry_s commit_log_root;
 
 
 #ifndef STM_TESTS
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -531,6 +531,52 @@
     _stm_smallmalloc_sweep();
 }
 
+static void clean_up_commit_log_entries()
+{
+    struct stm_commit_log_entry_s *cl, *next;
+
+#ifndef NDEBUG
+    /* check that all segments are at the same revision: */
+    cl = get_priv_segment(0)->last_commit_log_entry;
+    for (long i = 1; i < NB_SEGMENTS; i++) {
+        assert(get_priv_segment(i)->last_commit_log_entry == cl);
+    }
+#endif
+
+    /* if there is only one element, we don't have to do anything: */
+    cl = &commit_log_root;
+
+    if (cl->next == NULL || cl->next == INEV_RUNNING)
+        return;
+
+    bool was_inev = false;
+    uint64_t rev_num = -1;
+
+    next = cl->next;   /* guaranteed to exist */
+    do {
+        cl = next;
+        rev_num = cl->rev_num;
+
+        next = cl->next;
+        free(cl);
+        if (next == INEV_RUNNING) {
+            was_inev = true;
+            break;
+        }
+    } while (next != NULL);
+
+    /* set the commit_log_root to the last, common cl entry: */
+    commit_log_root.next = was_inev ? INEV_RUNNING : NULL;
+    commit_log_root.rev_num = rev_num;
+
+    /* update in all segments: */
+    for (long i = 0; i < NB_SEGMENTS; i++) {
+        get_priv_segment(i)->last_commit_log_entry = &commit_log_root;
+    }
+
+    assert(_stm_count_cl_entries() == 0);
+}
+
 
 
 static void major_collection_now_at_safe_point(void)
@@ -544,6 +590,12 @@
 
     dprintf((" | used before collection: %ld\n",
              (long)pages_ctl.total_allocated));
+    dprintf((" | commit log entries before: %ld\n",
+             _stm_count_cl_entries()));
+
+    /* free all commit log entries. all segments are on the most recent
+       revision now. */
+    clean_up_commit_log_entries();
 
     /* only necessary because of assert that fails otherwise (XXX) */
     acquire_all_privatization_locks();
@@ -558,10 +610,10 @@
     mark_visit_from_roots();
     LIST_FREE(marked_objects_to_trace);
 
-    /* /\* cleanup *\/ */
+    /* cleanup */
     clean_up_segment_lists();
 
-    /* /\* sweeping *\/ */
+    /* sweeping */
     sweep_large_objects();
     sweep_small_objects();
 
diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -41,6 +41,19 @@
     return (obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) == 0;
 }
 
+long _stm_count_cl_entries()
+{
+    struct stm_commit_log_entry_s *cl = &commit_log_root;
+
+    long count = 0;
+    while ((cl = cl->next)) {
+        if (cl == INEV_RUNNING)
+            break;
+        count++;
+    }
+    return count;
+}
+
 
 #ifdef STM_TESTS
 bool _stm_is_accessible_page(uintptr_t pagenum)
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -78,6 +78,11 @@
     setup_protection_settings();
     setup_signal_handler();
 
+    commit_log_root.next = NULL;
+    commit_log_root.segment_num = -1;
+    commit_log_root.rev_num = 0;
+    commit_log_root.written_count = 0;
+
     long i;
     /* including seg0 */
     for (i = 0; i < NB_SEGMENTS; i++) {
@@ -129,6 +134,8 @@
        need to call it. */
     assert(!_has_mutex());
 
+    assert(commit_log_root.segment_num == -1);
+
     long i;
     for (i = 0; i < NB_SEGMENTS; i++) {
         struct stm_priv_segment_info_s *pr = get_priv_segment(i);
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -113,6 +113,7 @@
 object_t *_stm_enum_objects_pointing_to_nursery(long index);
 object_t *_stm_next_last_cl_entry();
 void _stm_start_enum_last_cl_entry();
+long _stm_count_cl_entries();
 
 uint64_t _stm_total_allocated(void);
 #endif
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -110,6 +110,7 @@
 object_t *_stm_enum_objects_pointing_to_nursery(long index);
 object_t *_stm_next_last_cl_entry();
 void _stm_start_enum_last_cl_entry();
+long _stm_count_cl_entries();
 
 void *memset(void *s, int c, size_t n);
 
@@ -435,6 +436,7 @@
 
 def stm_major_collect():
     res = lib._check_stm_collect(1)
+    assert count_commit_log_entries() == 0
     if res == 1:
         raise Conflict()
     return res
@@ -474,7 +476,7 @@
         return None
     return map(lib._stm_enum_old_objects_with_cards, range(count))
 
-def last_commit_log_entries():
+def last_commit_log_entry_objs():
     lib._stm_start_enum_last_cl_entry()
     res = []
     obj = lib._stm_next_last_cl_entry()
@@ -483,6 +485,9 @@
         obj = lib._stm_next_last_cl_entry()
     return res
 
+def count_commit_log_entries():
+    return lib._stm_count_cl_entries()
+
 
 
 SHADOWSTACK_LENGTH = 1000
diff --git a/c8/test/test_basic.py b/c8/test/test_basic.py
--- a/c8/test/test_basic.py
+++ b/c8/test/test_basic.py
@@ -33,12 +33,14 @@
         self.switch(1)
         self.start_transaction()
         self.commit_transaction()
-        assert last_commit_log_entries() == []
+        assert last_commit_log_entry_objs() == []
+        assert count_commit_log_entries() == 1
 
         self.switch(0)
 
         self.commit_transaction()
-        assert last_commit_log_entries() == []
+        assert last_commit_log_entry_objs() == []
+        assert count_commit_log_entries() == 2
 
     def test_simple_read(self):
         self.start_transaction()
@@ -46,7 +48,7 @@
         stm_read(lp1)
         assert stm_was_read(lp1)
         self.commit_transaction()
-        assert last_commit_log_entries() == []
+        assert last_commit_log_entry_objs() == []
 
     def test_simple_write(self):
         self.start_transaction()
@@ -57,7 +59,7 @@
         assert modified_old_objects() == []             # object not old
         assert objects_pointing_to_nursery() == []    # short transaction
         self.commit_transaction()
-        assert last_commit_log_entries() == []
+        assert last_commit_log_entry_objs() == []
 
     def test_allocate_old(self):
         lp1 = stm_allocate_old(16)
@@ -106,7 +108,7 @@
         #
         self.switch(1)
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1]
+        assert last_commit_log_entry_objs() == [lp1]
         #
         py.test.raises(Conflict, self.switch, 0) # detects rw conflict
 
@@ -128,13 +130,13 @@
         #
         self.switch(0)
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1] # commit '0'
+        assert last_commit_log_entry_objs() == [lp1] # commit '0'
         #
         py.test.raises(Conflict, self.switch, 1)
         self.start_transaction() # updates to '0'
         stm_set_char(lp1, 'x')
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1] # commit 'x'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'x'
         #
         if only_bk:
             self.start_transaction()
@@ -169,7 +171,7 @@
         #
         self.switch(1)
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1]
+        assert last_commit_log_entry_objs() == [lp1]
         # '1' is committed
         #
         if only_bk:
@@ -206,13 +208,13 @@
         #
         self.switch(0)
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1] # commit '0'
+        assert last_commit_log_entry_objs() == [lp1] # commit '0'
         #
         py.test.raises(Conflict, self.switch, 1)
         self.start_transaction() # updates to '0'
         stm_set_char(lp1, 'x')
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1] # commit 'x'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'x'
         #
         if only_bk:
             self.start_transaction()
@@ -240,7 +242,7 @@
         self.start_transaction()
         stm_set_char(lp1, 'C')
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp1] # commit 'C'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'C'
         #
         if only_bk:
             self.start_transaction()
@@ -270,7 +272,7 @@
         self.start_transaction()
         stm_set_char(lp2, 'C')
         self.commit_transaction() # R1
-        assert last_commit_log_entries() == [lp2] # commit 'C'
+        assert last_commit_log_entry_objs() == [lp2] # commit 'C'
         if only_bk:
             self.start_transaction()
             stm_set_char(lp2, 'c') # R1.1
@@ -279,7 +281,7 @@
         self.start_transaction()
         stm_set_char(lp1, 'D')
         self.commit_transaction()  # R2
-        assert last_commit_log_entries() == [lp1] # commit 'D'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'D'
         if only_bk:
             self.start_transaction()
             stm_set_char(lp1, 'd') # R2.1
@@ -309,13 +311,13 @@
         self.start_transaction()
         stm_set_char(lp2, 'C')
         self.commit_transaction() # R1
-        assert last_commit_log_entries() == [lp2] # commit 'C'
+        assert last_commit_log_entry_objs() == [lp2] # commit 'C'
         #
         self.switch(2)
         self.start_transaction()
         stm_set_char(lp1, 'D')
         self.commit_transaction()  # R2
-        assert last_commit_log_entries() == [lp1] # commit 'D'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'D'
         #
         self.switch(3)
         self.start_transaction() # stm_validate() -> R2
@@ -325,13 +327,13 @@
         self.start_transaction()
         stm_set_char(lp1, 'I')
         self.commit_transaction()  # R2
-        assert last_commit_log_entries() == [lp1] # commit 'I'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'I'
         #
         self.switch(1)
         self.start_transaction()
         stm_set_char(lp2, 'H')
         self.commit_transaction() # R3
-        assert last_commit_log_entries() == [lp2] # commit 'H'
+        assert last_commit_log_entry_objs() == [lp2] # commit 'H'
         #
         self.switch(3, validate=False) # R2 again
         assert stm_get_char(lp1) == 'D' # R2
@@ -353,7 +355,7 @@
         self.start_transaction()
         stm_set_char(lp1, 'C')
         self.commit_transaction() # R1
-        assert last_commit_log_entries() == [lp1] # commit 'C'
+        assert last_commit_log_entry_objs() == [lp1] # commit 'C'
         self.start_transaction()
         stm_set_char(lp1, 'c') # bk_copy
         #
@@ -384,7 +386,7 @@
         assert (p2 - p1) % 4096 == 0
         assert stm_get_char(lp) == 'u'
         self.commit_transaction()
-        assert last_commit_log_entries() == [lp]
+        assert last_commit_log_entry_objs() == [lp]
 
     def test_commit_fresh_objects2(self):
         self.switch(1)
diff --git a/c8/test/test_gcpage.py b/c8/test/test_gcpage.py
--- a/c8/test/test_gcpage.py
+++ b/c8/test/test_gcpage.py
@@ -409,3 +409,26 @@
 
         self.switch(1, False)
         py.test.raises(Conflict, stm_major_collect)
+
+
+    def test_cleaning_of_cl(self):
+        self.start_transaction()
+        stm_major_collect()
+        self.commit_transaction()
+
+        self.switch(1)
+        self.start_transaction()
+        self.commit_transaction()
+
+        self.switch(0)
+        self.start_transaction()
+        assert count_commit_log_entries() == 2
+        stm_major_collect()
+        assert count_commit_log_entries() == 0
+
+        stm_major_collect()
+
+        self.become_inevitable()
+        stm_major_collect()
+        stm_major_collect()
+        self.commit_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to