[pypy-commit] stmgc hashtable: fix for test_minor_collect_bug1 and demo_hashtable1: see comments

arigo noreply at buildbot.pypy.org
Sat Nov 8 15:48:58 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: hashtable
Changeset: r1500:cf427187d1e0
Date: 2014-11-08 15:49 +0100
http://bitbucket.org/pypy/stmgc/changeset/cf427187d1e0/

Log:	fix for test_minor_collect_bug1 and demo_hashtable1: see comments

diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c
--- a/c7/stm/hashtable.c
+++ b/c7/stm/hashtable.c
@@ -240,7 +240,7 @@
     if (rc > 6) {
         /* we can only enter here once!  If we allocate stuff, we may
            run the GC, and so 'hashtableobj' might move afterwards. */
-        if (_is_from_same_transaction(hashtableobj)) {
+        if (_is_in_nursery(hashtableobj)) {
             entry = (stm_hashtable_entry_t *)
                 stm_allocate(sizeof(stm_hashtable_entry_t));
             entry->userdata = stm_hashtable_entry_userdata;
@@ -248,6 +248,26 @@
             entry->object = NULL;
         }
         else {
+            /* for a non-nursery 'hashtableobj', we pretend that the
+               'entry' object we're about to return was already
+               existing all along, with NULL in all segments.  If the
+               caller of this function is going to modify the 'object'
+               field, it will call stm_write(entry) first, which will
+               correctly schedule 'entry' for write propagation.  We
+               do that even if 'hashtableobj' was created by the
+               running transaction: the new 'entry' object is created
+               as if it was older than the transaction.
+
+               Note the following difference: if 'hashtableobj' is
+               still in the nursery (case above), the 'entry' object
+               is also allocated from the nursery, and after a minor
+               collection it ages as an old-but-created-by-the-
+               current-transaction object.  We could try to emulate
+               this here, or to create young 'entry' objects, but
+               doing either of these would require careful
+               synchronization with other pieces of the code that may
+               change.
+            */
             acquire_privatization_lock();
             char *p = allocate_outside_nursery_large(
                           sizeof(stm_hashtable_entry_t));
@@ -344,34 +364,9 @@
     }
 }
 
-static void _hashtable_minor_trace(object_t **pobj)
-{
-    abort();
-    object_t *obj = *pobj;
-    if (!_is_in_nursery(obj))
-        return;
-
-    TRACE_FOR_MINOR_COLLECTION(pobj);
-
-    obj = *pobj;
-    char *real_obj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
-    assert(((struct stm_hashtable_entry_s *)real_obj)->userdata ==
-           stm_hashtable_entry_userdata);
-
-    long j, num = STM_SEGMENT->segment_num;
-    for (j = 0; j <= NB_SEGMENTS; j++) {
-        if (j == num)
-            continue;
-        memcpy(REAL_ADDRESS(get_segment_base(j), obj), real_obj,
-               sizeof(struct stm_hashtable_entry_s));
-    }
-}
-
 void stm_hashtable_tracefn(stm_hashtable_t *hashtable, void trace(object_t **))
 {
-    if (trace == TRACE_FOR_MINOR_COLLECTION)
-        trace = &_hashtable_minor_trace;
-    else if (trace == TRACE_FOR_MAJOR_COLLECTION)
+    if (trace == TRACE_FOR_MAJOR_COLLECTION)
         _stm_compact_hashtable(hashtable);
 
     stm_hashtable_table_t *table;
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
@@ -187,6 +187,26 @@
         assert htget(h, 1) == lp1
         stm_major_collect()       # to get rid of the hashtable object
 
+    def test_minor_collect_bug1_different_thread(self):
+        self.start_transaction()
+        lp1 = stm_allocate(32)
+        self.push_root(lp1)
+        h = self.allocate_hashtable()
+        self.push_root(h)
+        stm_minor_collect()
+        h = self.pop_root()
+        lp1 = self.pop_root()
+        print 'h', h                       # 0xa040010
+        print 'lp1', lp1                   # 0xa040040
+        tl0 = self.tls[self.current_thread]
+        htset(h, 1, lp1, tl0)
+        self.commit_transaction()
+        #
+        self.switch(1)            # in a different thread
+        self.start_transaction()
+        assert htget(h, 1) == lp1
+        stm_major_collect()       # to get rid of the hashtable object
+
 
 class TestRandomHashtable(BaseTestHashtable):
 


More information about the pypy-commit mailing list