Commit 3665ef15024 by Armin Rigo

Test and fix

--HG--
branch : bag
parent 4c2c1694892
......@@ -46,6 +46,7 @@ typedef union {
uintptr_t *deque_left, *deque_middle, *deque_right;
struct list_s *abort_list;
uint64_t start_time; /* the transaction's unique_start_time */
bool must_add_to_overflow_bags;
};
char alignment[64]; /* 64-bytes alignment, to prevent false sharing */
} stm_bag_seg_t;
......@@ -73,6 +74,7 @@ stm_bag_t *stm_bag_create(void)
bs->deque_right = &block->items[0];
LIST_CREATE(bs->abort_list);
bs->start_time = 0;
bs->must_add_to_overflow_bags = false; /* currently young */
}
return bag;
}
......@@ -80,28 +82,29 @@ stm_bag_t *stm_bag_create(void)
void stm_bag_free(stm_bag_t *bag)
{
int i;
for (i = 0; i < STM_NB_SEGMENTS; i++) {
stm_bag_seg_t *bs = &bag->by_segment[i];
struct deque_block_s *block = deque_block(bs->deque_left);
while (block != NULL) {
struct deque_block_s *nextblock = block->next;
deque_free_block(block);
block = nextblock;
}
LIST_FREE(bs->abort_list);
}
s_mutex_lock();
for (i = 0; i < STM_NB_SEGMENTS; i++) {
stm_bag_seg_t *bs = &bag->by_segment[i];
struct stm_segment_info_s *pub = get_segment(i + 1);
stm_thread_local_t *tl = pub->running_thread;
if (tl->associated_segment_num == i + 1) {
if (tl != NULL && tl->associated_segment_num == i + 1) {
stm_call_on_abort(tl, bs, NULL);
}
}
s_mutex_unlock();
for (i = 0; i < STM_NB_SEGMENTS; i++) {
stm_bag_seg_t *bs = &bag->by_segment[i];
struct deque_block_s *block = deque_block(bs->deque_left);
while (block != NULL) {
struct deque_block_s *nextblock = block->next;
deque_free_block(block);
block = nextblock;
}
LIST_FREE(bs->abort_list);
}
free(bag);
}
......@@ -151,6 +154,8 @@ static stm_bag_seg_t *bag_check_start_time(stm_bag_t *bag)
bs->deque_middle = bs->deque_right;
list_clear(bs->abort_list);
bs->start_time = STM_PSEGMENT->unique_start_time;
bs->must_add_to_overflow_bags = false; /* not current transaction
any more */
/* We're about to modify the bag, so register an abort
callback now. */
......@@ -166,6 +171,13 @@ void stm_bag_add(stm_bag_t *bag, object_t *newobj)
{
stm_bag_seg_t *bs = bag_check_start_time(bag);
bag_add(bs, newobj);
if (bs->must_add_to_overflow_bags) {
bs->must_add_to_overflow_bags = false;
if (STM_PSEGMENT->overflow_bags == NULL)
LIST_CREATE(STM_PSEGMENT->overflow_bags);
LIST_APPEND(STM_PSEGMENT->overflow_bags, bag);
}
}
object_t *stm_bag_try_pop(stm_bag_t *bag)
......@@ -201,6 +213,10 @@ void stm_bag_tracefn(stm_bag_t *bag, void trace(object_t **))
stm_bag_seg_t *bs = &bag->by_segment[i];
deque_trace(bs->deque_middle, bs->deque_right, trace);
/* this case should only be called if the bag is from the current
transaction (either in the nursery or already overflowed) */
bs->must_add_to_overflow_bags = true;
}
else {
int i;
......@@ -210,3 +226,10 @@ void stm_bag_tracefn(stm_bag_t *bag, void trace(object_t **))
}
}
}
static void collect_overflow_bags(void)
{
LIST_FOREACH_R(STM_PSEGMENT->overflow_bags, stm_bag_t *,
stm_bag_tracefn(item, TRACE_FOR_MINOR_COLLECTION));
LIST_FREE(STM_PSEGMENT->overflow_bags);
}
static void collect_overflow_bags(void);
......@@ -205,6 +205,10 @@ struct stm_priv_segment_info_s {
/* regular finalizers (objs from the current transaction only) */
struct finalizers_s *finalizers;
/* list of bags that are overflow objects (current transaction but
outside the nursery) */
struct list_s *overflow_bags;
};
enum /* safe_point */ {
......
......@@ -578,6 +578,9 @@ static void _do_minor_collection(bool commit)
if (STM_PSEGMENT->finalizers != NULL)
collect_objs_still_young_but_with_finalizers();
if (STM_PSEGMENT->overflow_bags != NULL)
collect_overflow_bags();
collect_oldrefs_to_nursery();
assert(list_is_empty(STM_PSEGMENT->old_objects_with_cards));
......
......@@ -130,6 +130,7 @@ void stm_setup(void)
pr->callbacks_on_commit_and_abort[1] = tree_create();
pr->young_objects_with_light_finalizers = list_create();
pr->old_objects_with_light_finalizers = list_create();
pr->overflow_bags = NULL;
pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * i;
highest_overflow_number = pr->overflow_number;
pr->pub.transaction_read_version = 0xff;
......@@ -174,6 +175,7 @@ void stm_teardown(void)
tree_free(pr->callbacks_on_commit_and_abort[1]);
list_free(pr->young_objects_with_light_finalizers);
list_free(pr->old_objects_with_light_finalizers);
list_free(pr->overflow_bags);
}
munmap(stm_object_pages, TOTAL_MEMORY);
......
......@@ -16,6 +16,7 @@
#include "stm/weakref.h"
#include "stm/marker.h"
#include "stm/finalizer.h"
#include "stm/bag.h"
#include "stm/misc.c"
#include "stm/list.c"
......
......@@ -93,6 +93,15 @@ class TestBag(BaseTestBag):
assert lp1b != ffi.NULL
assert stm_get_char(lp1b) == 'N'
assert lp1b != lp1
#
lp2 = stm_allocate(16)
stm_set_char(lp2, 'M')
b_add(b, lp2)
stm_minor_collect()
lp2b = b_pop(b)
assert lp2b != ffi.NULL
assert stm_get_char(lp2b) == 'M'
assert lp2b != lp2
def test_keepalive_major(self):
self.start_transaction()
......
......@@ -146,6 +146,16 @@ class TestHashtable(BaseTestHashtable):
assert lp1b != ffi.NULL
assert stm_get_char(lp1b) == 'N'
assert lp1b != lp1
#
lp2 = stm_allocate(16)
stm_set_char(lp2, 'M')
tl0 = self.tls[self.current_thread]
htset(h, 1235, lp2, tl0)
stm_minor_collect()
lp2b = htget(h, 1235)
assert lp2b != ffi.NULL
assert stm_get_char(lp2b) == 'M'
assert lp2b != lp2
def test_keepalive_major(self):
lp1 = stm_allocate_old(16)
......
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