diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2019-03-03 21:34:08 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2019-03-03 21:34:08 +0100 |
commit | 6bb8b78a37d36e19d48897da6931fd9e82f4710a (patch) | |
tree | 0ce54246ed0096414777afd7656df3ad2253ce77 | |
parent | b9eaba7c7efa9631d48d016b83891c26814d8324 (diff) | |
download | cython-6bb8b78a37d36e19d48897da6931fd9e82f4710a.tar.gz |
Use "fast_gil" calls in line tracing code when available, and actually test it.
-rw-r--r-- | Cython/Compiler/Code.py | 26 | ||||
-rw-r--r-- | Cython/Compiler/ModuleNode.py | 2 | ||||
-rw-r--r-- | Cython/Compiler/Nodes.py | 2 | ||||
-rw-r--r-- | Cython/Utility/Profile.c | 4 | ||||
-rw-r--r-- | tests/run/coverage_nogil.srctree | 46 |
5 files changed, 46 insertions, 34 deletions
diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 02dd3a5d5..3817dd79a 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -2228,6 +2228,12 @@ class CCodeWriter(object): # GIL methods + def use_fast_gil_utility_code(self): + if self.globalstate.directives['fast_gil']: + self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c")) + else: + self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c")) + def put_ensure_gil(self, declare_gilstate=True, variable=None): """ Acquire the GIL. The generated code is safe even when no PyThreadState @@ -2237,10 +2243,7 @@ class CCodeWriter(object): """ self.globalstate.use_utility_code( UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c")) - if self.globalstate.directives['fast_gil']: - self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c")) - else: - self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c")) + self.use_fast_gil_utility_code() self.putln("#ifdef WITH_THREAD") if not variable: variable = '__pyx_gilstate_save' @@ -2253,10 +2256,7 @@ class CCodeWriter(object): """ Releases the GIL, corresponds to `put_ensure_gil`. """ - if self.globalstate.directives['fast_gil']: - self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c")) - else: - self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c")) + self.use_fast_gil_utility_code() if not variable: variable = '__pyx_gilstate_save' self.putln("#ifdef WITH_THREAD") @@ -2268,10 +2268,7 @@ class CCodeWriter(object): Acquire the GIL. The thread's thread state must have been initialized by a previous `put_release_gil` """ - if self.globalstate.directives['fast_gil']: - self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c")) - else: - self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c")) + self.use_fast_gil_utility_code() self.putln("#ifdef WITH_THREAD") self.putln("__Pyx_FastGIL_Forget();") if variable: @@ -2281,10 +2278,7 @@ class CCodeWriter(object): def put_release_gil(self, variable=None): "Release the GIL, corresponds to `put_acquire_gil`." - if self.globalstate.directives['fast_gil']: - self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c")) - else: - self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c")) + self.use_fast_gil_utility_code() self.putln("#ifdef WITH_THREAD") self.putln("PyThreadState *_save;") self.putln("Py_UNBLOCK_THREADS") diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 27fcad6e1..62f027d2c 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -2350,6 +2350,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): profile = code.globalstate.directives['profile'] linetrace = code.globalstate.directives['linetrace'] if profile or linetrace: + if linetrace: + code.use_fast_gil_utility_code() code.globalstate.use_utility_code(UtilityCode.load_cached("Profile", "Profile.c")) code.put_declare_refcount_context() diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index d8747a934..a119a848c 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1788,6 +1788,8 @@ class FuncDefNode(StatNode, BlockNode): profile = code.globalstate.directives['profile'] linetrace = code.globalstate.directives['linetrace'] if profile or linetrace: + if linetrace: + code.use_fast_gil_utility_code() code.globalstate.use_utility_code( UtilityCode.load_cached("Profile", "Profile.c")) diff --git a/Cython/Utility/Profile.c b/Cython/Utility/Profile.c index c4463e80a..d5e8606e4 100644 --- a/Cython/Utility/Profile.c +++ b/Cython/Utility/Profile.c @@ -197,12 +197,12 @@ if (CYTHON_TRACE_NOGIL) { \ int ret = 0; \ PyThreadState *tstate; \ - PyGILState_STATE state = PyGILState_Ensure(); \ + PyGILState_STATE state = __Pyx_PyGILState_Ensure(); \ tstate = __Pyx_PyThreadState_Current; \ if (unlikely(tstate->use_tracing && tstate->c_tracefunc && $frame_cname->f_trace)) { \ ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ } \ - PyGILState_Release(state); \ + __Pyx_PyGILState_Release(state); \ if (unlikely(ret)) goto_error; \ } \ } else { \ diff --git a/tests/run/coverage_nogil.srctree b/tests/run/coverage_nogil.srctree index 053008cc2..d51993ea5 100644 --- a/tests/run/coverage_nogil.srctree +++ b/tests/run/coverage_nogil.srctree @@ -1,5 +1,5 @@ # mode: run -# tag: coverage,trace,nogil +# tag: coverage,trace,nogil,fastgil """ PYTHON setup.py build_ext -i @@ -21,22 +21,34 @@ setup(ext_modules = cythonize([ plugins = Cython.Coverage -######## coverage_test_nogil.pyx ######## -# cython: linetrace=True +######## coverage_test_nogil_fastgil.pyx ######## +# cython: linetrace=True,fast_gil=True # distutils: define_macros=CYTHON_TRACE=1 CYTHON_TRACE_NOGIL=1 +include "_coverage_test_nogil.pxi" + +######## coverage_test_nogil_nofastgil.pyx ######## +# cython: linetrace=True,fast_gil=False +# distutils: define_macros=CYTHON_TRACE=1 CYTHON_TRACE_NOGIL=1 +include "_coverage_test_nogil.pxi" + + +######## _coverage_test_nogil.pxi ######## +# 1 +# 2 +# 3 cdef int func1(int a, int b) nogil: # 4 cdef int x # 5 with gil: # 6 x = 1 # 7 cdef int c = func2(a) + b # 8 return x + c # 9 - - +# 10 +# 11 cdef int func2(int a) with gil: # 12 return a * 2 # 13 - - +# 14 +# 15 def call(int a, int b): # 16 a, b = b, a # 17 with nogil: # 18 @@ -56,11 +68,12 @@ except ImportError: from coverage import coverage -def run_coverage(): +def run_coverage(module_name): + print("Testing module %s" % module_name) cov = coverage() cov.start() - import coverage_test_nogil as module + module = __import__(module_name) module_name = module.__name__ module_path = module_name + '.pyx' assert not any(module.__file__.endswith(ext) @@ -69,7 +82,6 @@ def run_coverage(): assert module.call(1, 2) == (1 * 2) + 2 + 1 cov.stop() - out = StringIO() cov.report(file=out) #cov.report([module], file=out) @@ -77,15 +89,17 @@ def run_coverage(): assert any(module_path in line for line in lines), \ "'%s' not found in coverage report:\n\n%s" % (module_path, out.getvalue()) - mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(os.path.abspath(module_path)) - assert module_path in mod_file + module_pxi = "_coverage_test_nogil.pxi" + mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(os.path.abspath(module_pxi)) + assert module_pxi in mod_file executed = set(exec_lines) - set(missing_lines) - # check that everything that runs with the gil owned was executed - assert all(line in executed for line in [12, 13, 16, 17, 18, 20]), '%s / %s' % (exec_lines, missing_lines) + # check that everything that runs with the gil owned was executed (missing due to pxi: 4, 12, 16) + assert all(line in executed for line in [13, 17, 18, 20]), '%s / %s' % (exec_lines, missing_lines) # check that everything that runs in nogil sections was executed - assert all(line in executed for line in [4, 6, 7, 8, 9]), '%s / %s' % (exec_lines, missing_lines) + assert all(line in executed for line in [6, 7, 8, 9]), '%s / %s' % (exec_lines, missing_lines) if __name__ == '__main__': - run_coverage() + for module_name in ["coverage_test_nogil_fastgil", "coverage_test_nogil_nofastgil"]: + run_coverage(module_name) |