Author: Armin Rigo <[email protected]>
Branch:
Changeset: r65:7526350df472
Date: 2013-06-05 15:57 +0200
http://bitbucket.org/pypy/stmgc/changeset/7526350df472/
Log: in-progress
diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -286,27 +286,33 @@
#endif
}
-static gcptr LocalizeProtected(struct tx_descriptor *d, gcptr R)
+static gcptr LocalizeProtected(struct tx_descriptor *d, gcptr P)
{
- assert(!(R->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
+ gcptr B;
- /* duplicate, and save the original R->h_revision into an extra
- word allocated just after L */
- assert(R->h_revision & 1);
- gcptr L = stmgc_duplicate(R, R->h_revision);
+ assert(P->h_revision != stm_private_rev_num);
+ assert(!(P->h_tid & GCFLAG_PUBLIC));
+ assert(!(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
+ assert(!(P->h_tid & GCFLAG_BACKUP_COPY));
+ assert(!(P->h_tid & GCFLAG_STUB));
- /* cross-thread memory barrier: make sure the local object is correct
- and has h_revision == stm_local_revision, and the extra word is
- written as well; when it is done, and only then, then we change
- R->h_revision */
- smp_wmb();
-
- R->h_revision = (revision_t)L;
-
- gcptrlist_insert(&d->protected_with_private_copy, R);
- AddInReadSet(d, R);
- /*mark*/
- return L;
+ if (P->h_revision & 1)
+ {
+ /* does not have a backup yet */
+ B = stmgc_duplicate(P, 0);
+ B->h_tid |= GCFLAG_BACKUP_COPY;
+ }
+ else
+ {
+ size_t size = stmcb_size(P);
+ B = (gcptr)P->h_revision;
+ assert(B->h_tid & GCFLAG_BACKUP_COPY);
+ memcpy(B + 1, P + 1, size - sizeof(*B));
+ }
+ assert(B->h_tid & GCFLAG_BACKUP_COPY);
+ g2l_insert(&d->private_to_backup, P, B);
+ P->h_revision = stm_private_rev_num;
+ return P;
}
static gcptr LocalizePublic(struct tx_descriptor *d, gcptr R)
@@ -338,35 +344,25 @@
gcptr stm_WriteBarrier(gcptr P)
{
- gcptr R, W;
+ gcptr W;
struct tx_descriptor *d = thread_descriptor;
assert(d->active >= 1);
- /* must normalize the situation now, otherwise we risk that
- LocalizePublic creates a new private version of a public
- object that has got one, attached to the equivalent stolen
- protected object */
- if (gcptrlist_size(&d->stolen_objects) > 0)
- stmgc_normalize_stolen_objects();
-
- /* XXX optimize me based on common patterns */
- R = HeadOfRevisionChainList(d, P);
-
- switch (stmgc_classify(R)) {
- case K_PRIVATE: W = R; break;
- case K_PROTECTED: W = LocalizeProtected(d, R); break;
- case K_PUBLIC: W = LocalizePublic(d, R); break;
- default: abort();
- }
-
- if (W->h_tid & GCFLAG_WRITE_BARRIER)
- stmgc_write_barrier(W);
+ W = LocalizeProtected(d, P);
fprintf(stderr, "write_barrier: %p -> %p\n", P, W);
return W;
}
+gcptr stm_get_backup_copy(gcptr P)
+{
+ struct tx_descriptor *d = thread_descriptor;
+ wlog_t *entry;
+ G2L_FIND(d->private_to_backup, P, entry, return NULL);
+ return entry->val;
+}
+
/************************************************************/
static revision_t GetGlobalCurTime(struct tx_descriptor *d)
@@ -527,6 +523,7 @@
}
gcptrlist_clear(&d->list_of_read_objects);
+ g2l_clear(&d->private_to_backup);
stmgc_abort_transaction(d);
fprintf(stderr,
@@ -590,6 +587,7 @@
d->start_real_time.tv_nsec = -1;
}
assert(d->list_of_read_objects.size == 0);
+ assert(!g2l_any_entry(&d->private_to_backup));
stmgc_start_transaction(d);
d->count_reads = 1;
@@ -775,6 +773,23 @@
}
}
+void TurnPrivateWithBackupToProtected(struct tx_descriptor *d,
+ revision_t cur_time)
+{
+ wlog_t *item;
+ G2L_LOOP_FORWARD(d->private_to_backup, item)
+ {
+ gcptr P = item->addr;
+ gcptr B = item->val;
+ assert(P->h_revision == stm_private_rev_num);
+ assert(B->h_tid & GCFLAG_BACKUP_COPY);
+ B->h_revision = cur_time;
+ P->h_revision = (revision_t)B;
+
+ } G2L_LOOP_END;
+ g2l_clear(&d->private_to_backup);
+}
+
void CommitTransaction(void)
{ /* must save roots around this call */
revision_t cur_time;
@@ -828,6 +843,8 @@
"*************************************\n",
(long)cur_time);
+ TurnPrivateWithBackupToProtected(d, cur_time);
+
revision_t localrev = stm_private_rev_num;
UpdateProtectedChainHeads(d, cur_time, localrev);
smp_wmb();
@@ -1057,6 +1074,7 @@
thread_descriptor = NULL;
+ g2l_delete(&d->private_to_backup);
gcptrlist_delete(&d->list_of_read_objects);
gcptrlist_delete(&d->abortinfo);
free(d->longest_abort_info);
diff --git a/c3/et.h b/c3/et.h
--- a/c3/et.h
+++ b/c3/et.h
@@ -116,6 +116,7 @@
unsigned int num_spinloops[SPINLOOP_REASONS];
struct GcPtrList list_of_read_objects;
struct GcPtrList abortinfo;
+ struct G2L private_to_backup;
char *longest_abort_info;
long long longest_abort_info_time;
struct FXCache recent_reads_cache;
@@ -175,6 +176,7 @@
gcptr stm_RepeatReadBarrier(gcptr);
gcptr stm_WriteBarrier(gcptr);
gcptr _stm_nonrecord_barrier(gcptr, int *);
+gcptr stm_get_backup_copy(gcptr);
int DescriptorInit(void);
void DescriptorDone(void);
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -180,12 +180,14 @@
memcpy(localobj, globalobj, size);
assert(!(localobj->h_tid & GCFLAG_NURSERY_MOVED));
+#if 0
localobj->h_tid &= ~(GCFLAG_VISITED |
GCFLAG_PUBLIC_TO_PRIVATE |
GCFLAG_PREBUILT_ORIGINAL |
GCFLAG_WRITE_BARRIER |
GCFLAG_OLD);
localobj->h_revision = stm_private_rev_num;
+#endif
return localobj;
}
diff --git a/c3/test/support.py b/c3/test/support.py
--- a/c3/test/support.py
+++ b/c3/test/support.py
@@ -68,6 +68,7 @@
void stm_start_sharedlock(void);
void stm_stop_sharedlock(void);
void AbortTransaction(int);
+ gcptr stm_get_backup_copy(gcptr);
gcptr getptr(gcptr, long);
void setptr(gcptr, long, gcptr);
@@ -90,12 +91,15 @@
/* some constants normally private that are useful in the tests */
#define WORD ...
#define GC_PAGE_SIZE ...
+ #define GCFLAG_OLD ...
#define GCFLAG_VISITED ...
+ #define GCFLAG_PUBLIC ...
+ #define GCFLAG_PREBUILT_ORIGINAL ...
+ #define GCFLAG_BACKUP_COPY ...
#define GCFLAG_PUBLIC_TO_PRIVATE ...
- #define GCFLAG_PREBUILT_ORIGINAL ...
#define GCFLAG_WRITE_BARRIER ...
#define GCFLAG_NURSERY_MOVED ...
- #define GCFLAG_OLD ...
+ #define GCFLAG_STOLEN ...
#define GCFLAG_STUB ...
#define ABRT_MANUAL ...
typedef struct { ...; } page_header_t;
@@ -509,3 +513,17 @@
def abort_and_retry():
lib.AbortTransaction(lib.ABRT_MANUAL)
+
+def classify(p):
+ private = p.h_revision == lib.get_private_rev_num()
+ public = (p.h_tid & GCFLAG_PUBLIC) != 0
+ backup = (p.h_tid & GCFLAG_BACKUP_COPY) != 0
+ assert private + public + backup <= 1
+ if private:
+ return "private"
+ if public:
+ return "public"
+ if backup:
+ return "backup"
+ else:
+ return "protected"
diff --git a/c3/test/test_et.py b/c3/test/test_et.py
--- a/c3/test/test_et.py
+++ b/c3/test/test_et.py
@@ -7,6 +7,8 @@
lib.stm_initialize_tests(getattr(f, 'max_aborts', 0))
def teardown_function(_):
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
lib.stm_finalize()
@@ -16,12 +18,14 @@
assert r < 0 and r % 2 == 1
assert p.h_revision == r
assert p.h_tid == lib.gettid(p) | 0 # no GC flags
+ assert classify(p) == "private"
def test_write_barrier_private():
p = nalloc(HDR)
assert lib.stm_write_barrier(p) == p
assert p.h_revision == lib.get_private_rev_num()
assert p.h_tid == lib.gettid(p) | 0 # no GC flags
+ assert classify(p) == "private"
def test_protected_no_backup():
p = nalloc(HDR)
@@ -34,6 +38,7 @@
assert r != r2
assert p.h_revision == r
assert p.h_tid == lib.gettid(p) | 0 # no GC flags
+ assert classify(p) == "protected"
def test_private_with_backup():
p = nalloc(HDR)
@@ -41,9 +46,11 @@
lib.stm_begin_inevitable_transaction()
r2 = lib.get_private_rev_num()
assert p.h_revision != r2
+ assert classify(p) == "protected"
p2 = lib.stm_write_barrier(p)
assert p2 == p # does not move
assert p.h_revision == r2
+ assert classify(p) == "private"
def test_get_backup_copy():
p = nalloc(HDR + WORD)
@@ -59,6 +66,21 @@
assert pback.h_tid == p.h_tid | GCFLAG_BACKUP_COPY
assert lib.rawgetlong(pback, 0) == 78927812
assert lib.rawgetlong(p, 0) == 927122
+ assert classify(p) == "private"
+ assert classify(pback) == "backup"
def test_protected_with_backup():
- xxx
+ p = nalloc(HDR + WORD)
+ lib.setlong(p, 0, 78927812)
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
+ lib.setlong(p, 0, 927122)
+ pback = lib.stm_get_backup_copy(p)
+ assert pback != p
+ assert p.h_revision == lib.get_private_rev_num()
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
+ assert lib.stm_get_backup_copy(p) == ffi.NULL
+ assert classify(p) == "protected"
+ assert classify(pback) == "backup"
+ assert ffi.cast("revision_t *", p.h_revision) == pback
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit