Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r92:b30306fc8a86 Date: 2013-06-11 16:28 +0200 http://bitbucket.org/pypy/stmgc/changeset/b30306fc8a86/
Log: in-progress diff --git a/c4/et.c b/c4/et.c --- a/c4/et.c +++ b/c4/et.c @@ -35,6 +35,10 @@ return (P->h_revision == stm_private_rev_num) || (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED); } +int _stm_is_private(gcptr P) +{ + return is_private(P); +} /************************************************************/ @@ -208,82 +212,89 @@ } } -#if 0 -static gcptr _latest_gcptr(gcptr R) +gcptr _stm_nonrecord_barrier(gcptr G) { - /* don't use, for tests only */ + /* follows the logic in stm_DirectReadBarrier() */ + struct tx_descriptor *d = thread_descriptor; + gcptr P = G; revision_t v; - retry: - v = R->h_revision; - if (!(v & 1)) // "is a pointer", i.e. - { // "has a more recent revision" - if (v & 2) + + if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) + { + private_from_protected: + if (!(((gcptr)P->h_revision)->h_revision & 1)) { - v &= ~2; - if (!stmgc_is_young_in(thread_descriptor, (gcptr)v)) - return NULL; /* can't access */ + fprintf(stderr, "_stm_nonrecord_barrier: %p -> NULL " + "private_from_protected but protected changed\n", G); + return NULL; } - R = (gcptr)v; - goto retry; - } - return R; -} - -gcptr _stm_nonrecord_barrier(gcptr obj, int *result) -{ - /* warning, this is for tests only, and it is not thread-safe! */ - struct tx_descriptor *d = thread_descriptor; - if (gcptrlist_size(&d->stolen_objects) > 0) - stmgc_normalize_stolen_objects(); - - enum protection_class_t e = stmgc_classify(obj); - if (e == K_PRIVATE) - { - *result = 2; /* 'obj' a private object to start with */ - return obj; - } - obj = _latest_gcptr(obj); - if (obj == NULL) - { - assert(e == K_PUBLIC); - *result = 3; /* can't check anything: we'd need foreign access */ - return NULL; - } - if (stmgc_classify(obj) == K_PRIVATE) - { - *result = 1; - return obj; + goto add_in_recent_reads_cache; } - wlog_t *item; - G2L_LOOP_FORWARD(d->public_to_private, item) + if (P->h_tid & GCFLAG_PUBLIC) { - gcptr R = item->addr; - gcptr L = item->val; - if (_latest_gcptr(R) == obj) + while (v = ACCESS_ONCE(P->h_revision), !(v & 1)) { - /* 'obj' has a private version. The way we detect this lets us - find it even if we already have a committed version that - will cause conflict. */ - *result = 1; - return L; + if (v & 2) + goto follow_stub; + + P = (gcptr)v; + assert(P->h_tid & GCFLAG_PUBLIC); } - } G2L_LOOP_END; - if (obj->h_revision > d->start_time) - { - /* 'obj' has no private version, and the public version was modified */ - *result = -1; - return NULL; + if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE) + { + wlog_t *item; + G2L_FIND(d->public_to_private, P, item, goto no_private_obj); + + P = item->val; + found_in_stolen_objects: + assert(!(P->h_tid & GCFLAG_PUBLIC)); + assert(is_private(P)); + fprintf(stderr, "_stm_nonrecord_barrier: %p -> %p " + "public_to_private\n", G, P); + return P; + + no_private_obj:; + gcptr L = _stm_find_stolen_objects(d, P); + if (L != NULL) + { + P = L; + goto found_in_stolen_objects; + } + } + + if (UNLIKELY(v > d->start_time)) + { + fprintf(stderr, "_stm_nonrecord_barrier: %p -> NULL changed\n", G); + return NULL; // object too recent + } + fprintf(stderr, "_stm_nonrecord_barrier: %p -> %p public\n", G, P); } else { - /* 'obj' has only an up-to-date public version */ - *result = 0; - return obj; + fprintf(stderr, "_stm_nonrecord_barrier: %p -> %p protected\n", G, P); + } + + register_in_list_of_read_objects: + add_in_recent_reads_cache: + return P; + + follow_stub:; + P = (gcptr)(v - 2); + assert(!(P->h_tid & GCFLAG_PUBLIC)); + if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) + { + fprintf(stderr, "_stm_nonrecord_barrier: %p -> %p handle " + "private_from_protected\n", G, P); + goto private_from_protected; + } + else + { + fprintf(stderr, "read_barrier: %p -> %p handle\n", G, P); + goto register_in_list_of_read_objects; } } -#endif #if 0 void *stm_DirectReadBarrierFromR(void *G1, void *R_Container1, size_t offset) diff --git a/c4/et.h b/c4/et.h --- a/c4/et.h +++ b/c4/et.h @@ -164,7 +164,9 @@ gcptr stm_DirectReadBarrier(gcptr); gcptr stm_RepeatReadBarrier(gcptr); gcptr stm_WriteBarrier(gcptr); -gcptr _stm_nonrecord_barrier(gcptr, int *); +gcptr _stm_nonrecord_barrier(gcptr); /* debugging: read barrier, but + not recording anything */ +int _stm_is_private(gcptr); /* debugging */ gcptr stm_get_private_from_protected(long); /* debugging */ gcptr stm_get_read_obj(long); /* debugging */ gcptr stmgc_duplicate(gcptr); diff --git a/c4/steal.c b/c4/steal.c --- a/c4/steal.c +++ b/c4/steal.c @@ -96,3 +96,20 @@ } gcptrlist_clear(&d->public_descriptor->stolen_objects); } + +gcptr _stm_find_stolen_objects(struct tx_descriptor *d, gcptr obj) +{ + /* read-only, for debugging */ + long i, size = d->public_descriptor->stolen_objects.size; + gcptr *items = d->public_descriptor->stolen_objects.items; + + for (i = 0; i < size; i += 2) { + gcptr B = items[i]; + gcptr L = items[i + 1]; + + assert(L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED); + if (B == obj) + return L; + } + return NULL; +} diff --git a/c4/steal.h b/c4/steal.h --- a/c4/steal.h +++ b/c4/steal.h @@ -11,6 +11,7 @@ void stm_steal_stub(gcptr); gcptr stm_get_stolen_obj(long index); /* debugging */ void stm_normalize_stolen_objects(struct tx_descriptor *); +gcptr _stm_find_stolen_objects(struct tx_descriptor *, gcptr); #endif diff --git a/c3/test/model.py b/c4/test/model.py copy from c3/test/model.py copy to c4/test/model.py diff --git a/c4/test/support.py b/c4/test/support.py --- a/c4/test/support.py +++ b/c4/test/support.py @@ -63,7 +63,8 @@ //void stmgcpage_add_prebuilt_root(gcptr); void stm_clear_between_tests(void); //void stmgc_minor_collect(void); - //gcptr _stm_nonrecord_barrier(gcptr, int *); + gcptr _stm_nonrecord_barrier(gcptr); + int _stm_is_private(gcptr); int stm_dbgmem_is_active(void *p, int allow_outside); void stm_start_sharedlock(void); void stm_stop_sharedlock(void); @@ -436,7 +437,7 @@ def nalloc_refs(nrefs): "Allocate a fresh object from the nursery, with nrefs pointers" p = lib.stm_allocate(HDR + WORD * nrefs, 421 + nrefs) - assert p.h_revision == lib.get_local_revision() + assert p.h_revision == lib.get_private_rev_num() for i in range(nrefs): assert rawgetptr(p, i) == ffi.NULL # must already be zero-filled return p diff --git a/c3/test/test_random.py b/c4/test/test_random.py copy from c3/test/test_random.py copy to c4/test/test_random.py --- a/c3/test/test_random.py +++ b/c4/test/test_random.py @@ -191,12 +191,10 @@ return newextra def nonrecord_barrier(self, ptr): - result = ffi.new("int *") - ptr = lib._stm_nonrecord_barrier(ptr, result) - return ptr, result[0] + return lib._stm_nonrecord_barrier(ptr) def is_private(self, ptr): - return ptr.h_revision == lib.get_local_revision() + return lib._stm_is_private(ptr) def check_valid(self, lst): lst = list(lst) @@ -207,23 +205,18 @@ continue self.check(p) - ptr, result = self.nonrecord_barrier(p.ptr) - if ptr == ffi.NULL and result == 3: - continue # can't check anything: we'd need foreign access + ptr = self.nonrecord_barrier(p.ptr) has_private_copy = p.obj in self.current_rev.content - assert has_private_copy == (result >= 1) if has_private_copy: + assert ptr != ffi.NULL and self.is_private(ptr) content = self.current_rev.content[p.obj] else: try: content = self.current_rev._try_read(p.obj) - is_too_recent = False except model.Deleted: - is_too_recent = True - if result < 0: - assert is_too_recent - if is_too_recent: - continue # can't really check more in this case + assert ptr == ffi.NULL + continue + assert ptr != ffi.NULL and not self.is_private(ptr) self.check_not_free(ptr) assert lib.rawgetptr(ptr, 2) == p.obj.identity _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit