Author: Armin Rigo <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit