Commit cf427187d1e by Armin Rigo

fix for test_minor_collect_bug1 and demo_hashtable1: see comments

--HG--
branch : hashtable
parent b27bcdd6bc8
......@@ -240,7 +240,7 @@ static stm_hashtable_entry_t *_stm_hashtable_lookup(object_t *hashtableobj,
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 @@ static stm_hashtable_entry_t *_stm_hashtable_lookup(object_t *hashtableobj,
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 _stm_compact_hashtable(stm_hashtable_t *hashtable)
}
}
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;
......
......@@ -187,6 +187,26 @@ class TestHashtable(BaseTestHashtable):
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):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment