Author: Remi Meier Branch: c7 Changeset: r689:4d91804e80ed Date: 2014-01-29 15:07 +0100 http://bitbucket.org/pypy/stmgc/changeset/4d91804e80ed/
Log: try to implement more general safe-points. not sure if successful diff --git a/c7/core.c b/c7/core.c --- a/c7/core.c +++ b/c7/core.c @@ -138,10 +138,10 @@ if (_STM_TL->active == 2) { /* we must succeed! */ _stm_dbg_get_tl(prev_owner - 1)->need_abort = 1; - _stm_start_no_collect_safe_point(); - /* XXX: not good */ + _stm_start_safe_point(0); + /* XXX: not good, maybe should be signalled by other thread */ usleep(1); - _stm_stop_no_collect_safe_point(); + _stm_stop_safe_point(0); goto retry; } /* XXXXXX */ @@ -353,27 +353,21 @@ uint8_t our_lock = _STM_TL->thread_num + 1; do { - _stm_start_safe_point(); - - stm_start_exclusive_lock(); - if (_STM_TL->need_abort) { - stm_stop_exclusive_lock(); - stm_start_shared_lock(); - stm_abort_transaction(); - } + _stm_start_safe_point(LOCK_COLLECT); + _stm_stop_safe_point(LOCK_COLLECT|LOCK_EXCLUSIVE); if (!inevitable_lock) break; - stm_stop_exclusive_lock(); - _stm_stop_safe_point(); + _stm_start_safe_point(LOCK_EXCLUSIVE|LOCK_COLLECT); + _stm_stop_safe_point(LOCK_COLLECT); } while (1); inevitable_lock = our_lock; _STM_TL->active = 2; - stm_stop_exclusive_lock(); - _stm_stop_safe_point(); + _stm_start_safe_point(LOCK_EXCLUSIVE|LOCK_COLLECT); + _stm_stop_safe_point(LOCK_COLLECT); } void stm_start_inevitable_transaction() @@ -385,8 +379,8 @@ void stm_start_transaction(jmpbufptr_t *jmpbufptr) { assert(!_STM_TL->active); - - stm_start_shared_lock(); + + _stm_stop_safe_point(LOCK_COLLECT); uint8_t old_rv = _STM_TL->transaction_read_version; _STM_TL->transaction_read_version = old_rv + 1; @@ -415,28 +409,23 @@ /* Some operations require us to have the EXCLUSIVE lock */ if (_STM_TL->active == 1) { while (1) { - _stm_start_safe_point(); + _stm_start_safe_point(LOCK_COLLECT); usleep(1); /* XXX: better algorithm that allows for waiting on a mutex */ - stm_start_exclusive_lock(); - if (_STM_TL->need_abort) { - stm_stop_exclusive_lock(); - stm_start_shared_lock(); - stm_abort_transaction(); - } + _stm_stop_safe_point(LOCK_COLLECT|LOCK_EXCLUSIVE); if (!inevitable_lock) break; - stm_stop_exclusive_lock(); - _stm_stop_safe_point(); + + _stm_start_safe_point(LOCK_COLLECT|LOCK_EXCLUSIVE); + _stm_stop_safe_point(LOCK_COLLECT); } /* we have the exclusive lock */ } else { /* inevitable! no other transaction could have committed or aborted us */ - stm_stop_shared_lock(); - stm_start_exclusive_lock(); - assert(!_STM_TL->need_abort); + _stm_start_safe_point(LOCK_COLLECT); + _stm_stop_safe_point(LOCK_EXCLUSIVE|LOCK_COLLECT); inevitable_lock = 0; } @@ -451,7 +440,7 @@ _STM_TL->active = 0; - stm_stop_exclusive_lock(); + _stm_start_safe_point(LOCK_EXCLUSIVE|LOCK_COLLECT); fprintf(stderr, "%c", 'C'+_STM_TL->thread_num*32); } @@ -504,13 +493,15 @@ assert(_STM_TL->jmpbufptr != NULL); assert(_STM_TL->jmpbufptr != (jmpbufptr_t *)-1); /* for tests only */ _STM_TL->active = 0; - stm_stop_shared_lock(); + /* _STM_TL->need_abort = 0; */ + + _stm_start_safe_point(LOCK_COLLECT); + fprintf(stderr, "%c", 'A'+_STM_TL->thread_num*32); /* reset all the modified objects (incl. re-adding GCFLAG_WRITE_BARRIER) */ reset_modified_from_other_threads(); stm_list_clear(_STM_TL->modified_objects); - __builtin_longjmp(*_STM_TL->jmpbufptr, 1); } diff --git a/c7/nursery.c b/c7/nursery.c --- a/c7/nursery.c +++ b/c7/nursery.c @@ -176,9 +176,14 @@ localchar_t *collect_and_reserve(size_t size) { - _stm_start_safe_point(); + _stm_start_safe_point(0); /* don't release the COLLECT lock, + that needs to be done afterwards if + we want a major collection */ minor_collect(); - _stm_stop_safe_point(); + _stm_stop_safe_point(0); + + /* XXX: if we_want_major_collect: acquire EXCLUSIVE & COLLECT lock + and do it */ localchar_t *current = _STM_TL->nursery_current; _STM_TL->nursery_current = current + size; @@ -188,8 +193,10 @@ object_t *stm_allocate(size_t size) { - _stm_start_safe_point(); - _stm_stop_safe_point(); + _stm_start_safe_point(LOCK_COLLECT); + /* all collections may happen here */ + _stm_stop_safe_point(LOCK_COLLECT); + assert(_STM_TL->active); assert(size % 8 == 0); assert(16 <= size && size < NB_NURSERY_PAGES * 4096);//XXX diff --git a/c7/stmsync.c b/c7/stmsync.c --- a/c7/stmsync.c +++ b/c7/stmsync.c @@ -1,8 +1,11 @@ +#include <assert.h> +#include <string.h> +#include <unistd.h> + + #include "stmsync.h" #include "core.h" #include "reader_writer_lock.h" -#include <assert.h> -#include <string.h> /* a multi-reader, single-writer lock: transactions normally take a reader @@ -10,6 +13,8 @@ we take a writer lock to "stop the world". */ rwticket rw_shared_lock; /* the "GIL" */ +rwticket rw_collection_lock; /* for major collections */ + void _stm_reset_shared_lock() { @@ -17,16 +22,45 @@ assert(!rwticket_wrunlock(&rw_shared_lock)); memset(&rw_shared_lock, 0, sizeof(rwticket)); + + assert(!rwticket_wrtrylock(&rw_collection_lock)); + assert(!rwticket_wrunlock(&rw_collection_lock)); + + memset(&rw_collection_lock, 0, sizeof(rwticket)); +} + +void stm_acquire_collection_lock() +{ + /* we must have the exclusive lock here and + not the colletion lock!! */ + while (1) { + if (!rwticket_wrtrylock(&rw_collection_lock)) + break; /* acquired! */ + + stm_stop_exclusive_lock(); + usleep(1); + stm_start_exclusive_lock(); + if (_STM_TL->need_abort) { + stm_stop_exclusive_lock(); + stm_start_shared_lock(); + stm_abort_transaction(); + } + } } void stm_start_shared_lock(void) { - rwticket_rdlock(&rw_shared_lock); + rwticket_rdlock(&rw_shared_lock); } -void stm_stop_shared_lock(void) +void stm_stop_shared_lock() { - rwticket_rdunlock(&rw_shared_lock); + rwticket_rdunlock(&rw_shared_lock); +} + +void stm_start_exclusive_lock(void) +{ + rwticket_wrlock(&rw_shared_lock); } void stm_stop_exclusive_lock(void) @@ -34,20 +68,52 @@ rwticket_wrunlock(&rw_shared_lock); } -void stm_start_exclusive_lock(void) +/* _stm_start_safe_point(LOCK_EXCLUSIVE|LOCK_COLLECT) + -> release the exclusive lock and also the collect-read-lock */ +void _stm_start_safe_point(uint8_t flags) { - rwticket_wrlock(&rw_shared_lock); + if (flags & LOCK_EXCLUSIVE) + stm_stop_exclusive_lock(); + else + stm_stop_shared_lock(); + + if (flags & LOCK_COLLECT) + rwticket_rdunlock(&rw_collection_lock); } -void _stm_start_safe_point(void) +/* + _stm_stop_safe_point(LOCK_COLLECT|LOCK_EXCLUSIVE); + -> reacquire the collect-read-lock and the exclusive lock + */ +void _stm_stop_safe_point(uint8_t flags) { - assert(!_STM_TL->need_abort); - stm_stop_shared_lock(); + if (flags & LOCK_EXCLUSIVE) + stm_start_exclusive_lock(); + else + stm_start_shared_lock(); + + if (!(flags & LOCK_COLLECT)) { /* if we released the collection lock */ + /* acquire read-collection. always succeeds because + if there was a write-collection holder we would + also not have gotten the shared_lock */ + rwticket_rdlock(&rw_collection_lock); + } + + if (_STM_TL->active && _STM_TL->need_abort) { + if (flags & LOCK_EXCLUSIVE) { + /* restore to shared-mode with the collection lock */ + stm_stop_exclusive_lock(); + stm_start_shared_lock(); + if (flags & LOCK_COLLECT) + rwticket_rdlock(&rw_collection_lock); + stm_abort_transaction(); + } else { + if (flags & LOCK_COLLECT) + rwticket_rdlock(&rw_collection_lock); + stm_abort_transaction(); + } + } } -void _stm_stop_safe_point(void) -{ - stm_start_shared_lock(); - if (_STM_TL->need_abort) - stm_abort_transaction(); -} + + diff --git a/c7/stmsync.h b/c7/stmsync.h --- a/c7/stmsync.h +++ b/c7/stmsync.h @@ -1,14 +1,16 @@ +#include <stdint.h> void stm_start_shared_lock(void); void stm_stop_shared_lock(void); void stm_stop_exclusive_lock(void); void stm_start_exclusive_lock(void); -void _stm_start_safe_point(void); -void _stm_stop_safe_point(void); +void _stm_start_safe_point(uint8_t flags); +void _stm_stop_safe_point(uint8_t flags); void _stm_reset_shared_lock(void); -/* XXX: major collections must not be possible here: */ -#define _stm_start_no_collect_safe_point(void) _stm_start_safe_point() -#define _stm_stop_no_collect_safe_point(void) _stm_stop_safe_point() +enum { + LOCK_COLLECT = (1 << 0), + LOCK_EXCLUSIVE = (1 << 1), +}; diff --git a/c7/test/support.py b/c7/test/support.py --- a/c7/test/support.py +++ b/c7/test/support.py @@ -58,8 +58,8 @@ bool _stm_is_young(object_t *o); object_t *_stm_allocate_old(size_t size); -void _stm_start_safe_point(void); -void _stm_stop_safe_point(void); +void _stm_start_safe_point(uint8_t); +void _stm_stop_safe_point(uint8_t); bool _stm_check_stop_safe_point(void); void _set_type_id(object_t *obj, uint32_t h); @@ -91,7 +91,12 @@ enum { GCFLAG_WRITE_BARRIER = 1, GCFLAG_NOT_COMMITTED = 2, - GCFLAG_MOVED = 4 + GCFLAG_MOVED = 4, +}; + +enum { + LOCK_COLLECT = 1, + LOCK_EXCLUSIVE = 2, }; @@ -185,7 +190,7 @@ if (__builtin_setjmp(here) == 0) { // returned directly assert(_STM_TL->jmpbufptr == (jmpbufptr_t*)-1); _STM_TL->jmpbufptr = &here; - _stm_stop_safe_point(); + _stm_stop_safe_point(LOCK_COLLECT); _STM_TL->jmpbufptr = (jmpbufptr_t*)-1; return 0; } @@ -360,7 +365,7 @@ def stm_start_safe_point(): - lib._stm_start_safe_point() + lib._stm_start_safe_point(lib.LOCK_COLLECT) def stm_stop_safe_point(): if lib._stm_check_stop_safe_point(): diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py --- a/c7/test/test_basic.py +++ b/c7/test/test_basic.py @@ -314,7 +314,7 @@ def test_many_allocs(self): # assumes NB_NURSERY_PAGES 1024 obj_size = 1024 - num = 5000 # more than what fits in the nursery (4MB) + num = 9000 # more than what fits in the nursery (4MB) stm_start_transaction() for i in range(num): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit