Author: Armin Rigo <ar...@tunes.org> Branch: c7-refactor Changeset: r771:c07b26b32fb1 Date: 2014-02-19 06:43 +0100 http://bitbucket.org/pypy/stmgc/changeset/c07b26b32fb1/
Log: Adapt demo2.c. diff --git a/c7/Makefile b/c7/Makefile --- a/c7/Makefile +++ b/c7/Makefile @@ -14,16 +14,14 @@ rm -f $(BUILD_EXE) $(DEBUG_EXE) $(RELEASE_EXE) -H_FILES = core.h list.h pagecopy.h reader_writer_lock.h stmsync.h pages.h nursery.h largemalloc.h +H_FILES = stmgc.h stm/*.h +C_FILES = stmgc.c stm/*.c -C_FILES = core.c list.c pagecopy.c reader_writer_lock.c stmsync.c pages.c nursery.c largemalloc.c -DEBUG = -g - - -# note that we don't say -DNDEBUG, so that asserts should still be compiled in -# also, all debug code with extra checks but not the debugprints -build-%: %.c ${H_FILES} ${C_FILES} - clang -pthread -g -O1 $< -o build-$* -Wall ${C_FILES} -release-%: %.c ${H_FILES} ${C_FILES} - clang -pthread -g -DNDEBUG -O2 $< -o release-$* -Wall ${C_FILES} +# note that 'build' is optimized but still contains all asserts +debug-%: %.c ${H_FILES} ${C_FILES} + clang -pthread -g $< -o debug-$* -Wall -Werror stmgc.c +build-%: %.c ${H_FILES} ${C_FILES} + clang -pthread -g -O1 $< -o build-$* -Wall stmgc.c +release-%: %.c ${H_FILES} ${C_FILES} + clang -pthread -g -DNDEBUG -O2 $< -o release-$* -Wall stmgc.c diff --git a/c7/demo2.c b/c7/demo2.c --- a/c7/demo2.c +++ b/c7/demo2.c @@ -4,8 +4,7 @@ #include <pthread.h> #include <semaphore.h> -#include "core.h" -#include "stmsync.h" +#include "stmgc.h" #define LIST_LENGTH 6000 #define BUNCH 400 @@ -20,8 +19,13 @@ nodeptr_t next; }; +__thread stm_thread_local_t stm_thread_local; -size_t stmcb_size(struct object_s *ob) +#define PUSH_ROOT(p) (void)0 // XXX... +#define POP_ROOT(p) (void)0 // XXX... + + +ssize_t stmcb_size_rounded_up(struct object_s *ob) { return sizeof(struct node_s); } @@ -34,97 +38,88 @@ } -nodeptr_t global_chained_list = NULL; +nodeptr_t global_chained_list; -long check_sorted() +long check_sorted(void) { nodeptr_t r_n; long prev, sum; - jmpbufptr_t here; + stm_jmpbuf_t here; - back: - if (__builtin_setjmp(here) == 0) { - stm_start_transaction(&here); - - stm_read((objptr_t)global_chained_list); - r_n = global_chained_list; - assert(r_n->value == -1); - - prev = -1; - sum = 0; - while (r_n->next) { - r_n = r_n->next; - stm_read((objptr_t)r_n); - sum += r_n->value; + STM_START_TRANSACTION(&stm_thread_local, here); - _stm_start_safe_point(0); - _stm_stop_safe_point(0); - if (prev >= r_n->value) { - stm_stop_transaction(); - return -1; - } - - prev = r_n->value; + stm_read((objptr_t)global_chained_list); + r_n = global_chained_list; + assert(r_n->value == -1); + + prev = -1; + sum = 0; + while (r_n->next) { + r_n = r_n->next; + stm_read((objptr_t)r_n); + sum += r_n->value; + + stm_safe_point(); + if (prev >= r_n->value) { + stm_commit_transaction(); + return -1; } - stm_stop_transaction(); - return sum; + prev = r_n->value; } - goto back; + + stm_commit_transaction(); + return sum; } nodeptr_t swap_nodes(nodeptr_t initial) { - jmpbufptr_t here; + stm_jmpbuf_t here; assert(initial != NULL); - back: - if (__builtin_setjmp(here) == 0) { - stm_start_transaction(&here); - nodeptr_t prev = initial; - stm_read((objptr_t)prev); - - int i; - for (i=0; i<BUNCH; i++) { - nodeptr_t current = prev->next; - if (current == NULL) { - stm_stop_transaction(); - return NULL; - } - stm_read((objptr_t)current); - nodeptr_t next = current->next; - if (next == NULL) { - stm_stop_transaction(); - return NULL; - } - stm_read((objptr_t)next); - - if (next->value < current->value) { - stm_write((objptr_t)prev); - stm_write((objptr_t)current); - stm_write((objptr_t)next); - - prev->next = next; - current->next = next->next; - next->next = current; - _stm_start_safe_point(0); - _stm_stop_safe_point(0); - } - prev = current; + STM_START_TRANSACTION(&stm_thread_local, here); + + nodeptr_t prev = initial; + stm_read((objptr_t)prev); + + int i; + for (i=0; i<BUNCH; i++) { + nodeptr_t current = prev->next; + if (current == NULL) { + stm_commit_transaction(); + return NULL; } + stm_read((objptr_t)current); + nodeptr_t next = current->next; + if (next == NULL) { + stm_commit_transaction(); + return NULL; + } + stm_read((objptr_t)next); - stm_stop_transaction(); - return prev; + if (next->value < current->value) { + stm_write((objptr_t)prev); + stm_write((objptr_t)current); + stm_write((objptr_t)next); + + prev->next = next; + current->next = next->next; + next->next = current; + + stm_safe_point(); + } + prev = current; } - goto back; + + stm_commit_transaction(); + return prev; } - -void bubble_run() +void bubble_run(void) { nodeptr_t r_current; @@ -136,25 +131,25 @@ /* initialize list with values in decreasing order */ -void setup_list() +void setup_list(void) { int i; nodeptr_t w_newnode, w_prev; - stm_start_transaction(NULL); + stm_start_inevitable_transaction(&stm_thread_local); global_chained_list = (nodeptr_t)stm_allocate(sizeof(struct node_s)); global_chained_list->value = -1; global_chained_list->next = NULL; - - stm_push_root((objptr_t)global_chained_list); - + + PUSH_ROOT(global_chained_list); + w_prev = global_chained_list; for (i = 0; i < LIST_LENGTH; i++) { - stm_push_root((objptr_t)w_prev); + PUSH_ROOT(w_prev); w_newnode = (nodeptr_t)stm_allocate(sizeof(struct node_s)); - - w_prev = (nodeptr_t)stm_pop_root(); + + POP_ROOT(w_prev); w_newnode->value = LIST_LENGTH - i; w_newnode->next = NULL; @@ -163,44 +158,31 @@ w_prev = w_newnode; } - _stm_minor_collect(); /* hack.. */ - global_chained_list = (nodeptr_t)stm_pop_root(); - - stm_stop_transaction(); + //_stm_minor_collect(); /* hack.. */ + //POP_ROOT(global_chained_list); --- remains in the shadowstack - - + stm_commit_transaction(); + + printf("setup ok\n"); } static sem_t done; -static sem_t go; -static sem_t initialized; void *demo2(void *arg) { - int status; - if (arg != NULL) { - /* we still need to initialize */ - stm_setup_pthread(); - sem_post(&initialized); - status = sem_wait(&go); - assert(status == 0); - } - + stm_register_thread_local(&stm_thread_local); + while (check_sorted() == -1) { bubble_run(); } - if (arg != NULL) { - status = sem_post(&done); - assert(status == 0); - stm_teardown_pthread(); - } - + assert(stm_thread_local.shadowstack == stm_thread_local.shadowstack_base); + stm_unregister_thread_local(&stm_thread_local); + status = sem_post(&done); assert(status == 0); return NULL; } @@ -236,32 +218,22 @@ { int status; - status = sem_init(&initialized, 0, 0); - assert(status == 0); - status = sem_init(&go, 0, 0); - assert(status == 0); - + status = sem_init(&done, 0, 0); assert(status == 0); + stm_setup(); - stm_setup_pthread(); - - newthread(demo2, (void*)1); - - status = sem_wait(&initialized); - assert(status == 0); + stm_register_thread_local(&stm_thread_local); setup_list(); - status = sem_post(&go); - assert(status == 0); - - demo2(NULL); - - status = sem_wait(&done); - assert(status == 0); - + newthread(demo2, (void*)1); + newthread(demo2, (void*)2); + + status = sem_wait(&done); assert(status == 0); + status = sem_wait(&done); assert(status == 0); + final_check(); - stm_teardown_pthread(); + stm_unregister_thread_local(&stm_thread_local); stm_teardown(); return 0; diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c --- a/c7/stm/nursery.c +++ b/c7/stm/nursery.c @@ -199,7 +199,7 @@ /* may collect! */ STM_SEGMENT->nursery_current -= size_rounded_up; /* restore correct val */ - if (collectable_safe_point()) + if (_stm_collectable_safe_point()) return (stm_char *)stm_allocate(size_rounded_up); if (size_rounded_up < MEDIUM_OBJECT) { diff --git a/c7/stm/nursery.h b/c7/stm/nursery.h --- a/c7/stm/nursery.h +++ b/c7/stm/nursery.h @@ -3,6 +3,10 @@ #define NSE_SIGNAL 1 #define NSE_SIGNAL_DONE 2 +#if _STM_NSE_SIGNAL != NSE_SIGNAL +# error "adapt _STM_NSE_SIGNAL" +#endif + /* Rules for 'v_nursery_section_end': - Its main purpose is to be read by the owning thread in stm_allocate(). diff --git a/c7/stm/sync.c b/c7/stm/sync.c --- a/c7/stm/sync.c +++ b/c7/stm/sync.c @@ -266,7 +266,7 @@ return true; } -static bool collectable_safe_point(void) +bool _stm_collectable_safe_point(void) { bool any_operation = false; restart:; diff --git a/c7/stm/sync.h b/c7/stm/sync.h --- a/c7/stm/sync.h +++ b/c7/stm/sync.h @@ -17,4 +17,3 @@ /* see the source for an exact description */ static bool try_wait_for_other_safe_points(int requested_safe_point_kind); -static bool collectable_safe_point(void); diff --git a/c7/stmgc.h b/c7/stmgc.h --- a/c7/stmgc.h +++ b/c7/stmgc.h @@ -82,6 +82,7 @@ stm_char *_stm_allocate_slowpath(ssize_t); void _stm_become_inevitable(char*); void _stm_start_transaction(stm_thread_local_t *, stm_jmpbuf_t *); +bool _stm_collectable_safe_point(void); #ifdef STM_TESTS bool _stm_was_read(object_t *obj); @@ -100,6 +101,7 @@ #endif #define _STM_GCFLAG_WRITE_BARRIER_CALLED 0x80 +#define _STM_NSE_SIGNAL 1 #define STM_FLAGS_PREBUILT 0 @@ -208,13 +210,13 @@ void stm_register_thread_local(stm_thread_local_t *tl); void stm_unregister_thread_local(stm_thread_local_t *tl); -/* Starting and ending transactions. You should only call stm_read(), - stm_write() and stm_allocate() from within a transaction. Use - the macro STM_START_TRANSACTION() to start a transaction that +/* Starting and ending transactions. stm_read(), stm_write() and + stm_allocate() should only be called from within a transaction. + Use the macro STM_START_TRANSACTION() to start a transaction that can be restarted using the 'jmpbuf' (a local variable of type stm_jmpbuf_t). */ #define STM_START_TRANSACTION(tl, jmpbuf) ({ \ - int _restart = __builtin_setjmp(&jmpbuf); \ + int _restart = __builtin_setjmp(jmpbuf); \ _stm_start_transaction(tl, &jmpbuf); \ _restart; \ }) @@ -239,6 +241,13 @@ _stm_become_inevitable(msg); } +/* Forces a safe-point if needed. Normally not needed: this is + automatic if you call stm_allocate(). */ +static inline void stm_safe_point(void) { + if (STM_SEGMENT->v_nursery_section_end == _STM_NSE_SIGNAL) + _stm_collectable_safe_point(); +} + /* ==================== END ==================== */ _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit