Skip to content

Commit 705b490

Browse files
authored
Merge pull request scipy#21860 from rgommers/fix-f2py-tls
MAINT: improve handling of thread-local storage
2 parents 6acf136 + ac2c3d2 commit 705b490

File tree

8 files changed

+76
-39
lines changed

8 files changed

+76
-39
lines changed

scipy/_lib/meson.build

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,20 @@ lib_cython_gen = generator(cython,
3131
output : '@[email protected]',
3232
depends : [_cython_tree, _lib_pxd])
3333

34+
ccallback_dep = declare_dependency(include_directories: ['..', 'src'])
35+
3436
py3.extension_module('_ccallback_c',
3537
lib_cython_gen.process('_ccallback_c.pyx'),
3638
c_args: [cython_c_args, Wno_discarded_qualifiers],
37-
include_directories: 'src',
39+
dependencies: ccallback_dep,
3840
link_args: version_link_args,
3941
install: true,
4042
subdir: 'scipy/_lib'
4143
)
4244

4345
py3.extension_module('_test_ccallback',
4446
'src/_test_ccallback.c',
45-
include_directories: 'src',
47+
dependencies: ccallback_dep,
4648
link_args: version_link_args,
4749
install: true,
4850
subdir: 'scipy/_lib',

scipy/_lib/src/ccallback.h

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <Python.h>
2323
#include <setjmp.h>
2424

25+
#include "scipy_config.h"
26+
2527
/* Default behavior */
2628
#define CCALLBACK_DEFAULTS 0x0
2729
/* Whether calling ccallback_obtain is enabled */
@@ -66,32 +68,9 @@ struct ccallback {
6668
* Thread-local storage
6769
*/
6870

69-
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)))
70-
71-
static __thread ccallback_t *_active_ccallback = NULL;
72-
73-
static void *ccallback__get_thread_local(void)
74-
{
75-
return (void *)_active_ccallback;
76-
}
77-
78-
static int ccallback__set_thread_local(void *value)
79-
{
80-
_active_ccallback = value;
81-
return 0;
82-
}
83-
84-
/*
85-
* Obtain a pointer to the current ccallback_t structure.
86-
*/
87-
static ccallback_t *ccallback_obtain(void)
88-
{
89-
return (ccallback_t *)ccallback__get_thread_local();
90-
}
91-
92-
#elif defined(_MSC_VER)
71+
#if !defined(SCIPY_TLS_EMPTY)
9372

94-
static __declspec(thread) ccallback_t *_active_ccallback = NULL;
73+
static SCIPY_TLS ccallback_t *_active_ccallback = NULL;
9574

