diff options
author | Antoine Pitrou <pitrou@free.fr> | 2017-09-07 16:56:24 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2017-09-07 16:56:24 (GMT) |
commit | a6a4dc816d68df04a7d592e0b6af8c7ecc4d4344 (patch) | |
tree | 1c31738009bee903417cea928e705a112aea2392 /Python | |
parent | 1f06a680de465be0c24a78ea3b610053955daa99 (diff) | |
download | cpython-a6a4dc816d68df04a7d592e0b6af8c7ecc4d4344.zip cpython-a6a4dc816d68df04a7d592e0b6af8c7ecc4d4344.tar.gz cpython-a6a4dc816d68df04a7d592e0b6af8c7ecc4d4344.tar.bz2 |
bpo-31370: Remove support for threads-less builds (#3385)
* Remove Setup.config
* Always define WITH_THREAD for compatibility.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 124 | ||||
-rw-r--r-- | Python/fileutils.c | 14 | ||||
-rw-r--r-- | Python/import.c | 14 | ||||
-rw-r--r-- | Python/mystrtoul.c | 2 | ||||
-rw-r--r-- | Python/pylifecycle.c | 12 | ||||
-rw-r--r-- | Python/pystate.c | 30 | ||||
-rw-r--r-- | Python/sysmodule.c | 7 | ||||
-rw-r--r-- | Python/traceback.c | 16 |
8 files changed, 3 insertions, 216 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 436e5ca..8fc65cd 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -87,11 +87,7 @@ static long dxp[256]; #endif #endif -#ifdef WITH_THREAD #define GIL_REQUEST _Py_atomic_load_relaxed(&gil_drop_request) -#else -#define GIL_REQUEST 0 -#endif /* This can set eval_breaker to 0 even though gil_drop_request became 1. We believe this is all right because the eval loop will release @@ -103,8 +99,6 @@ static long dxp[256]; _Py_atomic_load_relaxed(&pendingcalls_to_do) | \ pending_async_exc) -#ifdef WITH_THREAD - #define SET_GIL_DROP_REQUEST() \ do { \ _Py_atomic_store_relaxed(&gil_drop_request, 1); \ @@ -117,8 +111,6 @@ static long dxp[256]; COMPUTE_EVAL_BREAKER(); \ } while (0) -#endif - /* Pending calls are only modified under pending_lock */ #define SIGNAL_PENDING_CALLS() \ do { \ @@ -151,8 +143,6 @@ static _Py_atomic_int pendingcalls_to_do = {0}; Guarded by the GIL. */ static int pending_async_exc = 0; -#ifdef WITH_THREAD - #ifdef HAVE_ERRNO_H #include <errno.h> #endif @@ -256,8 +246,6 @@ PyEval_ReInitThreads(void) _PyThreadState_DeleteExcept(current_tstate); } -#endif /* WITH_THREAD */ - /* This function is used to signal that async exceptions are waiting to be raised, therefore it is also useful in non-threaded builds. */ @@ -277,10 +265,8 @@ PyEval_SaveThread(void) PyThreadState *tstate = PyThreadState_Swap(NULL); if (tstate == NULL) Py_FatalError("PyEval_SaveThread: NULL tstate"); -#ifdef WITH_THREAD if (gil_created()) drop_gil(tstate); -#endif return tstate; } @@ -289,7 +275,6 @@ PyEval_RestoreThread(PyThreadState *tstate) { if (tstate == NULL) Py_FatalError("PyEval_RestoreThread: NULL tstate"); -#ifdef WITH_THREAD if (gil_created()) { int err = errno; take_gil(tstate); @@ -301,7 +286,6 @@ PyEval_RestoreThread(PyThreadState *tstate) } errno = err; } -#endif PyThreadState_Swap(tstate); } @@ -320,14 +304,12 @@ PyEval_RestoreThread(PyThreadState *tstate) Note that because registry may occur from within signal handlers, or other asynchronous events, calling malloc() is unsafe! -#ifdef WITH_THREAD Any thread can schedule pending calls, but only the main thread will execute them. There is no facility to schedule calls to a particular thread, but that should be easy to change, should that ever be required. In that case, the static variables here should go into the python threadstate. -#endif */ void @@ -339,9 +321,7 @@ _PyEval_SignalReceived(void) SIGNAL_PENDING_CALLS(); } -#ifdef WITH_THREAD - -/* The WITH_THREAD implementation is thread-safe. It allows +/* This implementation is thread-safe. It allows scheduling to be made from any thread, and even from an executing callback. */ @@ -464,106 +444,6 @@ error: return -1; } -#else /* if ! defined WITH_THREAD */ - -/* - WARNING! ASYNCHRONOUSLY EXECUTING CODE! - This code is used for signal handling in python that isn't built - with WITH_THREAD. - Don't use this implementation when Py_AddPendingCalls() can happen - on a different thread! - - There are two possible race conditions: - (1) nested asynchronous calls to Py_AddPendingCall() - (2) AddPendingCall() calls made while pending calls are being processed. - - (1) is very unlikely because typically signal delivery - is blocked during signal handling. So it should be impossible. - (2) is a real possibility. - The current code is safe against (2), but not against (1). - The safety against (2) is derived from the fact that only one - thread is present, interrupted by signals, and that the critical - section is protected with the "busy" variable. On Windows, which - delivers SIGINT on a system thread, this does not hold and therefore - Windows really shouldn't use this version. - The two threads could theoretically wiggle around the "busy" variable. -*/ - -#define NPENDINGCALLS 32 -static struct { - int (*func)(void *); - void *arg; -} pendingcalls[NPENDINGCALLS]; -static volatile int pendingfirst = 0; -static volatile int pendinglast = 0; - -int -Py_AddPendingCall(int (*func)(void *), void *arg) -{ - static volatile int busy = 0; - int i, j; - /* XXX Begin critical section */ - if (busy) - return -1; - busy = 1; - i = pendinglast; - j = (i + 1) % NPENDINGCALLS; - if (j == pendingfirst) { - busy = 0; - return -1; /* Queue full */ - } - pendingcalls[i].func = func; - pendingcalls[i].arg = arg; - pendinglast = j; - - SIGNAL_PENDING_CALLS(); - busy = 0; - /* XXX End critical section */ - return 0; -} - -int -Py_MakePendingCalls(void) -{ - static int busy = 0; - if (busy) - return 0; - busy = 1; - - /* unsignal before starting to call callbacks, so that any callback - added in-between re-signals */ - UNSIGNAL_PENDING_CALLS(); - /* Python signal handler doesn't really queue a callback: it only signals - that a signal was received, see _PyEval_SignalReceived(). */ - if (PyErr_CheckSignals() < 0) { - goto error; - } - - for (;;) { - int i; - int (*func)(void *); - void *arg; - i = pendingfirst; - if (i == pendinglast) - break; /* Queue empty */ - func = pendingcalls[i].func; - arg = pendingcalls[i].arg; - pendingfirst = (i + 1) % NPENDINGCALLS; - if (func(arg) < 0) { - goto error; - } - } - busy = 0; - return 0; - -error: - busy = 0; - SIGNAL_PENDING_CALLS(); /* We're not done yet */ - return -1; -} - -#endif /* WITH_THREAD */ - /* The interpreter's recursion limit */ @@ -1101,7 +981,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) if (Py_MakePendingCalls() < 0) goto error; } -#ifdef WITH_THREAD if (_Py_atomic_load_relaxed(&gil_drop_request)) { /* Give another thread a chance */ if (PyThreadState_Swap(NULL) != tstate) @@ -1121,7 +1000,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) if (PyThreadState_Swap(tstate) != NULL) Py_FatalError("ceval: orphan tstate"); } -#endif /* Check for asynchronous exceptions. */ if (tstate->async_exc != NULL) { PyObject *exc = tstate->async_exc; diff --git a/Python/fileutils.c b/Python/fileutils.c index 97505e5..1cd8ac5 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -680,9 +680,7 @@ _Py_fstat(int fd, struct _Py_stat_struct *status) { int res; -#ifdef WITH_THREAD assert(PyGILState_Check()); -#endif Py_BEGIN_ALLOW_THREADS res = _Py_fstat_noraise(fd, status); @@ -999,10 +997,8 @@ _Py_open_impl(const char *pathname, int flags, int gil_held) int _Py_open(const char *pathname, int flags) { -#ifdef WITH_THREAD /* _Py_open() must be called with the GIL held. */ assert(PyGILState_Check()); -#endif return _Py_open_impl(pathname, flags, 1); } @@ -1095,9 +1091,7 @@ _Py_fopen_obj(PyObject *path, const char *mode) wchar_t wmode[10]; int usize; -#ifdef WITH_THREAD assert(PyGILState_Check()); -#endif if (!PyUnicode_Check(path)) { PyErr_Format(PyExc_TypeError, @@ -1125,9 +1119,7 @@ _Py_fopen_obj(PyObject *path, const char *mode) PyObject *bytes; char *path_bytes; -#ifdef WITH_THREAD assert(PyGILState_Check()); -#endif if (!PyUnicode_FSConverter(path, &bytes)) return NULL; @@ -1177,9 +1169,7 @@ _Py_read(int fd, void *buf, size_t count) int err; int async_err = 0; -#ifdef WITH_THREAD assert(PyGILState_Check()); -#endif /* _Py_read() must not be called with an exception set, otherwise the * caller may think that read() was interrupted by a signal and the signal @@ -1318,9 +1308,7 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held) Py_ssize_t _Py_write(int fd, const void *buf, size_t count) { -#ifdef WITH_THREAD assert(PyGILState_Check()); -#endif /* _Py_write() must not be called with an exception set, otherwise the * caller may think that write() was interrupted by a signal and the signal @@ -1471,9 +1459,7 @@ _Py_dup(int fd) DWORD ftype; #endif -#ifdef WITH_THREAD assert(PyGILState_Check()); -#endif #ifdef MS_WINDOWS _Py_BEGIN_SUPPRESS_IPH diff --git a/Python/import.c b/Python/import.c index 542a91b..a406db3 100644 --- a/Python/import.c +++ b/Python/import.c @@ -142,8 +142,6 @@ _PyImportZip_Init(void) in different threads to return with a partially loaded module. These calls are serialized by the global interpreter lock. */ -#ifdef WITH_THREAD - #include "pythread.h" static PyThread_type_lock import_lock = 0; @@ -224,8 +222,6 @@ _PyImport_ReInitLock(void) } } -#endif - /*[clinic input] _imp.lock_held @@ -238,11 +234,7 @@ static PyObject * _imp_lock_held_impl(PyObject *module) /*[clinic end generated code: output=8b89384b5e1963fc input=9b088f9b217d9bdf]*/ { -#ifdef WITH_THREAD return PyBool_FromLong(import_lock_thread != PYTHREAD_INVALID_THREAD_ID); -#else - Py_RETURN_FALSE; -#endif } /*[clinic input] @@ -258,9 +250,7 @@ static PyObject * _imp_acquire_lock_impl(PyObject *module) /*[clinic end generated code: output=1aff58cb0ee1b026 input=4a2d4381866d5fdc]*/ { -#ifdef WITH_THREAD _PyImport_AcquireLock(); -#endif Py_RETURN_NONE; } @@ -276,13 +266,11 @@ static PyObject * _imp_release_lock_impl(PyObject *module) /*[clinic end generated code: output=7faab6d0be178b0a input=934fb11516dd778b]*/ { -#ifdef WITH_THREAD if (_PyImport_ReleaseLock() < 0) { PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); return NULL; } -#endif Py_RETURN_NONE; } @@ -290,12 +278,10 @@ void _PyImport_Fini(void) { Py_CLEAR(extensions); -#ifdef WITH_THREAD if (import_lock != NULL) { PyThread_free_lock(import_lock); import_lock = NULL; } -#endif } /* Helper for sys */ diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c index a85790e..7ab5814 100644 --- a/Python/mystrtoul.c +++ b/Python/mystrtoul.c @@ -1,7 +1,7 @@ #include "Python.h" -#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE) +#if defined(__sgi) && !defined(_SGI_MP_SOURCE) #define _SGI_MP_SOURCE #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 662405b..7798dfe 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -72,10 +72,8 @@ extern int _PyTraceMalloc_Init(void); extern int _PyTraceMalloc_Fini(void); extern void _Py_ReadyTypes(void); -#ifdef WITH_THREAD extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); extern void _PyGILState_Fini(void); -#endif /* WITH_THREAD */ /* Global configuration variable declarations are in pydebug.h */ /* XXX (ncoghlan): move those declarations to pylifecycle.h? */ @@ -618,7 +616,6 @@ void _Py_InitializeCore(const _PyCoreConfig *config) Py_FatalError("Py_InitializeCore: can't make first thread"); (void) PyThreadState_Swap(tstate); -#ifdef WITH_THREAD /* We can't call _PyEval_FiniThreads() in Py_FinalizeEx because destroying the GIL might fail when it is being referenced from another running thread (see issue #9901). @@ -627,7 +624,6 @@ void _Py_InitializeCore(const _PyCoreConfig *config) _PyEval_FiniThreads(); /* Auto-thread-state API */ _PyGILState_Init(interp, tstate); -#endif /* WITH_THREAD */ _Py_ReadyTypes(); @@ -1084,9 +1080,7 @@ Py_FinalizeEx(void) PyGrammar_RemoveAccelerators(&_PyParser_Grammar); /* Cleanup auto-thread-state */ -#ifdef WITH_THREAD _PyGILState_Fini(); -#endif /* WITH_THREAD */ /* Delete current thread. After this, many C API calls become crashy. */ PyThreadState_Swap(NULL); @@ -1142,11 +1136,9 @@ Py_NewInterpreter(void) if (!_Py_Initialized) Py_FatalError("Py_NewInterpreter: call Py_Initialize first"); -#ifdef WITH_THREAD /* Issue #10915, #15751: The GIL API doesn't work with multiple interpreters: disable PyGILState_Check(). */ _PyGILState_check_enabled = 0; -#endif interp = PyInterpreterState_New(); if (interp == NULL) @@ -1850,9 +1842,7 @@ exit: /* Clean up and exit */ -#ifdef WITH_THREAD # include "pythread.h" -#endif static void (*pyexitfunc)(void) = NULL; /* For the atexit module. */ @@ -1878,7 +1868,6 @@ call_py_exitfuncs(void) static void wait_for_thread_shutdown(void) { -#ifdef WITH_THREAD _Py_IDENTIFIER(_shutdown); PyObject *result; PyObject *threading = _PyImport_GetModuleId(&PyId_threading); @@ -1896,7 +1885,6 @@ wait_for_thread_shutdown(void) Py_DECREF(result); } Py_DECREF(threading); -#endif } #define NEXITFUNCS 32 diff --git a/Python/pystate.c b/Python/pystate.c index 30a3722..379e5a3 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -36,7 +36,6 @@ extern "C" { int _PyGILState_check_enabled = 1; -#ifdef WITH_THREAD #include "pythread.h" static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */ #define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock())) @@ -49,11 +48,6 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */ /* TODO: Given interp_main, it may be possible to kill this ref */ static PyInterpreterState *autoInterpreterState = NULL; static int autoTLSkey = -1; -#else -#define HEAD_INIT() /* Nothing */ -#define HEAD_LOCK() /* Nothing */ -#define HEAD_UNLOCK() /* Nothing */ -#endif static PyInterpreterState *interp_head = NULL; static PyInterpreterState *interp_main = NULL; @@ -63,9 +57,7 @@ static PyInterpreterState *interp_main = NULL; _Py_atomic_address _PyThreadState_Current = {0}; PyThreadFrameGetter _PyThreadState_GetFrame = NULL; -#ifdef WITH_THREAD static void _PyGILState_NoteThreadState(PyThreadState* tstate); -#endif /* _next_interp_id is an auto-numbered sequence of small integers. It gets initialized in _PyInterpreterState_Init(), which is called @@ -93,10 +85,8 @@ PyInterpreterState_New(void) if (interp != NULL) { HEAD_INIT(); -#ifdef WITH_THREAD if (head_mutex == NULL) Py_FatalError("Can't initialize threads for interpreter"); -#endif interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; @@ -206,12 +196,10 @@ PyInterpreterState_Delete(PyInterpreterState *interp) } HEAD_UNLOCK(); PyMem_RawFree(interp); -#ifdef WITH_THREAD if (interp_head == NULL && head_mutex != NULL) { PyThread_free_lock(head_mutex); head_mutex = NULL; } -#endif } @@ -252,11 +240,7 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->use_tracing = 0; tstate->gilstate_counter = 0; tstate->async_exc = NULL; -#ifdef WITH_THREAD tstate->thread_id = PyThread_get_thread_ident(); -#else - tstate->thread_id = 0; -#endif tstate->dict = NULL; @@ -314,9 +298,7 @@ _PyThreadState_Prealloc(PyInterpreterState *interp) void _PyThreadState_Init(PyThreadState *tstate) { -#ifdef WITH_THREAD _PyGILState_NoteThreadState(tstate); -#endif } PyObject* @@ -498,15 +480,12 @@ PyThreadState_Delete(PyThreadState *tstate) { if (tstate == GET_TSTATE()) Py_FatalError("PyThreadState_Delete: tstate is still current"); -#ifdef WITH_THREAD if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) PyThread_delete_key_value(autoTLSkey); -#endif /* WITH_THREAD */ tstate_delete_common(tstate); } -#ifdef WITH_THREAD void PyThreadState_DeleteCurrent() { @@ -520,7 +499,6 @@ PyThreadState_DeleteCurrent() SET_TSTATE(NULL); PyEval_ReleaseLock(); } -#endif /* WITH_THREAD */ /* @@ -588,7 +566,7 @@ PyThreadState_Swap(PyThreadState *newts) to be used for a thread. Check this the best we can in debug builds. */ -#if defined(Py_DEBUG) && defined(WITH_THREAD) +#if defined(Py_DEBUG) if (newts) { /* This can be called from PyEval_RestoreThread(). Similar to it, we need to ensure errno doesn't change. @@ -749,7 +727,6 @@ _PyThread_CurrentFrames(void) } /* Python "auto thread state" API. */ -#ifdef WITH_THREAD /* Keep this as a static, as it is not reliable! It can only ever be compared to the state for the *current* thread. @@ -805,10 +782,8 @@ _PyGILState_Fini(void) void _PyGILState_Reinit(void) { -#ifdef WITH_THREAD head_mutex = NULL; HEAD_INIT(); -#endif PyThreadState *tstate = PyGILState_GetThisThreadState(); PyThread_delete_key(autoTLSkey); if ((autoTLSkey = PyThread_create_key()) == -1) @@ -960,10 +935,7 @@ PyGILState_Release(PyGILState_STATE oldstate) PyEval_SaveThread(); } -#endif /* WITH_THREAD */ #ifdef __cplusplus } #endif - - diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 852babb..fba7220 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -556,7 +556,6 @@ PyDoc_STRVAR(getcheckinterval_doc, "getcheckinterval() -> current check interval; see setcheckinterval()." ); -#ifdef WITH_THREAD static PyObject * sys_setswitchinterval(PyObject *self, PyObject *args) { @@ -594,8 +593,6 @@ PyDoc_STRVAR(getswitchinterval_doc, "getswitchinterval() -> current thread switch interval; see setswitchinterval()." ); -#endif /* WITH_THREAD */ - static PyObject * sys_setrecursionlimit(PyObject *self, PyObject *args) { @@ -1418,12 +1415,10 @@ static PyMethodDef sys_methods[] = { setcheckinterval_doc}, {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, getcheckinterval_doc}, -#ifdef WITH_THREAD {"setswitchinterval", sys_setswitchinterval, METH_VARARGS, setswitchinterval_doc}, {"getswitchinterval", sys_getswitchinterval, METH_NOARGS, getswitchinterval_doc}, -#endif #ifdef HAVE_DLOPEN {"setdlopenflags", sys_setdlopenflags, METH_VARARGS, setdlopenflags_doc}, @@ -2055,9 +2050,7 @@ _PySys_BeginInit(void) PyUnicode_FromString("legacy")); #endif -#ifdef WITH_THREAD SET_SYS_FROM_STRING("thread_info", PyThread_GetInfo()); -#endif /* initialize asyncgen_hooks */ if (AsyncGenHooksType.tp_name == NULL) { diff --git a/Python/traceback.c b/Python/traceback.c index b52385e..cd30d56 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -749,7 +749,6 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, PyThreadState *tstate; unsigned int nthreads; -#ifdef WITH_THREAD if (current_tstate == NULL) { /* _Py_DumpTracebackThreads() is called from signal handlers by faulthandler. @@ -777,21 +776,6 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, interp = current_tstate->interp; } } -#else - if (current_tstate == NULL) { - /* Call _PyThreadState_UncheckedGet() instead of PyThreadState_Get() - to not fail with a fatal error if the thread state is NULL. */ - current_tstate = _PyThreadState_UncheckedGet(); - } - - if (interp == NULL) { - if (current_tstate == NULL) { - /* We need the interpreter state to get Python threads */ - return "unable to get the interpreter state"; - } - interp = current_tstate->interp; - } -#endif assert(interp != NULL); /* Get the current interpreter from the current thread */ |