[pypy-commit] stmgc c7: make test pass
Remi Meier
noreply at buildbot.pypy.org
Tue Jan 21 16:49:05 CET 2014
Author: Remi Meier
Branch: c7
Changeset: r660:33eb0c7ce3c8
Date: 2014-01-21 16:49 +0100
http://bitbucket.org/pypy/stmgc/changeset/33eb0c7ce3c8/
Log: make test pass
diff --git a/c7/core.c b/c7/core.c
--- a/c7/core.c
+++ b/c7/core.c
@@ -55,7 +55,8 @@
bool need_abort;
char *thread_base;
struct stm_list_s *modified_objects;
- struct stm_list_s *new_object_ranges;
+ struct stm_list_s *uncommitted_objects;
+ struct stm_list_s *uncommitted_object_ranges;
struct alloc_for_size_s alloc[LARGE_OBJECT_WORDS];
localchar_t *nursery_current;
object_t **old_shadow_stack;
@@ -345,6 +346,36 @@
}
}
+static void push_uncommitted_to_other_threads()
+{
+ /* WE HAVE THE EXCLUSIVE LOCK HERE */
+
+ struct stm_list_s *uncommitted = _STM_TL2->uncommitted_objects;
+ char *local_base = _STM_TL2->thread_base;
+ char *remote_base = get_thread_base(1 - _STM_TL2->thread_num);
+
+ STM_LIST_FOREACH(
+ uncommitted,
+ ({
+ /* write-lock always cleared for these objects */
+ uintptr_t lock_idx;
+ assert(lock_idx = (((uintptr_t)item) >> 4) - READMARKER_START);
+ assert(!write_locks[lock_idx]);
+
+ /* remove the flag (they are now committed) */
+ item->stm_flags &= ~GCFLAG_NOT_COMMITTED;
+
+ uintptr_t pagenum = ((uintptr_t)item) / 4096UL;
+ if (flag_page_private[pagenum] == PRIVATE_PAGE) {
+ /* page was privatized... */
+ char *src = REAL_ADDRESS(local_base, item);
+ char *dst = REAL_ADDRESS(remote_base, item);
+ size_t size = stmcb_size((struct object_s*)src);
+ memcpy(dst, src, size);
+ }
+ }));
+}
+
@@ -353,9 +384,8 @@
{
uintptr_t pagenum = ((uintptr_t)obj) / 4096;
assert(pagenum < NB_PAGES);
-
- _STM_TL2->old_objects_to_trace = stm_list_append
- (_STM_TL2->old_objects_to_trace, obj);
+
+ LIST_APPEND(_STM_TL2->old_objects_to_trace, obj);
/* for old objects from the same transaction we don't need
to privatize the page */
@@ -389,8 +419,7 @@
obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
stm_read(obj);
- _STM_TL2->modified_objects = stm_list_append
- (_STM_TL2->modified_objects, obj);
+ LIST_APPEND(_STM_TL2->modified_objects, obj);
}
@@ -422,15 +451,15 @@
((start) = (uint16_t)(uintptr_t)(range), \
(stop) = ((uintptr_t)(range)) >> 16)
-localchar_t *_stm_alloc_old(size_t size)
+object_t *_stm_alloc_old(size_t size)
{
- localchar_t *result;
+ object_t *result;
size_t size_class = size / 8;
assert(size_class >= 2);
if (size_class >= LARGE_OBJECT_WORDS) {
- result = (localchar_t*)_stm_allocate_old(size);
- ((object_t*)result)->stm_flags &= ~GCFLAG_WRITE_BARRIER; /* added by _stm_allocate_old... */
+ result = _stm_allocate_old(size);
+ result->stm_flags &= ~GCFLAG_WRITE_BARRIER; /* added by _stm_allocate_old... */
int page = ((uintptr_t)result) / 4096;
int pages = (size + 4095) / 4096;
@@ -440,18 +469,22 @@
}
} else {
alloc_for_size_t *alloc = &_STM_TL2->alloc[size_class];
-
- if ((uint16_t)((uintptr_t)alloc->next) == alloc->stop)
- result = _stm_alloc_next_page(size_class);
- else {
- result = alloc->next;
+
+ if ((uint16_t)((uintptr_t)alloc->next) == alloc->stop) {
+ result = (object_t *)_stm_alloc_next_page(size_class);
+ } else {
+ result = (object_t *)alloc->next;
alloc->next += size;
+ if (alloc->flag_partial_page) {
+ LIST_APPEND(_STM_TL2->uncommitted_objects, result);
+ result->stm_flags |= GCFLAG_NOT_COMMITTED;
+ }
}
}
return result;
}
-localchar_t *_stm_alloc_next_page(size_t i)
+localchar_t *_stm_alloc_next_page(size_t size_class)
{
/* 'alloc->next' points to where the next allocation should go. The
present function is called instead when this next allocation is
@@ -459,27 +492,11 @@
'stop' are always nearby pointers, we play tricks and only store
the lower 16 bits of 'start' and 'stop', so that the three
variables plus some flags fit in 16 bytes.
-
- 'flag_partial_page' is *cleared* to mean that the 'alloc'
- describes a complete page, so that it needs not be listed inside
- 'new_object_ranges'. In all other cases it is *set*.
*/
uintptr_t page;
localchar_t *result;
- alloc_for_size_t *alloc = &_STM_TL2->alloc[i];
- size_t size = i * 8;
-
- /* if (alloc->flag_partial_page) { */
- /* /\* record this range in 'new_object_ranges' *\/ */
- /* localchar_t *ptr1 = alloc->next - size - 1; */
- /* object_t *range; */
- /* TO_RANGE(range, alloc->start, alloc->stop); */
- /* page = ((uintptr_t)ptr1) / 4096; */
- /* _STM_TL2->new_object_ranges = stm_list_append( */
- /* _STM_TL2->new_object_ranges, (object_t *)page); */
- /* _STM_TL2->new_object_ranges = stm_list_append( */
- /* _STM_TL2->new_object_ranges, range); */
- /* } */
+ alloc_for_size_t *alloc = &_STM_TL2->alloc[size_class];
+ size_t size = size_class * 8;
/* reserve a fresh new page */
page = _stm_reserve_pages(1);
@@ -499,8 +516,7 @@
void mark_page_as_uncommitted(uintptr_t pagenum)
{
flag_page_private[pagenum] = UNCOMMITTED_SHARED_PAGE;
- _STM_TL2->uncommitted_pages = stm_list_append
- (_STM_TL2->uncommitted_pages, (object_t*)pagenum);
+ LIST_APPEND(_STM_TL2->uncommitted_pages, (object_t*)pagenum);
}
void trace_if_young(object_t **pobj)
@@ -521,6 +537,10 @@
/* move obj to somewhere else */
size_t size = stmcb_size(real_address(*pobj));
object_t *moved = (object_t*)_stm_alloc_old(size);
+
+ if (moved->stm_flags & GCFLAG_NOT_COMMITTED)
+ (*pobj)->stm_flags |= GCFLAG_NOT_COMMITTED; /* XXX: memcpy below overwrites this otherwise.
+ find better solution.*/
memcpy((void*)real_address(moved),
(void*)real_address(*pobj),
@@ -530,8 +550,7 @@
*pforwarded = moved;
*pobj = moved;
- _STM_TL2->old_objects_to_trace = stm_list_append
- (_STM_TL2->old_objects_to_trace, moved);
+ LIST_APPEND(_STM_TL2->old_objects_to_trace, moved);
}
void minor_collect()
@@ -700,6 +719,7 @@
_STM_TL2->uncommitted_pages = stm_list_create();
_STM_TL2->modified_objects = stm_list_create();
+ _STM_TL2->uncommitted_objects = stm_list_create();
assert(!_STM_TL2->running_transaction);
}
@@ -716,6 +736,10 @@
stm_list_free(_STM_TL2->modified_objects);
_STM_TL2->modified_objects = NULL;
+ assert(stm_list_is_empty(_STM_TL2->uncommitted_objects));
+ stm_list_free(_STM_TL2->uncommitted_objects);
+ _STM_TL2->uncommitted_objects = NULL;
+
assert(_STM_TL1->shadow_stack == _STM_TL1->shadow_stack_base);
free(_STM_TL1->shadow_stack);
@@ -831,6 +855,10 @@
push_modified_to_other_threads();
stm_list_clear(_STM_TL2->modified_objects);
+ /* uncommitted objects / partially COMMITTED pages */
+ push_uncommitted_to_other_threads();
+ stm_list_clear(_STM_TL2->uncommitted_objects);
+
/* uncommitted_pages */
long j;
for (j = 2; j < LARGE_OBJECT_WORDS; j++) {
@@ -841,12 +869,8 @@
continue;
uintptr_t pagenum = ((uintptr_t)(alloc->next - 1)) / 4096UL;
if (flag_page_private[pagenum] == UNCOMMITTED_SHARED_PAGE) {
- /* mark it as empty so it doesn't get used in the next
- transaction */
- /* XXX: flag_partial_page!! */
- alloc->start = 0;
- alloc->next = 0;
- alloc->stop = 0;
+ /* becomes a SHARED (s.b.) partially used page */
+ alloc->flag_partial_page = 1;
}
}
@@ -858,12 +882,14 @@
}));
stm_list_clear(_STM_TL2->uncommitted_pages);
+
- /* /\* walk the new_object_ranges and manually copy the new objects */
+
+ /* /\* walk the uncommitted_object_ranges and manually copy the new objects */
/* to the other thread's pages in the (hopefully rare) case that */
/* the page they belong to is already unshared *\/ */
/* long i; */
- /* struct stm_list_s *lst = _STM_TL2->new_object_ranges; */
+ /* struct stm_list_s *lst = _STM_TL2->uncommitted_object_ranges; */
/* for (i = stm_list_count(lst); i > 0; ) { */
/* i -= 2; */
/* uintptr_t pagenum = (uintptr_t)stm_list_item(lst, i); */
@@ -1001,7 +1027,7 @@
/* uint16_t num_allocated = ((uintptr_t)alloc->next) - alloc->start; */
/* alloc->next -= num_allocated; */
/* } */
- /* stm_list_clear(_STM_TL2->new_object_ranges); */
+ /* stm_list_clear(_STM_TL2->uncommitted_object_ranges); */
assert(_STM_TL1->jmpbufptr != NULL);
diff --git a/c7/list.h b/c7/list.h
--- a/c7/list.h
+++ b/c7/list.h
@@ -33,6 +33,10 @@
return lst;
}
+#define LIST_APPEND(lst, e) { \
+ lst = stm_list_append(lst, e); \
+ }
+
static inline void stm_list_clear(struct stm_list_s *lst)
{
lst->count = 0;
diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py
--- a/c7/test/test_basic.py
+++ b/c7/test/test_basic.py
@@ -418,6 +418,11 @@
assert stm_get_flags(newer) & lib.GCFLAG_NOT_COMMITTED
stm_write(newer) # does not privatize
assert stm_get_page_flag(stm_get_obj_pages(newer)[0]) == lib.SHARED_PAGE
+ stm_stop_transaction()
+
+ assert stm_get_page_flag(stm_get_obj_pages(newer)[0]) == lib.SHARED_PAGE
+ assert not (stm_get_flags(newer) & lib.GCFLAG_NOT_COMMITTED)
+
# def test_resolve_write_write_no_conflict(self):
More information about the pypy-commit
mailing list