9675
static void *ccallback__get_thread_local(void)
9776
{

scipy/integrate/meson.build

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ dop_lib = static_library('dop_lib',
6363

6464
py3.extension_module('_quadpack',
6565
['__quadpack.h', '__quadpack.c'],
66-
include_directories: ['../_lib/src'],
67-
dependencies: np_dep,
66+
dependencies: [np_dep, ccallback_dep],
6867
install: true,
6968
subdir: 'scipy/integrate'
7069
)

scipy/meson.build

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,51 @@ fortranobject_dep = declare_dependency(
136136
link_with: fortranobject_lib,
137137
include_directories: [inc_np, inc_f2py],
138138
)
139-
# Workaround for numpy#24761 on numpy<1.26.1 (see also gh-20515)
140-
_f2py_c_args = []
141-
if is_mingw
142-
_f2py_c_args = '-DNPY_OS_MINGW'
139+
140+
cdata = configuration_data()
141+
142+
# Test variable attribute to use for thread-local storage;
143+
# Adapted from `numpy/_core/meson.build`.
144+
check_tls_attrs = [
145+
['thread_local', 'HAVE_THREAD_LOCAL'], # C23
146+
['_Thread_local', 'HAVE__THREAD_LOCAL'], # C11/C17
147+
['__thread', 'HAVE__THREAD'],
148+
]
149+
if is_windows and not is_mingw
150+
check_tls_attrs += ['__declspec(thread)', 'HAVE___DECLSPEC_THREAD_']
143151
endif
152+
f2py_tls_define = ''
153+
foreach tls_attrs: check_tls_attrs
154+
attr = tls_attrs[0]
155+
code = f'''
156+
#pragma GCC diagnostic error "-Wattributes"
157+
#pragma clang diagnostic error "-Wattributes"
158+
159+
int @attr@ foo;
160+
'''
161+
code += '''
162+
int
163+
main()
164+
{
165+
return 0;
166+
}
167+
'''
168+
if cc.compiles(code, name: tls_attrs[0])
169+
cdata.set10(tls_attrs[1], true)
170+
f2py_tls_define = tls_attrs[0]
171+
endif
172+
endforeach
173+
174+
# Contains only TLS check results for now - name chosen for when more compiler
175+
# checks need adding in the future.
176+
scipy_config_h = configure_file(
177+
input: 'scipy_config.h.in',
178+
output: 'scipy_config.h',
179+
configuration: cdata,
180+
install: false
181+
)
182+
183+
_f2py_c_args = [f'-DF2PY_THREAD_LOCAL_DECL=@f2py_tls_define@']
144184
fortranobject_dep = declare_dependency(
145185
dependencies: fortranobject_dep,
146186
compile_args: _f2py_c_args,

scipy/ndimage/meson.build

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ py3.extension_module('_nd_image',
99
'src/ni_splines.c',
1010
'src/ni_support.c'
1111
],
12-
include_directories: ['../_lib/src', '../_build_utils/src'],
13-
dependencies: np_dep,
12+
include_directories: ['../_build_utils/src'],
13+
dependencies: [np_dep, ccallback_dep],
1414
link_args: version_link_args,
1515
install: true,
1616
subdir: 'scipy/ndimage'

scipy/optimize/meson.build

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ py3.extension_module('_minpack',
1919
'__minpack.h',
2020
'__minpack.c',
2121
],
22-
include_directories: '../_lib/src',
23-
dependencies: np_dep,
22+
dependencies: [np_dep, ccallback_dep],
2423
install: true,
2524
subdir: 'scipy/optimize'
2625
)

scipy/scipy_config.h.in

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* Thread-local storage */
2+
#mesondefine HAVE_THREAD_LOCAL
3+
#mesondefine HAVE__THREAD_LOCAL
4+
#mesondefine HAVE__THREAD
5+
#mesondefine HAVE___DECLSPEC_THREAD_
6+
7+
#ifdef __cplusplus
8+
#define SCIPY_TLS thread_local
9+
#elif defined(HAVE_THREAD_LOCAL)
10+
#define SCIPY_TLS thread_local
11+
#elif defined(HAVE__THREAD_LOCAL)
12+
#define SCIPY_TLS _Thread_local
13+
#elif defined(HAVE___THREAD)
14+
#define SCIPY_TLS __thread
15+
#elif defined(HAVE___DECLSPEC_THREAD_)
16+
#define SCIPY_TLS __declspec(thread)
17+
#else
18+
#define SCIPY_TLS
19+
#endif

scipy/stats/_unuran/meson.build

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ unuran_sources = [
156156
]
157157

158158
unuran_include_dirs = [
159-
'../../_lib/src', # for messagestream.h
160159
'../../_lib/unuran/unuran/src',
161160
'../../_lib/unuran/unuran/src/distr',
162161
'../../_lib/unuran/unuran/src/distributions',
@@ -228,7 +227,7 @@ py3.extension_module('unuran_wrapper',
228227
],
229228
c_args: [unuran_defines, cython_c_args],
230229
include_directories: [unuran_include_dirs],
231-
dependencies: np_dep,
230+
dependencies: [np_dep, ccallback_dep],
232231
link_args: version_link_args,
233232
install: true,
234233
subdir: 'scipy/stats/_unuran'

0 commit comments

Comments
 (0)