Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit