[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