LCOV - code coverage report
Current view: | top level - Python - ceval_gil.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 159 | 365 | 43.6 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 23 | 47 | 48.9 %
|  |  | Branches: | 47 | 160 | 29.4 %

               Branch data     Line data    Source code
           1                 :            :
           2                 :            : #include "Python.h"
           3                 :            : #include "pycore_atomic.h"        // _Py_atomic_int
           4                 :            : #include "pycore_ceval.h"         // _PyEval_SignalReceived()
           5                 :            : #include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
           6                 :            : #include "pycore_pylifecycle.h"   // _PyErr_Print()
           7                 :            : #include "pycore_initconfig.h"    // _PyStatus_OK()
           8                 :            : #include "pycore_interp.h"        // _Py_RunGC()
           9                 :            : #include "pycore_pymem.h"         // _PyMem_IsPtrFreed()
          10                 :            :
          11                 :            : /*
          12                 :            :    Notes about the implementation:
          13                 :            :
          14                 :            :    - The GIL is just a boolean variable (locked) whose access is protected
          15                 :            :      by a mutex (gil_mutex), and whose changes are signalled by a condition
          16                 :            :      variable (gil_cond). gil_mutex is taken for short periods of time,
          17                 :            :      and therefore mostly uncontended.
          18                 :            :
          19                 :            :    - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
          20                 :            :      able to release the GIL on demand by another thread. A volatile boolean
          21                 :            :      variable (gil_drop_request) is used for that purpose, which is checked
          22                 :            :      at every turn of the eval loop. That variable is set after a wait of
          23                 :            :      `interval` microseconds on `gil_cond` has timed out.
          24                 :            :
          25                 :            :       [Actually, another volatile boolean variable (eval_breaker) is used
          26                 :            :        which ORs several conditions into one. Volatile booleans are
          27                 :            :        sufficient as inter-thread signalling means since Python is run
          28                 :            :        on cache-coherent architectures only.]
          29                 :            :
          30                 :            :    - A thread wanting to take the GIL will first let pass a given amount of
          31                 :            :      time (`interval` microseconds) before setting gil_drop_request. This
          32                 :            :      encourages a defined switching period, but doesn't enforce it since
          33                 :            :      opcodes can take an arbitrary time to execute.
          34                 :            :
          35                 :            :      The `interval` value is available for the user to read and modify
          36                 :            :      using the Python API `sys.{get,set}switchinterval()`.
          37                 :            :
          38                 :            :    - When a thread releases the GIL and gil_drop_request is set, that thread
          39                 :            :      ensures that another GIL-awaiting thread gets scheduled.
          40                 :            :      It does so by waiting on a condition variable (switch_cond) until
          41                 :            :      the value of last_holder is changed to something else than its
          42                 :            :      own thread state pointer, indicating that another thread was able to
          43                 :            :      take the GIL.
          44                 :            :
          45                 :            :      This is meant to prohibit the latency-adverse behaviour on multi-core
          46                 :            :      machines where one thread would speculatively release the GIL, but still
          47                 :            :      run and end up being the first to re-acquire it, making the "timeslices"
          48                 :            :      much longer than expected.
          49                 :            :      (Note: this mechanism is enabled with FORCE_SWITCHING above)
          50                 :            : */
          51                 :            :
          52                 :            : // GH-89279: Force inlining by using a macro.
          53                 :            : #if defined(_MSC_VER) && SIZEOF_INT == 4
          54                 :            : #define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) (assert(sizeof((ATOMIC_VAL)->_value) == 4), *((volatile int*)&((ATOMIC_VAL)->_value)))
          55                 :            : #else
          56                 :            : #define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL)
          57                 :            : #endif
          58                 :            :
          59                 :            : /* This can set eval_breaker to 0 even though gil_drop_request became
          60                 :            :    1.  We believe this is all right because the eval loop will release
          61                 :            :    the GIL eventually anyway. */
          62                 :            : static inline void
          63                 :      30818 : COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
          64                 :            :                      struct _ceval_runtime_state *ceval,
          65                 :            :                      struct _ceval_state *ceval2)
          66                 :            : {
          67   [ -  +  -  -  :      30818 :     _Py_atomic_store_relaxed(&ceval2->eval_breaker,
                 -  +  -  - ]
          68                 :            :         _Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)
          69                 :            :         | (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)
          70                 :            :            && _Py_ThreadCanHandleSignals(interp))
          71                 :            :         | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)
          72                 :            :            && _Py_ThreadCanHandlePendingCalls())
          73                 :            :         | ceval2->pending.async_exc
          74                 :            :         | _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled));
          75                 :      30818 : }
          76                 :            :
          77                 :            :
          78                 :            : static inline void
          79                 :          0 : SET_GIL_DROP_REQUEST(PyInterpreterState *interp)
          80                 :            : {
          81                 :          0 :     struct _ceval_state *ceval2 = &interp->ceval;
          82                 :          0 :     _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 1);
          83                 :          0 :     _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
          84                 :          0 : }
          85                 :            :
          86                 :            :
          87                 :            : static inline void
          88                 :          0 : RESET_GIL_DROP_REQUEST(PyInterpreterState *interp)
          89                 :            : {
          90                 :          0 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
          91                 :          0 :     struct _ceval_state *ceval2 = &interp->ceval;
          92                 :          0 :     _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 0);
          93                 :          0 :     COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
          94                 :          0 : }
          95                 :            :
          96                 :            :
          97                 :            : static inline void
          98                 :          0 : SIGNAL_PENDING_CALLS(PyInterpreterState *interp)
          99                 :            : {
         100                 :          0 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
         101                 :          0 :     struct _ceval_state *ceval2 = &interp->ceval;
         102                 :          0 :     _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);
         103                 :          0 :     COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
         104                 :          0 : }
         105                 :            :
         106                 :            :
         107                 :            : static inline void
         108                 :         22 : UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp)
         109                 :            : {
         110                 :         22 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
         111                 :         22 :     struct _ceval_state *ceval2 = &interp->ceval;
         112                 :         22 :     _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0);
         113                 :         22 :     COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
         114                 :         22 : }
         115                 :            :
         116                 :            :
         117                 :            : static inline void
         118                 :          0 : SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force)
         119                 :            : {
         120                 :          0 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
         121                 :          0 :     struct _ceval_state *ceval2 = &interp->ceval;
         122                 :          0 :     _Py_atomic_store_relaxed(&ceval->signals_pending, 1);
         123         [ #  # ]:          0 :     if (force) {
         124                 :          0 :         _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
         125                 :            :     }
         126                 :            :     else {
         127                 :            :         /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */
         128                 :          0 :         COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
         129                 :            :     }
         130                 :          0 : }
         131                 :            :
         132                 :            :
         133                 :            : static inline void
         134                 :         22 : UNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)
         135                 :            : {
         136                 :         22 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
         137                 :         22 :     struct _ceval_state *ceval2 = &interp->ceval;
         138                 :         22 :     _Py_atomic_store_relaxed(&ceval->signals_pending, 0);
         139                 :         22 :     COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
         140                 :         22 : }
         141                 :            :
         142                 :            :
         143                 :            : static inline void
         144                 :          0 : SIGNAL_ASYNC_EXC(PyInterpreterState *interp)
         145                 :            : {
         146                 :          0 :     struct _ceval_state *ceval2 = &interp->ceval;
         147                 :          0 :     ceval2->pending.async_exc = 1;
         148                 :          0 :     _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
         149                 :          0 : }
         150                 :            :
         151                 :            :
         152                 :            : static inline void
         153                 :          0 : UNSIGNAL_ASYNC_EXC(PyInterpreterState *interp)
         154                 :            : {
         155                 :          0 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
         156                 :          0 :     struct _ceval_state *ceval2 = &interp->ceval;
         157                 :          0 :     ceval2->pending.async_exc = 0;
         158                 :          0 :     COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
         159                 :          0 : }
         160                 :            :
         161                 :            : #ifndef NDEBUG
         162                 :            : /* Ensure that tstate is valid */
         163                 :            : static int
         164                 :            : is_tstate_valid(PyThreadState *tstate)
         165                 :            : {
         166                 :            :     assert(!_PyMem_IsPtrFreed(tstate));
         167                 :            :     assert(!_PyMem_IsPtrFreed(tstate->interp));
         168                 :            :     return 1;
         169                 :            : }
         170                 :            : #endif
         171                 :            :
         172                 :            : /*
         173                 :            :  * Implementation of the Global Interpreter Lock (GIL).
         174                 :            :  */
         175                 :            :
         176                 :            : #include <stdlib.h>
         177                 :            : #include <errno.h>
         178                 :            :
         179                 :            : #include "pycore_atomic.h"
         180                 :            :
         181                 :            :
         182                 :            : #include "condvar.h"
         183                 :            :
         184                 :            : #define MUTEX_INIT(mut) \
         185                 :            :     if (PyMUTEX_INIT(&(mut))) { \
         186                 :            :         Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); };
         187                 :            : #define MUTEX_FINI(mut) \
         188                 :            :     if (PyMUTEX_FINI(&(mut))) { \
         189                 :            :         Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); };
         190                 :            : #define MUTEX_LOCK(mut) \
         191                 :            :     if (PyMUTEX_LOCK(&(mut))) { \
         192                 :            :         Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); };
         193                 :            : #define MUTEX_UNLOCK(mut) \
         194                 :            :     if (PyMUTEX_UNLOCK(&(mut))) { \
         195                 :            :         Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); };
         196                 :            :
         197                 :            : #define COND_INIT(cond) \
         198                 :            :     if (PyCOND_INIT(&(cond))) { \
         199                 :            :         Py_FatalError("PyCOND_INIT(" #cond ") failed"); };
         200                 :            : #define COND_FINI(cond) \
         201                 :            :     if (PyCOND_FINI(&(cond))) { \
         202                 :            :         Py_FatalError("PyCOND_FINI(" #cond ") failed"); };
         203                 :            : #define COND_SIGNAL(cond) \
         204                 :            :     if (PyCOND_SIGNAL(&(cond))) { \
         205                 :            :         Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); };
         206                 :            : #define COND_WAIT(cond, mut) \
         207                 :            :     if (PyCOND_WAIT(&(cond), &(mut))) { \
         208                 :            :         Py_FatalError("PyCOND_WAIT(" #cond ") failed"); };
         209                 :            : #define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
         210                 :            :     { \
         211                 :            :         int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \
         212                 :            :         if (r < 0) \
         213                 :            :             Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \
         214                 :            :         if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \
         215                 :            :             timeout_result = 1; \
         216                 :            :         else \
         217                 :            :             timeout_result = 0; \
         218                 :            :     } \
         219                 :            :
         220                 :            :
         221                 :            : #define DEFAULT_INTERVAL 5000
         222                 :            :
         223                 :         29 : static void _gil_initialize(struct _gil_runtime_state *gil)
         224                 :            : {
         225                 :         29 :     _Py_atomic_int uninitialized = {-1};
         226                 :         29 :     gil->locked = uninitialized;
         227                 :         29 :     gil->interval = DEFAULT_INTERVAL;
         228                 :         29 : }
         229                 :            :
         230                 :         29 : static int gil_created(struct _gil_runtime_state *gil)
         231                 :            : {
         232                 :         29 :     return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0);
         233                 :            : }
         234                 :            :
         235                 :         29 : static void create_gil(struct _gil_runtime_state *gil)
         236                 :            : {
         237         [ -  + ]:         29 :     MUTEX_INIT(gil->mutex);
         238                 :            : #ifdef FORCE_SWITCHING
         239         [ -  + ]:         29 :     MUTEX_INIT(gil->switch_mutex);
         240                 :            : #endif
         241         [ -  + ]:         29 :     COND_INIT(gil->cond);
         242                 :            : #ifdef FORCE_SWITCHING
         243         [ -  + ]:         29 :     COND_INIT(gil->switch_cond);
         244                 :            : #endif
         245                 :         29 :     _Py_atomic_store_relaxed(&gil->last_holder, 0);
         246                 :            :     _Py_ANNOTATE_RWLOCK_CREATE(&gil->locked);
         247                 :         29 :     _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release);
         248                 :         29 : }
         249                 :            :
         250                 :          0 : static void destroy_gil(struct _gil_runtime_state *gil)
         251                 :            : {
         252                 :            :     /* some pthread-like implementations tie the mutex to the cond
         253                 :            :      * and must have the cond destroyed first.
         254                 :            :      */
         255         [ #  # ]:          0 :     COND_FINI(gil->cond);
         256         [ #  # ]:          0 :     MUTEX_FINI(gil->mutex);
         257                 :            : #ifdef FORCE_SWITCHING
         258         [ #  # ]:          0 :     COND_FINI(gil->switch_cond);
         259         [ #  # ]:          0 :     MUTEX_FINI(gil->switch_mutex);
         260                 :            : #endif
         261                 :          0 :     _Py_atomic_store_explicit(&gil->locked, -1,
         262                 :            :                               _Py_memory_order_release);
         263                 :            :     _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);
         264                 :          0 : }
         265                 :            :
         266                 :            : #ifdef HAVE_FORK
         267                 :          0 : static void recreate_gil(struct _gil_runtime_state *gil)
         268                 :            : {
         269                 :            :     _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);
         270                 :            :     /* XXX should we destroy the old OS resources here? */
         271                 :          0 :     create_gil(gil);
         272                 :          0 : }
         273                 :            : #endif
         274                 :            :
         275                 :            : static void
         276                 :      30151 : drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
         277                 :            :          PyThreadState *tstate)
         278                 :            : {
         279                 :      30151 :     struct _gil_runtime_state *gil = &ceval->gil;
         280         [ -  + ]:      30151 :     if (!_Py_atomic_load_relaxed(&gil->locked)) {
         281                 :          0 :         Py_FatalError("drop_gil: GIL is not locked");
         282                 :            :     }
         283                 :            :
         284                 :            :     /* tstate is allowed to be NULL (early interpreter init) */
         285         [ +  - ]:      30151 :     if (tstate != NULL) {
         286                 :            :         /* Sub-interpreter support: threads might have been switched
         287                 :            :            under our feet using PyThreadState_Swap(). Fix the GIL last
         288                 :            :            holder variable so that our heuristics work. */
         289                 :      30151 :         _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
         290                 :            :     }
         291                 :            :
         292         [ -  + ]:      30151 :     MUTEX_LOCK(gil->mutex);
         293                 :            :     _Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1);
         294                 :      30151 :     _Py_atomic_store_relaxed(&gil->locked, 0);
         295         [ -  + ]:      30151 :     COND_SIGNAL(gil->cond);
         296         [ -  + ]:      30151 :     MUTEX_UNLOCK(gil->mutex);
         297                 :            :
         298                 :            : #ifdef FORCE_SWITCHING
         299   [ -  +  -  - ]:      30151 :     if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) {
         300         [ #  # ]:          0 :         MUTEX_LOCK(gil->switch_mutex);
         301                 :            :         /* Not switched yet => wait */
         302         [ #  # ]:          0 :         if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate)
         303                 :            :         {
         304                 :            :             assert(is_tstate_valid(tstate));
         305                 :          0 :             RESET_GIL_DROP_REQUEST(tstate->interp);
         306                 :            :             /* NOTE: if COND_WAIT does not atomically start waiting when
         307                 :            :                releasing the mutex, another thread can run through, take
         308                 :            :                the GIL and drop it again, and reset the condition
         309                 :            :                before we even had a chance to wait for it. */
         310         [ #  # ]:          0 :             COND_WAIT(gil->switch_cond, gil->switch_mutex);
         311                 :            :         }
         312         [ #  # ]:          0 :         MUTEX_UNLOCK(gil->switch_mutex);
         313                 :            :     }
         314                 :            : #endif
         315                 :      30151 : }
         316                 :            :
         317                 :            :
         318                 :            : /* Check if a Python thread must exit immediately, rather than taking the GIL
         319                 :            :    if Py_Finalize() has been called.
         320                 :            :
         321                 :            :    When this function is called by a daemon thread after Py_Finalize() has been
         322                 :            :    called, the GIL does no longer exist.
         323                 :            :
         324                 :            :    tstate must be non-NULL. */
         325                 :            : static inline int
         326                 :      60360 : tstate_must_exit(PyThreadState *tstate)
         327                 :            : {
         328                 :            :     /* bpo-39877: Access _PyRuntime directly rather than using
         329                 :            :        tstate->interp->runtime to support calls from Python daemon threads.
         330                 :            :        After Py_Finalize() has been called, tstate can be a dangling pointer:
         331                 :            :        point to PyThreadState freed memory. */
         332                 :      60360 :     PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime);
         333   [ +  +  -  + ]:      60360 :     return (finalizing != NULL && finalizing != tstate);
         334                 :            : }
         335                 :            :
         336                 :            :
         337                 :            : /* Take the GIL.
         338                 :            :
         339                 :            :    The function saves errno at entry and restores its value at exit.
         340                 :            :
         341                 :            :    tstate must be non-NULL. */
         342                 :            : static void
         343                 :      30180 : take_gil(PyThreadState *tstate)
         344                 :            : {
         345                 :      30180 :     int err = errno;
         346                 :            :
         347                 :            :     assert(tstate != NULL);
         348                 :            :
         349         [ -  + ]:      30180 :     if (tstate_must_exit(tstate)) {
         350                 :            :         /* bpo-39877: If Py_Finalize() has been called and tstate is not the
         351                 :            :            thread which called Py_Finalize(), exit immediately the thread.
         352                 :            :
         353                 :            :            This code path can be reached by a daemon thread after Py_Finalize()
         354                 :            :            completes. In this case, tstate is a dangling pointer: points to
         355                 :            :            PyThreadState freed memory. */
         356                 :          0 :         PyThread_exit_thread();
         357                 :            :     }
         358                 :            :
         359                 :            :     assert(is_tstate_valid(tstate));
         360                 :      30180 :     PyInterpreterState *interp = tstate->interp;
         361                 :      30180 :     struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
         362                 :      30180 :     struct _ceval_state *ceval2 = &interp->ceval;
         363                 :      30180 :     struct _gil_runtime_state *gil = &ceval->gil;
         364                 :            :
         365                 :            :     /* Check that _PyEval_InitThreads() was called to create the lock */
         366                 :            :     assert(gil_created(gil));
         367                 :            :
         368         [ -  + ]:      30180 :     MUTEX_LOCK(gil->mutex);
         369                 :            :
         370         [ +  - ]:      30180 :     if (!_Py_atomic_load_relaxed(&gil->locked)) {
         371                 :      30180 :         goto _ready;
         372                 :            :     }
         373                 :            :
         374                 :          0 :     int drop_requested = 0;
         375         [ #  # ]:          0 :     while (_Py_atomic_load_relaxed(&gil->locked)) {
         376                 :          0 :         unsigned long saved_switchnum = gil->switch_number;
         377                 :            :
         378         [ #  # ]:          0 :         unsigned long interval = (gil->interval >= 1 ? gil->interval : 1);
         379                 :          0 :         int timed_out = 0;
         380   [ #  #  #  # ]:          0 :         COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out);
         381                 :            :
         382                 :            :         /* If we timed out and no switch occurred in the meantime, it is time
         383                 :            :            to ask the GIL-holding thread to drop it. */
         384         [ #  # ]:          0 :         if (timed_out &&
         385         [ #  # ]:          0 :             _Py_atomic_load_relaxed(&gil->locked) &&
         386         [ #  # ]:          0 :             gil->switch_number == saved_switchnum)
         387                 :            :         {
         388         [ #  # ]:          0 :             if (tstate_must_exit(tstate)) {
         389         [ #  # ]:          0 :                 MUTEX_UNLOCK(gil->mutex);
         390                 :            :                 // gh-96387: If the loop requested a drop request in a previous
         391                 :            :                 // iteration, reset the request. Otherwise, drop_gil() can
         392                 :            :                 // block forever waiting for the thread which exited. Drop
         393                 :            :                 // requests made by other threads are also reset: these threads
         394                 :            :                 // may have to request again a drop request (iterate one more
         395                 :            :                 // time).
         396         [ #  # ]:          0 :                 if (drop_requested) {
         397                 :          0 :                     RESET_GIL_DROP_REQUEST(interp);
         398                 :            :                 }
         399                 :          0 :                 PyThread_exit_thread();
         400                 :            :             }
         401                 :            :             assert(is_tstate_valid(tstate));
         402                 :            :
         403                 :          0 :             SET_GIL_DROP_REQUEST(interp);
         404                 :          0 :             drop_requested = 1;
         405                 :            :         }
         406                 :            :     }
         407                 :            :
         408                 :          0 : _ready:
         409                 :            : #ifdef FORCE_SWITCHING
         410                 :            :     /* This mutex must be taken before modifying gil->last_holder:
         411                 :            :        see drop_gil(). */
         412         [ -  + ]:      30180 :     MUTEX_LOCK(gil->switch_mutex);
         413                 :            : #endif
         414                 :            :     /* We now hold the GIL */
         415                 :      30180 :     _Py_atomic_store_relaxed(&gil->locked, 1);
         416                 :            :     _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil->locked, /*is_write=*/1);
         417                 :            :
         418         [ +  + ]:      30180 :     if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) {
         419                 :         29 :         _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
         420                 :         29 :         ++gil->switch_number;
         421                 :            :     }
         422                 :            :
         423                 :            : #ifdef FORCE_SWITCHING
         424         [ -  + ]:      30180 :     COND_SIGNAL(gil->switch_cond);
         425         [ -  + ]:      30180 :     MUTEX_UNLOCK(gil->switch_mutex);
         426                 :            : #endif
         427                 :            :
         428         [ -  + ]:      30180 :     if (tstate_must_exit(tstate)) {
         429                 :            :         /* bpo-36475: If Py_Finalize() has been called and tstate is not
         430                 :            :            the thread which called Py_Finalize(), exit immediately the
         431                 :            :            thread.
         432                 :            :
         433                 :            :            This code path can be reached by a daemon thread which was waiting
         434                 :            :            in take_gil() while the main thread called
         435                 :            :            wait_for_thread_shutdown() from Py_Finalize(). */
         436         [ #  # ]:          0 :         MUTEX_UNLOCK(gil->mutex);
         437                 :          0 :         drop_gil(ceval, ceval2, tstate);
         438                 :          0 :         PyThread_exit_thread();
         439                 :            :     }
         440                 :            :     assert(is_tstate_valid(tstate));
         441                 :            :
         442         [ -  + ]:      30180 :     if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) {
         443                 :          0 :         RESET_GIL_DROP_REQUEST(interp);
         444                 :            :     }
         445                 :            :     else {
         446                 :            :         /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there
         447                 :            :            is a pending signal: signal received by another thread which cannot
         448                 :            :            handle signals.
         449                 :            :
         450                 :            :            Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */
         451                 :      30180 :         COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
         452                 :            :     }
         453                 :            :
         454                 :            :     /* Don't access tstate if the thread must exit */
         455         [ -  + ]:      30180 :     if (tstate->async_exc != NULL) {
         456                 :          0 :         _PyEval_SignalAsyncExc(tstate->interp);
         457                 :            :     }
         458                 :            :
         459         [ -  + ]:      30180 :     MUTEX_UNLOCK(gil->mutex);
         460                 :            :
         461                 :      30180 :     errno = err;
         462                 :      30180 : }
         463                 :            :
         464                 :          0 : void _PyEval_SetSwitchInterval(unsigned long microseconds)
         465                 :            : {
         466                 :          0 :     struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
         467                 :          0 :     gil->interval = microseconds;
         468                 :          0 : }
         469                 :            :
         470                 :          0 : unsigned long _PyEval_GetSwitchInterval()
         471                 :            : {
         472                 :          0 :     struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
         473                 :          0 :     return gil->interval;
         474                 :            : }
         475                 :            :
         476                 :            :
         477                 :            : int
         478                 :          0 : _PyEval_ThreadsInitialized(_PyRuntimeState *runtime)
         479                 :            : {
         480                 :          0 :     return gil_created(&runtime->ceval.gil);
         481                 :            : }
         482                 :            :
         483                 :            : int
         484                 :          0 : PyEval_ThreadsInitialized(void)
         485                 :            : {
         486                 :          0 :     _PyRuntimeState *runtime = &_PyRuntime;
         487                 :          0 :     return _PyEval_ThreadsInitialized(runtime);
         488                 :            : }
         489                 :            :
         490                 :            : PyStatus
         491                 :         29 : _PyEval_InitGIL(PyThreadState *tstate)
         492                 :            : {
         493         [ -  + ]:         29 :     if (!_Py_IsMainInterpreter(tstate->interp)) {
         494                 :            :         /* Currently, the GIL is shared by all interpreters,
         495                 :            :            and only the main interpreter is responsible to create
         496                 :            :            and destroy it. */
         497                 :          0 :         return _PyStatus_OK();
         498                 :            :     }
         499                 :            :
         500                 :         29 :     struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
         501                 :            :     assert(!gil_created(gil));
         502                 :            :
         503                 :         29 :     PyThread_init_thread();
         504                 :         29 :     create_gil(gil);
         505                 :            :
         506                 :         29 :     take_gil(tstate);
         507                 :            :
         508                 :            :     assert(gil_created(gil));
         509                 :         29 :     return _PyStatus_OK();
         510                 :            : }
         511                 :            :
         512                 :            : void
         513                 :         29 : _PyEval_FiniGIL(PyInterpreterState *interp)
         514                 :            : {
         515         [ -  + ]:         29 :     if (!_Py_IsMainInterpreter(interp)) {
         516                 :            :         /* Currently, the GIL is shared by all interpreters,
         517                 :            :            and only the main interpreter is responsible to create
         518                 :            :            and destroy it. */
         519                 :          0 :         return;
         520                 :            :     }
         521                 :            :
         522                 :         29 :     struct _gil_runtime_state *gil = &interp->runtime->ceval.gil;
         523         [ +  - ]:         29 :     if (!gil_created(gil)) {
         524                 :            :         /* First Py_InitializeFromConfig() call: the GIL doesn't exist
         525                 :            :            yet: do nothing. */
         526                 :         29 :         return;
         527                 :            :     }
         528                 :            :
         529                 :          0 :     destroy_gil(gil);
         530                 :            :     assert(!gil_created(gil));
         531                 :            : }
         532                 :            :
         533                 :            : void
         534                 :          0 : PyEval_InitThreads(void)
         535                 :            : {
         536                 :            :     /* Do nothing: kept for backward compatibility */
         537                 :          0 : }
         538                 :            :
         539                 :            : void
         540                 :         25 : _PyEval_Fini(void)
         541                 :            : {
         542                 :            : #ifdef Py_STATS
         543                 :            :     _Py_PrintSpecializationStats(1);
         544                 :            : #endif
         545                 :         25 : }
         546                 :            : void
         547                 :          0 : PyEval_AcquireLock(void)
         548                 :            : {
         549                 :          0 :     _PyRuntimeState *runtime = &_PyRuntime;
         550                 :          0 :     PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
         551                 :          0 :     _Py_EnsureTstateNotNULL(tstate);
         552                 :            :
         553                 :          0 :     take_gil(tstate);
         554                 :          0 : }
         555                 :            :
         556                 :            : void
         557                 :          0 : PyEval_ReleaseLock(void)
         558                 :            : {
         559                 :          0 :     _PyRuntimeState *runtime = &_PyRuntime;
         560                 :          0 :     PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
         561                 :            :     /* This function must succeed when the current thread state is NULL.
         562                 :            :        We therefore avoid PyThreadState_Get() which dumps a fatal error
         563                 :            :        in debug mode. */
         564                 :          0 :     struct _ceval_runtime_state *ceval = &runtime->ceval;
         565                 :          0 :     struct _ceval_state *ceval2 = &tstate->interp->ceval;
         566                 :          0 :     drop_gil(ceval, ceval2, tstate);
         567                 :          0 : }
         568                 :            :
         569                 :            : void
         570                 :          0 : _PyEval_ReleaseLock(PyThreadState *tstate)
         571                 :            : {
         572                 :          0 :     struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
         573                 :          0 :     struct _ceval_state *ceval2 = &tstate->interp->ceval;
         574                 :          0 :     drop_gil(ceval, ceval2, tstate);
         575                 :          0 : }
         576                 :            :
         577                 :            : void
         578                 :          0 : PyEval_AcquireThread(PyThreadState *tstate)
         579                 :            : {
         580                 :          0 :     _Py_EnsureTstateNotNULL(tstate);
         581                 :            :
         582                 :          0 :     take_gil(tstate);
         583                 :            :
         584         [ #  # ]:          0 :     if (_PyThreadState_Swap(tstate->interp->runtime, tstate) != NULL) {
         585                 :          0 :         Py_FatalError("non-NULL old thread state");
         586                 :            :     }
         587                 :          0 : }
         588                 :            :
         589                 :            : void
         590                 :          0 : PyEval_ReleaseThread(PyThreadState *tstate)
         591                 :            : {
         592                 :            :     assert(is_tstate_valid(tstate));
         593                 :            :
         594                 :          0 :     _PyRuntimeState *runtime = tstate->interp->runtime;
         595                 :          0 :     PyThreadState *new_tstate = _PyThreadState_Swap(runtime, NULL);
         596         [ #  # ]:          0 :     if (new_tstate != tstate) {
         597                 :          0 :         Py_FatalError("wrong thread state");
         598                 :            :     }
         599                 :          0 :     struct _ceval_runtime_state *ceval = &runtime->ceval;
         600                 :          0 :     struct _ceval_state *ceval2 = &tstate->interp->ceval;
         601                 :          0 :     drop_gil(ceval, ceval2, tstate);
         602                 :          0 : }
         603                 :            :
         604                 :            : #ifdef HAVE_FORK
         605                 :            : /* This function is called from PyOS_AfterFork_Child to destroy all threads
         606                 :            :    which are not running in the child process, and clear internal locks
         607                 :            :    which might be held by those threads. */
         608                 :            : PyStatus
         609                 :          0 : _PyEval_ReInitThreads(PyThreadState *tstate)
         610                 :            : {
         611                 :          0 :     _PyRuntimeState *runtime = tstate->interp->runtime;
         612                 :            :
         613                 :          0 :     struct _gil_runtime_state *gil = &runtime->ceval.gil;
         614         [ #  # ]:          0 :     if (!gil_created(gil)) {
         615                 :          0 :         return _PyStatus_OK();
         616                 :            :     }
         617                 :          0 :     recreate_gil(gil);
         618                 :            :
         619                 :          0 :     take_gil(tstate);
         620                 :            :
         621                 :          0 :     struct _pending_calls *pending = &tstate->interp->ceval.pending;
         622         [ #  # ]:          0 :     if (_PyThread_at_fork_reinit(&pending->lock) < 0) {
         623                 :          0 :         return _PyStatus_ERR("Can't reinitialize pending calls lock");
         624                 :            :     }
         625                 :            :
         626                 :            :     /* Destroy all threads except the current one */
         627                 :          0 :     _PyThreadState_DeleteExcept(tstate);
         628                 :          0 :     return _PyStatus_OK();
         629                 :            : }
         630                 :            : #endif
         631                 :            :
         632                 :            : /* This function is used to signal that async exceptions are waiting to be
         633                 :            :    raised. */
         634                 :            :
         635                 :            : void
         636                 :          0 : _PyEval_SignalAsyncExc(PyInterpreterState *interp)
         637                 :            : {
         638                 :          0 :     SIGNAL_ASYNC_EXC(interp);
         639                 :          0 : }
         640                 :            :
         641                 :            : PyThreadState *
         642                 :      30151 : PyEval_SaveThread(void)
         643                 :            : {
         644                 :      30151 :     _PyRuntimeState *runtime = &_PyRuntime;
         645                 :      30151 :     PyThreadState *tstate = _PyThreadState_Swap(runtime, NULL);
         646                 :      30151 :     _Py_EnsureTstateNotNULL(tstate);
         647                 :            :
         648                 :      30151 :     struct _ceval_runtime_state *ceval = &runtime->ceval;
         649                 :      30151 :     struct _ceval_state *ceval2 = &tstate->interp->ceval;
         650                 :            :     assert(gil_created(&ceval->gil));
         651                 :      30151 :     drop_gil(ceval, ceval2, tstate);
         652                 :      30151 :     return tstate;
         653                 :            : }
         654                 :            :
         655                 :            : void
         656                 :      30151 : PyEval_RestoreThread(PyThreadState *tstate)
         657                 :            : {
         658                 :      30151 :     _Py_EnsureTstateNotNULL(tstate);
         659                 :            :
         660                 :      30151 :     take_gil(tstate);
         661                 :            :
         662                 :      30151 :     _PyThreadState_Swap(tstate->interp->runtime, tstate);
         663                 :      30151 : }
         664                 :            :
         665                 :            :
         666                 :            : /* Mechanism whereby asynchronously executing callbacks (e.g. UNIX
         667                 :            :    signal handlers or Mac I/O completion routines) can schedule calls
         668                 :            :    to a function to be called synchronously.
         669                 :            :    The synchronous function is called with one void* argument.
         670                 :            :    It should return 0 for success or -1 for failure -- failure should
         671                 :            :    be accompanied by an exception.
         672                 :            :
         673                 :            :    If registry succeeds, the registry function returns 0; if it fails
         674                 :            :    (e.g. due to too many pending calls) it returns -1 (without setting
         675                 :            :    an exception condition).
         676                 :            :
         677                 :            :    Note that because registry may occur from within signal handlers,
         678                 :            :    or other asynchronous events, calling malloc() is unsafe!
         679                 :            :
         680                 :            :    Any thread can schedule pending calls, but only the main thread
         681                 :            :    will execute them.
         682                 :            :    There is no facility to schedule calls to a particular thread, but
         683                 :            :    that should be easy to change, should that ever be required.  In
         684                 :            :    that case, the static variables here should go into the python
         685                 :            :    threadstate.
         686                 :            : */
         687                 :            :
         688                 :            : void
         689                 :          0 : _PyEval_SignalReceived(PyInterpreterState *interp)
         690                 :            : {
         691                 :            : #ifdef MS_WINDOWS
         692                 :            :     // bpo-42296: On Windows, _PyEval_SignalReceived() is called from a signal
         693                 :            :     // handler which can run in a thread different than the Python thread, in
         694                 :            :     // which case _Py_ThreadCanHandleSignals() is wrong. Ignore
         695                 :            :     // _Py_ThreadCanHandleSignals() and always set eval_breaker to 1.
         696                 :            :     //
         697                 :            :     // The next eval_frame_handle_pending() call will call
         698                 :            :     // _Py_ThreadCanHandleSignals() to recompute eval_breaker.
         699                 :            :     int force = 1;
         700                 :            : #else
         701                 :          0 :     int force = 0;
         702                 :            : #endif
         703                 :            :     /* bpo-30703: Function called when the C signal handler of Python gets a
         704                 :            :        signal. We cannot queue a callback using _PyEval_AddPendingCall() since
         705                 :            :        that function is not async-signal-safe. */
         706                 :          0 :     SIGNAL_PENDING_SIGNALS(interp, force);
         707                 :          0 : }
         708                 :            :
         709                 :            : /* Push one item onto the queue while holding the lock. */
         710                 :            : static int
         711                 :          0 : _push_pending_call(struct _pending_calls *pending,
         712                 :            :                    int (*func)(void *), void *arg)
         713                 :            : {
         714                 :          0 :     int i = pending->last;
         715                 :          0 :     int j = (i + 1) % NPENDINGCALLS;
         716         [ #  # ]:          0 :     if (j == pending->first) {
         717                 :          0 :         return -1; /* Queue full */
         718                 :            :     }
         719                 :          0 :     pending->calls[i].func = func;
         720                 :          0 :     pending->calls[i].arg = arg;
         721                 :          0 :     pending->last = j;
         722                 :          0 :     return 0;
         723                 :            : }
         724                 :            :
         725                 :            : /* Pop one item off the queue while holding the lock. */
         726                 :            : static void
         727                 :         22 : _pop_pending_call(struct _pending_calls *pending,
         728                 :            :                   int (**func)(void *), void **arg)
         729                 :            : {
         730                 :         22 :     int i = pending->first;
         731         [ +  - ]:         22 :     if (i == pending->last) {
         732                 :         22 :         return; /* Queue empty */
         733                 :            :     }
         734                 :            :
         735                 :          0 :     *func = pending->calls[i].func;
         736                 :          0 :     *arg = pending->calls[i].arg;
         737                 :          0 :     pending->first = (i + 1) % NPENDINGCALLS;
         738                 :            : }
         739                 :            :
         740                 :            : /* This implementation is thread-safe.  It allows
         741                 :            :    scheduling to be made from any thread, and even from an executing
         742                 :            :    callback.
         743                 :            :  */
         744                 :            :
         745                 :            : int
         746                 :          0 : _PyEval_AddPendingCall(PyInterpreterState *interp,
         747                 :            :                        int (*func)(void *), void *arg)
         748                 :            : {
         749                 :          0 :     struct _pending_calls *pending = &interp->ceval.pending;
         750                 :            :     /* Ensure that _PyEval_InitState() was called
         751                 :            :        and that _PyEval_FiniState() is not called yet. */
         752                 :            :     assert(pending->lock != NULL);
         753                 :            :
         754                 :          0 :     PyThread_acquire_lock(pending->lock, WAIT_LOCK);
         755                 :          0 :     int result = _push_pending_call(pending, func, arg);
         756                 :          0 :     PyThread_release_lock(pending->lock);
         757                 :            :
         758                 :            :     /* signal main loop */
         759                 :          0 :     SIGNAL_PENDING_CALLS(interp);
         760                 :          0 :     return result;
         761                 :            : }
         762                 :            :
         763                 :            : int
         764                 :          0 : Py_AddPendingCall(int (*func)(void *), void *arg)
         765                 :            : {
         766                 :            :     /* Best-effort to support subinterpreters and calls with the GIL released.
         767                 :            :
         768                 :            :        First attempt _PyThreadState_GET() since it supports subinterpreters.
         769                 :            :
         770                 :            :        If the GIL is released, _PyThreadState_GET() returns NULL . In this
         771                 :            :        case, use PyGILState_GetThisThreadState() which works even if the GIL
         772                 :            :        is released.
         773                 :            :
         774                 :            :        Sadly, PyGILState_GetThisThreadState() doesn't support subinterpreters:
         775                 :            :        see bpo-10915 and bpo-15751.
         776                 :            :
         777                 :            :        Py_AddPendingCall() doesn't require the caller to hold the GIL. */
         778                 :          0 :     PyThreadState *tstate = _PyThreadState_GET();
         779         [ #  # ]:          0 :     if (tstate == NULL) {
         780                 :          0 :         tstate = PyGILState_GetThisThreadState();
         781                 :            :     }
         782                 :            :
         783                 :            :     PyInterpreterState *interp;
         784         [ #  # ]:          0 :     if (tstate != NULL) {
         785                 :          0 :         interp = tstate->interp;
         786                 :            :     }
         787                 :            :     else {
         788                 :            :         /* Last resort: use the main interpreter */
         789                 :          0 :         interp = _PyInterpreterState_Main();
         790                 :            :     }
         791                 :          0 :     return _PyEval_AddPendingCall(interp, func, arg);
         792                 :            : }
         793                 :            :
         794                 :            : static int
         795                 :         22 : handle_signals(PyThreadState *tstate)
         796                 :            : {
         797                 :            :     assert(is_tstate_valid(tstate));
         798         [ -  + ]:         22 :     if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
         799                 :          0 :         return 0;
         800                 :            :     }
         801                 :            :
         802                 :         22 :     UNSIGNAL_PENDING_SIGNALS(tstate->interp);
         803         [ -  + ]:         22 :     if (_PyErr_CheckSignalsTstate(tstate) < 0) {
         804                 :            :         /* On failure, re-schedule a call to handle_signals(). */
         805                 :          0 :         SIGNAL_PENDING_SIGNALS(tstate->interp, 0);
         806                 :          0 :         return -1;
         807                 :            :     }
         808                 :         22 :     return 0;
         809                 :            : }
         810                 :            :
         811                 :            : static int
         812                 :         22 : make_pending_calls(PyInterpreterState *interp)
         813                 :            : {
         814                 :            :     /* only execute pending calls on main thread */
         815         [ -  + ]:         22 :     if (!_Py_ThreadCanHandlePendingCalls()) {
         816                 :          0 :         return 0;
         817                 :            :     }
         818                 :            :
         819                 :            :     /* don't perform recursive pending calls */
         820         [ -  + ]:         22 :     if (interp->ceval.pending.busy) {
         821                 :          0 :         return 0;
         822                 :            :     }
         823                 :         22 :     interp->ceval.pending.busy = 1;
         824                 :            :
         825                 :            :     /* unsignal before starting to call callbacks, so that any callback
         826                 :            :        added in-between re-signals */
         827                 :         22 :     UNSIGNAL_PENDING_CALLS(interp);
         828                 :         22 :     int res = 0;
         829                 :            :
         830                 :            :     /* perform a bounded number of calls, in case of recursion */
         831                 :         22 :     struct _pending_calls *pending = &interp->ceval.pending;
         832         [ +  - ]:         22 :     for (int i=0; i<NPENDINGCALLS; i++) {
         833                 :         22 :         int (*func)(void *) = NULL;
         834                 :         22 :         void *arg = NULL;
         835                 :            :
         836                 :            :         /* pop one item off the queue while holding the lock */
         837                 :         22 :         PyThread_acquire_lock(pending->lock, WAIT_LOCK);
         838                 :         22 :         _pop_pending_call(pending, &func, &arg);
         839                 :         22 :         PyThread_release_lock(pending->lock);
         840                 :            :
         841                 :            :         /* having released the lock, perform the callback */
         842         [ +  - ]:         22 :         if (func == NULL) {
         843                 :         22 :             break;
         844                 :            :         }
         845                 :          0 :         res = func(arg);
         846         [ #  # ]:          0 :         if (res) {
         847                 :          0 :             goto error;
         848                 :            :         }
         849                 :            :     }
         850                 :            :
         851                 :         22 :     interp->ceval.pending.busy = 0;
         852                 :         22 :     return res;
         853                 :            :
         854                 :          0 : error:
         855                 :          0 :     interp->ceval.pending.busy = 0;
         856                 :          0 :     SIGNAL_PENDING_CALLS(interp);
         857                 :          0 :     return res;
         858                 :            : }
         859                 :            :
         860                 :            : void
         861                 :         25 : _Py_FinishPendingCalls(PyThreadState *tstate)
         862                 :            : {
         863                 :            :     assert(PyGILState_Check());
         864                 :            :     assert(is_tstate_valid(tstate));
         865                 :            :
         866                 :         25 :     struct _pending_calls *pending = &tstate->interp->ceval.pending;
         867                 :            :
         868         [ +  - ]:         25 :     if (!_Py_atomic_load_relaxed_int32(&(pending->calls_to_do))) {
         869                 :         25 :         return;
         870                 :            :     }
         871                 :            :
         872         [ #  # ]:          0 :     if (make_pending_calls(tstate->interp) < 0) {
         873                 :          0 :         PyObject *exc = _PyErr_GetRaisedException(tstate);
         874                 :          0 :         PyErr_BadInternalCall();
         875                 :          0 :         _PyErr_ChainExceptions1(exc);
         876                 :          0 :         _PyErr_Print(tstate);
         877                 :            :     }
         878                 :            : }
         879                 :            :
         880                 :            : /* Py_MakePendingCalls() is a simple wrapper for the sake
         881                 :            :    of backward-compatibility. */
         882                 :            : int
         883                 :         22 : Py_MakePendingCalls(void)
         884                 :            : {
         885                 :            :     assert(PyGILState_Check());
         886                 :            :
         887                 :         22 :     PyThreadState *tstate = _PyThreadState_GET();
         888                 :            :     assert(is_tstate_valid(tstate));
         889                 :            :
         890                 :            :     /* Python signal handler doesn't really queue a callback: it only signals
         891                 :            :        that a signal was received, see _PyEval_SignalReceived(). */
         892                 :         22 :     int res = handle_signals(tstate);
         893         [ -  + ]:         22 :     if (res != 0) {
         894                 :          0 :         return res;
         895                 :            :     }
         896                 :            :
         897                 :         22 :     res = make_pending_calls(tstate->interp);
         898         [ -  + ]:         22 :     if (res != 0) {
         899                 :          0 :         return res;
         900                 :            :     }
         901                 :            :
         902                 :         22 :     return 0;
         903                 :            : }
         904                 :            :
         905                 :            : /* The interpreter's recursion limit */
         906                 :            :
         907                 :            : void
         908                 :         29 : _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
         909                 :            : {
         910                 :         29 :     _gil_initialize(&ceval->gil);
         911                 :         29 : }
         912                 :            :
         913                 :            : void
         914                 :         29 : _PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock)
         915                 :            : {
         916                 :         29 :     struct _pending_calls *pending = &ceval->pending;
         917                 :            :     assert(pending->lock == NULL);
         918                 :            :
         919                 :         29 :     pending->lock = pending_lock;
         920                 :         29 : }
         921                 :            :
         922                 :            : void
         923                 :         25 : _PyEval_FiniState(struct _ceval_state *ceval)
         924                 :            : {
         925                 :         25 :     struct _pending_calls *pending = &ceval->pending;
         926         [ +  - ]:         25 :     if (pending->lock != NULL) {
         927                 :         25 :         PyThread_free_lock(pending->lock);
         928                 :         25 :         pending->lock = NULL;
         929                 :            :     }
         930                 :         25 : }
         931                 :            :
         932                 :            : /* Handle signals, pending calls, GIL drop request
         933                 :            :    and asynchronous exception */
         934                 :            : int
         935                 :        298 : _Py_HandlePending(PyThreadState *tstate)
         936                 :            : {
         937                 :        298 :     _PyRuntimeState * const runtime = &_PyRuntime;
         938                 :        298 :     struct _ceval_runtime_state *ceval = &runtime->ceval;
         939                 :        298 :     struct _ceval_state *interp_ceval_state = &tstate->interp->ceval;
         940                 :            :
         941                 :            :     /* Pending signals */
         942         [ -  + ]:        298 :     if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) {
         943         [ #  # ]:          0 :         if (handle_signals(tstate) != 0) {
         944                 :          0 :             return -1;
         945                 :            :         }
         946                 :            :     }
         947                 :            :
         948                 :            :     /* Pending calls */
         949         [ -  + ]:        298 :     if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->pending.calls_to_do)) {
         950         [ #  # ]:          0 :         if (make_pending_calls(tstate->interp) != 0) {
         951                 :          0 :             return -1;
         952                 :            :         }
         953                 :            :     }
         954                 :            :
         955                 :            :     /* GC scheduled to run */
         956         [ +  + ]:        298 :     if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gc_scheduled)) {
         957                 :        296 :         _Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0);
         958                 :        296 :         COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);
         959                 :        296 :         _Py_RunGC(tstate);
         960                 :            :     }
         961                 :            :
         962                 :            :     /* GIL drop request */
         963         [ -  + ]:        298 :     if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gil_drop_request)) {
         964                 :            :         /* Give another thread a chance */
         965         [ #  # ]:          0 :         if (_PyThreadState_Swap(runtime, NULL) != tstate) {
         966                 :          0 :             Py_FatalError("tstate mix-up");
         967                 :            :         }
         968                 :          0 :         drop_gil(ceval, interp_ceval_state, tstate);
         969                 :            :
         970                 :            :         /* Other threads may run now */
         971                 :            :
         972                 :          0 :         take_gil(tstate);
         973                 :            :
         974         [ #  # ]:          0 :         if (_PyThreadState_Swap(runtime, tstate) != NULL) {
         975                 :          0 :             Py_FatalError("orphan tstate");
         976                 :            :         }
         977                 :            :     }
         978                 :            :
         979                 :            :     /* Check for asynchronous exception. */
         980         [ -  + ]:        298 :     if (tstate->async_exc != NULL) {
         981                 :          0 :         PyObject *exc = tstate->async_exc;
         982                 :          0 :         tstate->async_exc = NULL;
         983                 :          0 :         UNSIGNAL_ASYNC_EXC(tstate->interp);
         984                 :          0 :         _PyErr_SetNone(tstate, exc);
         985                 :          0 :         Py_DECREF(exc);
         986                 :          0 :         return -1;
         987                 :            :     }
         988                 :            :
         989                 :            :
         990                 :            :     // It is possible that some of the conditions that trigger the eval breaker
         991                 :            :     // are called in a different thread than the Python thread. An example of
         992                 :            :     // this is bpo-42296: On Windows, _PyEval_SignalReceived() can be called in
         993                 :            :     // a different thread than the Python thread, in which case
         994                 :            :     // _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the
         995                 :            :     // current Python thread with the correct _Py_ThreadCanHandleSignals()
         996                 :            :     // value. It prevents to interrupt the eval loop at every instruction if
         997                 :            :     // the current Python thread cannot handle signals (if
         998                 :            :     // _Py_ThreadCanHandleSignals() is false).
         999                 :        298 :     COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);
        1000                 :            :
        1001                 :        298 :     return 0;
        1002                 :            : }
        1003                 :            :

Generated by: LCOV version 1.14