Author: Armin Rigo <ar...@tunes.org> Branch: nogil-unsafe-2 Changeset: r90422:643158ba7b39 Date: 2017-02-28 15:31 +0100 http://bitbucket.org/pypy/pypy/changeset/643158ba7b39/
Log: progress diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py --- a/rpython/memory/gctransform/shadowstack.py +++ b/rpython/memory/gctransform/shadowstack.py @@ -104,7 +104,7 @@ self.rootstackhook(collect_stack_root, gcdata.root_stack_base, gcdata.root_stack_top) - def need_thread_support(self, gctransformer, getfn): + def need_thread_support_WITH_GIL(self, gctransformer, getfn): from rpython.rlib import rthread # xxx fish gcdata = self.gcdata # the interfacing between the threads and the GC is done via @@ -218,6 +218,49 @@ annmodel.s_None, minimal_transform=False) + def need_thread_support(self, gctransformer, getfn): # NO GIL VERSION + from rpython.rlib import rthread + gcdata = self.gcdata + # the interfacing between the threads and the GC is done via + # two completely ad-hoc operations at the moment: + # gc_thread_run and gc_thread_die. See docstrings below. + + tl_shadowstack = rthread.ThreadLocalField(llmemory.Address, + 'shadowstack') + + def thread_setup(): + allocate_shadow_stack() + + def thread_run(): + # If it's the first time we see this thread, allocate + # a shadowstack. + if tl_shadowstack.get_or_make_raw() == llmemory.NULL: + allocate_shadow_stack() + + def allocate_shadow_stack(): + root_stack_depth = 163840 + root_stack_size = sizeofaddr * root_stack_depth + ss = llmemory.raw_malloc(root_stack_size) + if not ss: + raise MemoryError + tl_shadowstack.setraw(ss) + allocate_shadow_stack._dont_inline_ = True + + def thread_die(): + """Called just before the final GIL release done by a dying + thread. After a thread_die(), no more gc operation should + occur in this thread. + """ + p = tl_shadowstack.get_or_make_raw() + tl_shadowstack.setraw(llmemory.NULL) + llmemory.raw_free(p) + + self.thread_setup = thread_setup + self.thread_run_ptr = getfn(thread_run, [], annmodel.s_None, + inline=True, minimal_transform=False) + self.thread_die_ptr = getfn(thread_die, [], annmodel.s_None, + minimal_transform=False) + def need_stacklet_support(self, gctransformer, getfn): from rpython.rlib import _stacklet_shadowstack _stacklet_shadowstack.complete_destrptr(gctransformer) diff --git a/rpython/translator/c/src/thread.h b/rpython/translator/c/src/thread.h --- a/rpython/translator/c/src/thread.h +++ b/rpython/translator/c/src/thread.h @@ -2,6 +2,7 @@ #define __PYPY_THREAD_H #include "precommondefs.h" #include <assert.h> +#include <stdlib.h> #define RPY_TIMEOUT_T long long @@ -41,19 +42,20 @@ # define RPY_FASTGIL_LOCKED(x) (x != 0) #endif -RPY_EXTERN long rpy_fastgil; +//RPY_EXTERN long rpy_fastgil; static inline void _RPyGilAcquire(void) { - long old_fastgil = pypy_lock_test_and_set(&rpy_fastgil, 1); - if (old_fastgil != 0) - RPyGilAcquireSlowPath(old_fastgil); +// long old_fastgil = pypy_lock_test_and_set(&rpy_fastgil, 1); +// if (old_fastgil != 0) +// RPyGilAcquireSlowPath(old_fastgil); } static inline void _RPyGilRelease(void) { - assert(RPY_FASTGIL_LOCKED(rpy_fastgil)); - pypy_lock_release(&rpy_fastgil); +// assert(RPY_FASTGIL_LOCKED(rpy_fastgil)); +// pypy_lock_release(&rpy_fastgil); } static inline long *_RPyFetchFastGil(void) { - return &rpy_fastgil; + abort(); +// return &rpy_fastgil; } #endif diff --git a/rpython/translator/c/src/thread_gil.c b/rpython/translator/c/src/thread_gil.c --- a/rpython/translator/c/src/thread_gil.c +++ b/rpython/translator/c/src/thread_gil.c @@ -58,13 +58,13 @@ void RPyGilAllocate(void) { - if (rpy_waiting_threads < 0) { - assert(rpy_waiting_threads == -42); - rpy_init_mutexes(); +// if (rpy_waiting_threads < 0) { +// assert(rpy_waiting_threads == -42); +// rpy_init_mutexes(); #ifdef HAVE_PTHREAD_ATFORK - pthread_atfork(NULL, NULL, rpy_init_mutexes); +// pthread_atfork(NULL, NULL, rpy_init_mutexes); #endif - } +// } } static void check_and_save_old_fastgil(long old_fastgil) diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -1427,6 +1427,46 @@ and result.count('a') == 1 and result.count('d') == 6) + def test_thread_and_gc_nogil(self): + import time, gc + from rpython.rlib import rthread, rposix + + def bootstrap(): + rthread.gc_thread_start() + os.write(1, "hi there\n") + rthread.gc_thread_die() + + def new_thread(): + ident = rthread.start_new_thread(bootstrap, ()) + return ident + + def entry_point(argv): + os.write(1, "hello world\n") + # start 5 new threads + ident1 = new_thread() + ident2 = new_thread() + ident3 = new_thread() + ident4 = new_thread() + ident5 = new_thread() + # wait for the 5 threads to finish + time.sleep(1) + gc.collect() + return 0 + + def runme(no__thread): + t, cbuilder = self.compile(entry_point, no__thread=no__thread) + data = cbuilder.cmdexec('') + assert data.splitlines() == ['hello world', + '1 ok', + '2 ok', + '3 ok', + '4 ok', + '5 ok'] + + if SUPPORT__THREAD: + runme(no__thread=False) + runme(no__thread=True) + class TestShared(StandaloneTests): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit