Author: Armin Rigo <[email protected]>
Branch:
Changeset: r135:450808530645
Date: 2013-06-15 18:52 +0200
http://bitbucket.org/pypy/stmgc/changeset/450808530645/
Log: Tweaks tweaks.
diff --git a/c4/doc-objects.txt b/c4/doc-objects.txt
--- a/c4/doc-objects.txt
+++ b/c4/doc-objects.txt
@@ -270,3 +270,26 @@
- public copies: must be changed carefully: `h_tid` is only modified to
add GCFLAG_PUBLIC_TO_PRIVATE; and `h_revision` changes are done with
bool_cas() in a thread-controlled way.
+
+
+
+Nursery and minor collections
+-----------------------------
+
+Every thread has its own nursery. When it's full, the thread does a
+minor collection and proceed.
+
+Most object copies are allocated "young", i.e. from the nursery of its
+thread, with the following exceptions.
+
+Any public object (GCFLAG_PUBLIC) must be old. This is a consequence of
+the fact that public objects may be accessed concurrently by any thead,
+but young objects are moved during a minor collection. The rule admits
+one exception: a young object may be turned GCFLAG_PUBLIC during its
+existence (together with GCFLAG_NURSERY_MOVED) in order to get the
+behavior of public objects, but only if we know that no other thread
+will access it anyway.
+
+The backup copy of a GCFLAG_PRIVATE_FROM_PROTECTED copy is allocated
+old, and explicitly freed when the thread commits (unless it was
+stolen).
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -1007,12 +1007,20 @@
assert(IS_POINTER(P->h_revision));
gcptr B = (gcptr)P->h_revision;
+ assert(B->h_tid & GCFLAG_OLD);
+
if (B->h_tid & GCFLAG_PUBLIC)
{
assert(!(B->h_tid & GCFLAG_BACKUP_COPY));
P->h_tid &= ~GCFLAG_PRIVATE_FROM_PROTECTED;
P->h_tid |= GCFLAG_PUBLIC;
- /* P becomes a public (possibly young) outdated object */
+ if (!(P->h_tid & GCFLAG_OLD)) P->h_tid |= GCFLAG_NURSERY_MOVED;
+ /* P becomes a public outdated object. It may create an
+ exception documented in doc-objects.txt: a public but young
+ object. It's still fine because it should only be seen by
+ other threads during stealing, and as it's outdated,
+ stealing will follow its h_revision (to B).
+ */
}
else
{
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -81,10 +81,7 @@
assert(!(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
assert(!(obj->h_tid & GCFLAG_OLD));
- size_t size = stmcb_size(obj);
- gcptr fresh_old_copy = stm_malloc(size);
- memcpy(fresh_old_copy, obj, size);
- fresh_old_copy->h_tid |= GCFLAG_OLD;
+ gcptr fresh_old_copy = stmgc_duplicate_old(obj);
fprintf(stderr, "minor: %p is copied to %p\n", obj, fresh_old_copy);
return fresh_old_copy;
diff --git a/c4/steal.c b/c4/steal.c
--- a/c4/steal.c
+++ b/c4/steal.c
@@ -104,8 +104,9 @@
/* B is now a backup copy, i.e. a protected object, and we own
the foreign thread's collection_lock, so we can read/write the
- flags
+ flags. B is old, like all backup copies.
*/
+ assert(B->h_tid & GCFLAG_OLD);
B->h_tid &= ~GCFLAG_BACKUP_COPY;
if (B->h_tid & GCFLAG_PUBLIC_TO_PRIVATE) {
@@ -129,11 +130,27 @@
if (L->h_tid & GCFLAG_PUBLIC) {
/* already stolen */
fprintf(stderr, "already stolen: %p -> %p\n", P, L);
+
+ /* note that we should follow h_revision at least one more
+ step: it is necessary if L is public but young (and then
+ has GCFLAG_NURSERY_MOVED), but it is fine to do it more
+ generally. */
+ v = ACCESS_ONCE(L->h_revision);
+ if (IS_POINTER(v))
+ L = (gcptr)v;
goto already_stolen;
}
else {
fprintf(stderr, "stolen: %p -> %p\n", P, L);
}
+
+ /* Copy the object out of the other thread's nursery, if needed */
+ if (!(L->h_tid & GCFLAG_OLD)) {
+ gcptr O = stmgc_duplicate_old(L);
+ L->h_revision = (revision_t)O;
+ L->h_tid |= GCFLAG_PUBLIC | GCFLAG_NURSERY_MOVED;
+ L = O;
+ }
}
/* Here L is a protected (or backup) copy, and we own the foreign
@@ -157,17 +174,6 @@
odd number that is also valid on a public up-to-date object.
*/
- /* Move the object out of the other thread's nursery, if needed */
- if (!(L->h_tid & GCFLAG_OLD)) {
- size_t size = stmcb_size(L);
- gcptr O = stm_malloc(size);
- memcpy(O, L, size);
- L->h_revision = (revision_t)O;
- L->h_tid |= GCFLAG_NURSERY_MOVED;
- O->h_tid |= GCFLAG_OLD;
- L = O;
- }
-
/* Fix the content of the object: we need to change all pointers
that reference protected copies into pointers that reference
stub copies.
@@ -188,6 +194,8 @@
smp_wmb();
already_stolen:
+ assert(L->h_tid & GCFLAG_OLD);
+
/* update the original P->h_revision to point directly to L */
P->h_revision = (revision_t)L;
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit