CINXE.COM

C API Extension Support for Free Threading — Python 3.13.2 documentation

<!DOCTYPE html> <html lang="en" data-content_root="../"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" /> <meta property="og:title" content="C API Extension Support for Free Threading" /> <meta property="og:type" content="website" /> <meta property="og:url" content="https://docs.python.org/3/howto/free-threading-extensions.html" /> <meta property="og:site_name" content="Python documentation" /> <meta property="og:description" content="Starting with the 3.13 release, CPython has experimental support for running with the global interpreter lock(GIL) disabled in a configuration called free threading. This document describes how to ..." /> <meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" /> <meta property="og:image:alt" content="Python documentation" /> <meta name="description" content="Starting with the 3.13 release, CPython has experimental support for running with the global interpreter lock(GIL) disabled in a configuration called free threading. This document describes how to ..." /> <meta property="og:image:width" content="200" /> <meta property="og:image:height" content="200" /> <meta name="theme-color" content="#3776ab" /> <title>C API Extension Support for Free Threading &#8212; Python 3.13.2 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" /> <link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?v=23252803" /> <link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" /> <script src="../_static/documentation_options.js?v=f92f4e34"></script> <script src="../_static/doctools.js?v=9bcbadda"></script> <script src="../_static/sphinx_highlight.js?v=dc90522c"></script> <script src="../_static/sidebar.js"></script> <link rel="search" type="application/opensearchdescription+xml" title="Search within Python 3.13.2 documentation" href="../_static/opensearch.xml"/> <link rel="author" title="About these documents" href="../about.html" /> <link rel="index" title="Index" href="../genindex.html" /> <link rel="search" title="Search" href="../search.html" /> <link rel="copyright" title="Copyright" href="../copyright.html" /> <link rel="next" title="Python Frequently Asked Questions" href="../faq/index.html" /> <link rel="prev" title="Python experimental support for free threading" href="free-threading-python.html" /> <script defer data-domain="docs.python.org" src="https://plausible.io/js/script.js"></script> <link rel="canonical" href="https://docs.python.org/3/howto/free-threading-extensions.html" /> <style> @media only screen { table.full-width-table { width: 100%; } } </style> <link rel="stylesheet" href="../_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css"> <link rel="shortcut icon" type="image/png" href="../_static/py.svg" /> <script type="text/javascript" src="../_static/copybutton.js"></script> <script type="text/javascript" src="../_static/menu.js"></script> <script type="text/javascript" src="../_static/search-focus.js"></script> <script type="text/javascript" src="../_static/themetoggle.js"></script> <script type="text/javascript" src="../_static/rtd_switcher.js"></script> <meta name="readthedocs-addons-api-version" content="1"> </head> <body> <div class="mobile-nav"> <input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation" aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" /> <nav class="nav-content" role="navigation"> <label for="menuToggler" class="toggler__label"> <span></span> </label> <span class="nav-items-wrapper"> <a href="https://www.python.org/" class="nav-logo"> <img src="../_static/py.svg" alt="Python logo"/> </a> <span class="version_switcher_placeholder"></span> <form role="search" class="search" action="../search.html" method="get"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon"> <path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path> </svg> <input placeholder="Quick search" aria-label="Quick search" type="search" name="q" /> <input type="submit" value="Go"/> </form> </span> </nav> <div class="menu-wrapper"> <nav class="menu" role="navigation" aria-label="main navigation"> <div class="language_switcher_placeholder"></div> <label class="theme-selector-label"> Theme <select class="theme-selector" oninput="activateTheme(this.value)"> <option value="auto" selected>Auto</option> <option value="light">Light</option> <option value="dark">Dark</option> </select> </label> <div> <h3><a href="../contents.html">Table of Contents</a></h3> <ul> <li><a class="reference internal" href="#">C API Extension Support for Free Threading</a><ul> <li><a class="reference internal" href="#identifying-the-free-threaded-build-in-c">Identifying the Free-Threaded Build in C</a></li> <li><a class="reference internal" href="#module-initialization">Module Initialization</a><ul> <li><a class="reference internal" href="#multi-phase-initialization">Multi-Phase Initialization</a></li> <li><a class="reference internal" href="#single-phase-initialization">Single-Phase Initialization</a></li> </ul> </li> <li><a class="reference internal" href="#general-api-guidelines">General API Guidelines</a><ul> <li><a class="reference internal" href="#container-thread-safety">Container Thread Safety</a><ul> <li><a class="reference internal" href="#pydict-next"><code class="docutils literal notranslate"><span class="pre">PyDict_Next</span></code></a></li> </ul> </li> </ul> </li> <li><a class="reference internal" href="#borrowed-references">Borrowed References</a></li> <li><a class="reference internal" href="#memory-allocation-apis">Memory Allocation APIs</a></li> <li><a class="reference internal" href="#thread-state-and-gil-apis">Thread State and GIL APIs</a></li> <li><a class="reference internal" href="#protecting-internal-extension-state">Protecting Internal Extension State</a></li> <li><a class="reference internal" href="#building-extensions-for-the-free-threaded-build">Building Extensions for the Free-Threaded Build</a><ul> <li><a class="reference internal" href="#limited-c-api-and-stable-abi">Limited C API and Stable ABI</a></li> <li><a class="reference internal" href="#windows">Windows</a></li> </ul> </li> </ul> </li> </ul> </div> <div> <h4>Previous topic</h4> <p class="topless"><a href="free-threading-python.html" title="previous chapter">Python experimental support for free threading</a></p> </div> <div> <h4>Next topic</h4> <p class="topless"><a href="../faq/index.html" title="next chapter">Python Frequently Asked Questions</a></p> </div> <div role="note" aria-label="source link"> <h3>This Page</h3> <ul class="this-page-menu"> <li><a href="../bugs.html">Report a Bug</a></li> <li> <a href="https://github.com/python/cpython/blob/main/Doc/howto/free-threading-extensions.rst" rel="nofollow">Show Source </a> </li> </ul> </div> </nav> </div> </div> <div class="related" role="navigation" aria-label="Related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > <a href="../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li class="right" > <a href="../faq/index.html" title="Python Frequently Asked Questions" accesskey="N">next</a> |</li> <li class="right" > <a href="free-threading-python.html" title="Python experimental support for free threading" accesskey="P">previous</a> |</li> <li><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"/></li> <li><a href="https://www.python.org/">Python</a> &#187;</li> <li class="switchers"> <div class="language_switcher_placeholder"></div> <div class="version_switcher_placeholder"></div> </li> <li> </li> <li id="cpython-language-and-version"> <a href="../index.html">3.13.2 Documentation</a> &#187; </li> <li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li> <li class="nav-item nav-item-this"><a href="">C API Extension Support for Free Threading</a></li> <li class="right"> <div class="inline-search" role="search"> <form class="inline-search" action="../search.html" method="get"> <input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box" /> <input type="submit" value="Go" /> </form> </div> | </li> <li class="right"> <label class="theme-selector-label"> Theme <select class="theme-selector" oninput="activateTheme(this.value)"> <option value="auto" selected>Auto</option> <option value="light">Light</option> <option value="dark">Dark</option> </select> </label> |</li> </ul> </div> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body" role="main"> <section id="c-api-extension-support-for-free-threading"> <span id="freethreading-extensions-howto"></span><h1>C API Extension Support for Free Threading<a class="headerlink" href="#c-api-extension-support-for-free-threading" title="Link to this heading">¶</a></h1> <p>Starting with the 3.13 release, CPython has experimental support for running with the <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global interpreter lock</span></a> (GIL) disabled in a configuration called <a class="reference internal" href="../glossary.html#term-free-threading"><span class="xref std std-term">free threading</span></a>. This document describes how to adapt C API extensions to support free threading.</p> <section id="identifying-the-free-threaded-build-in-c"> <h2>Identifying the Free-Threaded Build in C<a class="headerlink" href="#identifying-the-free-threaded-build-in-c" title="Link to this heading">¶</a></h2> <p>The CPython C API exposes the <code class="docutils literal notranslate"><span class="pre">Py_GIL_DISABLED</span></code> macro: in the free-threaded build it’s defined to <code class="docutils literal notranslate"><span class="pre">1</span></code>, and in the regular build it’s not defined. You can use it to enable code that only runs under the free-threaded build:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifdef Py_GIL_DISABLED</span> <span class="cm">/* code that only runs in the free-threaded build */</span> <span class="cp">#endif</span> </pre></div> </div> </section> <section id="module-initialization"> <h2>Module Initialization<a class="headerlink" href="#module-initialization" title="Link to this heading">¶</a></h2> <p>Extension modules need to explicitly indicate that they support running with the GIL disabled; otherwise importing the extension will raise a warning and enable the GIL at runtime.</p> <p>There are two ways to indicate that an extension module supports running with the GIL disabled depending on whether the extension uses multi-phase or single-phase initialization.</p> <section id="multi-phase-initialization"> <h3>Multi-Phase Initialization<a class="headerlink" href="#multi-phase-initialization" title="Link to this heading">¶</a></h3> <p>Extensions that use multi-phase initialization (i.e., <a class="reference internal" href="../c-api/module.html#c.PyModuleDef_Init" title="PyModuleDef_Init"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModuleDef_Init()</span></code></a>) should add a <a class="reference internal" href="../c-api/module.html#c.Py_mod_gil" title="Py_mod_gil"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_mod_gil</span></code></a> slot in the module definition. If your extension supports older versions of CPython, you should guard the slot with a <a class="reference internal" href="../c-api/apiabiversion.html#c.PY_VERSION_HEX" title="PY_VERSION_HEX"><code class="xref c c-data docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a> check.</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyModuleDef_Slot</span><span class="w"> </span><span class="n">module_slots</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="p">...</span> <span class="cp">#if PY_VERSION_HEX &gt;= 0x030D0000</span> <span class="w"> </span><span class="p">{</span><span class="n">Py_mod_gil</span><span class="p">,</span><span class="w"> </span><span class="n">Py_MOD_GIL_NOT_USED</span><span class="p">},</span> <span class="cp">#endif</span> <span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">}</span> <span class="p">};</span> <span class="k">static</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyModuleDef</span><span class="w"> </span><span class="n">moduledef</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span> <span class="w"> </span><span class="p">.</span><span class="n">m_slots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">module_slots</span><span class="p">,</span> <span class="w"> </span><span class="p">...</span> <span class="p">};</span> </pre></div> </div> </section> <section id="single-phase-initialization"> <h3>Single-Phase Initialization<a class="headerlink" href="#single-phase-initialization" title="Link to this heading">¶</a></h3> <p>Extensions that use single-phase initialization (i.e., <a class="reference internal" href="../c-api/module.html#c.PyModule_Create" title="PyModule_Create"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_Create()</span></code></a>) should call <a class="reference internal" href="../c-api/module.html#c.PyUnstable_Module_SetGIL" title="PyUnstable_Module_SetGIL"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUnstable_Module_SetGIL()</span></code></a> to indicate that they support running with the GIL disabled. The function is only defined in the free-threaded build, so you should guard the call with <code class="docutils literal notranslate"><span class="pre">#ifdef</span> <span class="pre">Py_GIL_DISABLED</span></code> to avoid compilation errors in the regular build.</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyModuleDef</span><span class="w"> </span><span class="n">moduledef</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span> <span class="w"> </span><span class="p">...</span> <span class="p">};</span> <span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_mymodule</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="cp">#ifdef Py_GIL_DISABLED</span> <span class="w"> </span><span class="n">PyUnstable_Module_SetGIL</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">Py_MOD_GIL_NOT_USED</span><span class="p">);</span> <span class="cp">#endif</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">m</span><span class="p">;</span> <span class="p">}</span> </pre></div> </div> </section> </section> <section id="general-api-guidelines"> <h2>General API Guidelines<a class="headerlink" href="#general-api-guidelines" title="Link to this heading">¶</a></h2> <p>Most of the C API is thread-safe, but there are some exceptions.</p> <ul class="simple"> <li><p><strong>Struct Fields</strong>: Accessing fields in Python C API objects or structs directly is not thread-safe if the field may be concurrently modified.</p></li> <li><p><strong>Macros</strong>: Accessor macros like <a class="reference internal" href="../c-api/list.html#c.PyList_GET_ITEM" title="PyList_GET_ITEM"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyList_GET_ITEM</span></code></a> and <a class="reference internal" href="../c-api/list.html#c.PyList_SET_ITEM" title="PyList_SET_ITEM"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyList_SET_ITEM</span></code></a> do not perform any error checking or locking. These macros are not thread-safe if the container object may be modified concurrently.</p></li> <li><p><strong>Borrowed References</strong>: C API functions that return <a class="reference internal" href="../glossary.html#term-borrowed-reference"><span class="xref std std-term">borrowed references</span></a> may not be thread-safe if the containing object is modified concurrently. See the section on <a class="reference internal" href="#id2"><span class="std std-ref">borrowed references</span></a> for more information.</p></li> </ul> <section id="container-thread-safety"> <h3>Container Thread Safety<a class="headerlink" href="#container-thread-safety" title="Link to this heading">¶</a></h3> <p>Containers like <a class="reference internal" href="../c-api/list.html#c.PyListObject" title="PyListObject"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PyListObject</span></code></a>, <a class="reference internal" href="../c-api/dict.html#c.PyDictObject" title="PyDictObject"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PyDictObject</span></code></a>, and <a class="reference internal" href="../c-api/set.html#c.PySetObject" title="PySetObject"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PySetObject</span></code></a> perform internal locking in the free-threaded build. For example, the <a class="reference internal" href="../c-api/list.html#c.PyList_Append" title="PyList_Append"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_Append()</span></code></a> will lock the list before appending an item.</p> <section id="pydict-next"> <span id="id1"></span><h4><code class="docutils literal notranslate"><span class="pre">PyDict_Next</span></code><a class="headerlink" href="#pydict-next" title="Link to this heading">¶</a></h4> <p>A notable exception is <a class="reference internal" href="../c-api/dict.html#c.PyDict_Next" title="PyDict_Next"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_Next()</span></code></a>, which does not lock the dictionary. You should use <a class="reference internal" href="../c-api/init.html#c.Py_BEGIN_CRITICAL_SECTION" title="Py_BEGIN_CRITICAL_SECTION"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_BEGIN_CRITICAL_SECTION</span></code></a> to protect the dictionary while iterating over it if the dictionary may be concurrently modified:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">Py_BEGIN_CRITICAL_SECTION</span><span class="p">(</span><span class="n">dict</span><span class="p">);</span> <span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">value</span><span class="p">;</span> <span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">pos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span> <span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">PyDict_Next</span><span class="p">(</span><span class="n">dict</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">pos</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">value</span><span class="p">))</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="p">...</span> <span class="p">}</span> <span class="n">Py_END_CRITICAL_SECTION</span><span class="p">();</span> </pre></div> </div> </section> </section> </section> <section id="borrowed-references"> <h2>Borrowed References<a class="headerlink" href="#borrowed-references" title="Link to this heading">¶</a></h2> <p id="id2">Some C API functions return <a class="reference internal" href="../glossary.html#term-borrowed-reference"><span class="xref std std-term">borrowed references</span></a>. These APIs are not thread-safe if the containing object is modified concurrently. For example, it’s not safe to use <a class="reference internal" href="../c-api/list.html#c.PyList_GetItem" title="PyList_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_GetItem()</span></code></a> if the list may be modified concurrently.</p> <p>The following table lists some borrowed reference APIs and their replacements that return <a class="reference internal" href="../glossary.html#term-strong-reference"><span class="xref std std-term">strong references</span></a>.</p> <table class="docutils align-default"> <thead> <tr class="row-odd"><th class="head"><p>Borrowed reference API</p></th> <th class="head"><p>Strong reference API</p></th> </tr> </thead> <tbody> <tr class="row-even"><td><p><a class="reference internal" href="../c-api/list.html#c.PyList_GetItem" title="PyList_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_GetItem()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/list.html#c.PyList_GetItemRef" title="PyList_GetItemRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_GetItemRef()</span></code></a></p></td> </tr> <tr class="row-odd"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItem" title="PyDict_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItem()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemRef" title="PyDict_GetItemRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemRef()</span></code></a></p></td> </tr> <tr class="row-even"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemWithError" title="PyDict_GetItemWithError"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemWithError()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemRef" title="PyDict_GetItemRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemRef()</span></code></a></p></td> </tr> <tr class="row-odd"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemString" title="PyDict_GetItemString"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemString()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemStringRef" title="PyDict_GetItemStringRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemStringRef()</span></code></a></p></td> </tr> <tr class="row-even"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_SetDefault" title="PyDict_SetDefault"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_SetDefault()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_SetDefaultRef" title="PyDict_SetDefaultRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_SetDefaultRef()</span></code></a></p></td> </tr> <tr class="row-odd"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_Next" title="PyDict_Next"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_Next()</span></code></a></p></td> <td><p>none (see <a class="reference internal" href="#pydict-next"><span class="std std-ref">PyDict_Next</span></a>)</p></td> </tr> <tr class="row-even"><td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GetObject" title="PyWeakref_GetObject"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GetObject()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GetRef" title="PyWeakref_GetRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GetRef()</span></code></a></p></td> </tr> <tr class="row-odd"><td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GET_OBJECT" title="PyWeakref_GET_OBJECT"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GET_OBJECT()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GetRef" title="PyWeakref_GetRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GetRef()</span></code></a></p></td> </tr> <tr class="row-even"><td><p><a class="reference internal" href="../c-api/import.html#c.PyImport_AddModule" title="PyImport_AddModule"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyImport_AddModule()</span></code></a></p></td> <td><p><a class="reference internal" href="../c-api/import.html#c.PyImport_AddModuleRef" title="PyImport_AddModuleRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyImport_AddModuleRef()</span></code></a></p></td> </tr> </tbody> </table> <p>Not all APIs that return borrowed references are problematic. For example, <a class="reference internal" href="../c-api/tuple.html#c.PyTuple_GetItem" title="PyTuple_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyTuple_GetItem()</span></code></a> is safe because tuples are immutable. Similarly, not all uses of the above APIs are problematic. For example, <a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItem" title="PyDict_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItem()</span></code></a> is often used for parsing keyword argument dictionaries in function calls; those keyword argument dictionaries are effectively private (not accessible by other threads), so using borrowed references in that context is safe.</p> <p>Some of these functions were added in Python 3.13. You can use the <a class="reference external" href="https://github.com/python/pythoncapi-compat">pythoncapi-compat</a> package to provide implementations of these functions for older Python versions.</p> </section> <section id="memory-allocation-apis"> <span id="free-threaded-memory-allocation"></span><h2>Memory Allocation APIs<a class="headerlink" href="#memory-allocation-apis" title="Link to this heading">¶</a></h2> <p>Python’s memory management C API provides functions in three different <a class="reference internal" href="../c-api/memory.html#id1"><span class="std std-ref">allocation domains</span></a>: “raw”, “mem”, and “object”. For thread-safety, the free-threaded build requires that only Python objects are allocated using the object domain, and that all Python object are allocated using that domain. This differs from the prior Python versions, where this was only a best practice and not a hard requirement.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Search for uses of <a class="reference internal" href="../c-api/memory.html#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a> in your extension and check that the allocated memory is used for Python objects. Use <a class="reference internal" href="../c-api/memory.html#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a> to allocate buffers instead of <a class="reference internal" href="../c-api/memory.html#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a>.</p> </div> </section> <section id="thread-state-and-gil-apis"> <h2>Thread State and GIL APIs<a class="headerlink" href="#thread-state-and-gil-apis" title="Link to this heading">¶</a></h2> <p>Python provides a set of functions and macros to manage thread state and the GIL, such as:</p> <ul class="simple"> <li><p><a class="reference internal" href="../c-api/init.html#c.PyGILState_Ensure" title="PyGILState_Ensure"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyGILState_Ensure()</span></code></a> and <a class="reference internal" href="../c-api/init.html#c.PyGILState_Release" title="PyGILState_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyGILState_Release()</span></code></a></p></li> <li><p><a class="reference internal" href="../c-api/init.html#c.PyEval_SaveThread" title="PyEval_SaveThread"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyEval_SaveThread()</span></code></a> and <a class="reference internal" href="../c-api/init.html#c.PyEval_RestoreThread" title="PyEval_RestoreThread"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyEval_RestoreThread()</span></code></a></p></li> <li><p><a class="reference internal" href="../c-api/init.html#c.Py_BEGIN_ALLOW_THREADS" title="Py_BEGIN_ALLOW_THREADS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_BEGIN_ALLOW_THREADS</span></code></a> and <a class="reference internal" href="../c-api/init.html#c.Py_END_ALLOW_THREADS" title="Py_END_ALLOW_THREADS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_END_ALLOW_THREADS</span></code></a></p></li> </ul> <p>These functions should still be used in the free-threaded build to manage thread state even when the <a class="reference internal" href="../glossary.html#term-GIL"><span class="xref std std-term">GIL</span></a> is disabled. For example, if you create a thread outside of Python, you must call <a class="reference internal" href="../c-api/init.html#c.PyGILState_Ensure" title="PyGILState_Ensure"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyGILState_Ensure()</span></code></a> before calling into the Python API to ensure that the thread has a valid Python thread state.</p> <p>You should continue to call <a class="reference internal" href="../c-api/init.html#c.PyEval_SaveThread" title="PyEval_SaveThread"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyEval_SaveThread()</span></code></a> or <a class="reference internal" href="../c-api/init.html#c.Py_BEGIN_ALLOW_THREADS" title="Py_BEGIN_ALLOW_THREADS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_BEGIN_ALLOW_THREADS</span></code></a> around blocking operations, such as I/O or lock acquisitions, to allow other threads to run the <a class="reference internal" href="../glossary.html#term-garbage-collection"><span class="xref std std-term">cyclic garbage collector</span></a>.</p> </section> <section id="protecting-internal-extension-state"> <h2>Protecting Internal Extension State<a class="headerlink" href="#protecting-internal-extension-state" title="Link to this heading">¶</a></h2> <p>Your extension may have internal state that was previously protected by the GIL. You may need to add locking to protect this state. The approach will depend on your extension, but some common patterns include:</p> <ul class="simple"> <li><p><strong>Caches</strong>: global caches are a common source of shared state. Consider using a lock to protect the cache or disabling it in the free-threaded build if the cache is not critical for performance.</p></li> <li><p><strong>Global State</strong>: global state may need to be protected by a lock or moved to thread local storage. C11 and C++11 provide the <code class="docutils literal notranslate"><span class="pre">thread_local</span></code> or <code class="docutils literal notranslate"><span class="pre">_Thread_local</span></code> for <a class="reference external" href="https://en.cppreference.com/w/c/language/storage_duration">thread-local storage</a>.</p></li> </ul> </section> <section id="building-extensions-for-the-free-threaded-build"> <h2>Building Extensions for the Free-Threaded Build<a class="headerlink" href="#building-extensions-for-the-free-threaded-build" title="Link to this heading">¶</a></h2> <p>C API extensions need to be built specifically for the free-threaded build. The wheels, shared libraries, and binaries are indicated by a <code class="docutils literal notranslate"><span class="pre">t</span></code> suffix.</p> <ul class="simple"> <li><p><a class="reference external" href="https://github.com/pypa/manylinux">pypa/manylinux</a> supports the free-threaded build, with the <code class="docutils literal notranslate"><span class="pre">t</span></code> suffix, such as <code class="docutils literal notranslate"><span class="pre">python3.13t</span></code>.</p></li> <li><p><a class="reference external" href="https://github.com/pypa/cibuildwheel">pypa/cibuildwheel</a> supports the free-threaded build if you set <a class="reference external" href="https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support">CIBW_FREE_THREADED_SUPPORT</a>.</p></li> </ul> <section id="limited-c-api-and-stable-abi"> <h3>Limited C API and Stable ABI<a class="headerlink" href="#limited-c-api-and-stable-abi" title="Link to this heading">¶</a></h3> <p>The free-threaded build does not currently support the <a class="reference internal" href="../c-api/stable.html#limited-c-api"><span class="std std-ref">Limited C API</span></a> or the stable ABI. If you use <a class="reference external" href="https://setuptools.pypa.io/en/latest/setuptools.html">setuptools</a> to build your extension and currently set <code class="docutils literal notranslate"><span class="pre">py_limited_api=True</span></code> you can use <code class="docutils literal notranslate"><span class="pre">py_limited_api=not</span> <span class="pre">sysconfig.get_config_var(&quot;Py_GIL_DISABLED&quot;)</span></code> to opt out of the limited API when building with the free-threaded build.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>You will need to build separate wheels specifically for the free-threaded build. If you currently use the stable ABI, you can continue to build a single wheel for multiple non-free-threaded Python versions.</p> </div> </section> <section id="windows"> <h3>Windows<a class="headerlink" href="#windows" title="Link to this heading">¶</a></h3> <p>Due to a limitation of the official Windows installer, you will need to manually define <code class="docutils literal notranslate"><span class="pre">Py_GIL_DISABLED=1</span></code> when building extensions from source.</p> <div class="admonition seealso"> <p class="admonition-title">See also</p> <p><a class="reference external" href="https://py-free-threading.github.io/porting/">Porting Extension Modules to Support Free-Threading</a>: A community-maintained porting guide for extension authors.</p> </div> </section> </section> </section> <div class="clearer"></div> </div> </div> </div> <div class="sphinxsidebar" role="navigation" aria-label="Main"> <div class="sphinxsidebarwrapper"> <div> <h3><a href="../contents.html">Table of Contents</a></h3> <ul> <li><a class="reference internal" href="#">C API Extension Support for Free Threading</a><ul> <li><a class="reference internal" href="#identifying-the-free-threaded-build-in-c">Identifying the Free-Threaded Build in C</a></li> <li><a class="reference internal" href="#module-initialization">Module Initialization</a><ul> <li><a class="reference internal" href="#multi-phase-initialization">Multi-Phase Initialization</a></li> <li><a class="reference internal" href="#single-phase-initialization">Single-Phase Initialization</a></li> </ul> </li> <li><a class="reference internal" href="#general-api-guidelines">General API Guidelines</a><ul> <li><a class="reference internal" href="#container-thread-safety">Container Thread Safety</a><ul> <li><a class="reference internal" href="#pydict-next"><code class="docutils literal notranslate"><span class="pre">PyDict_Next</span></code></a></li> </ul> </li> </ul> </li> <li><a class="reference internal" href="#borrowed-references">Borrowed References</a></li> <li><a class="reference internal" href="#memory-allocation-apis">Memory Allocation APIs</a></li> <li><a class="reference internal" href="#thread-state-and-gil-apis">Thread State and GIL APIs</a></li> <li><a class="reference internal" href="#protecting-internal-extension-state">Protecting Internal Extension State</a></li> <li><a class="reference internal" href="#building-extensions-for-the-free-threaded-build">Building Extensions for the Free-Threaded Build</a><ul> <li><a class="reference internal" href="#limited-c-api-and-stable-abi">Limited C API and Stable ABI</a></li> <li><a class="reference internal" href="#windows">Windows</a></li> </ul> </li> </ul> </li> </ul> </div> <div> <h4>Previous topic</h4> <p class="topless"><a href="free-threading-python.html" title="previous chapter">Python experimental support for free threading</a></p> </div> <div> <h4>Next topic</h4> <p class="topless"><a href="../faq/index.html" title="next chapter">Python Frequently Asked Questions</a></p> </div> <div role="note" aria-label="source link"> <h3>This Page</h3> <ul class="this-page-menu"> <li><a href="../bugs.html">Report a Bug</a></li> <li> <a href="https://github.com/python/cpython/blob/main/Doc/howto/free-threading-extensions.rst" rel="nofollow">Show Source </a> </li> </ul> </div> </div> <div id="sidebarbutton" title="Collapse sidebar"> <span>«</span> </div> </div> <div class="clearer"></div> </div> <div class="related" role="navigation" aria-label="Related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../genindex.html" title="General Index" >index</a></li> <li class="right" > <a href="../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li class="right" > <a href="../faq/index.html" title="Python Frequently Asked Questions" >next</a> |</li> <li class="right" > <a href="free-threading-python.html" title="Python experimental support for free threading" >previous</a> |</li> <li><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"/></li> <li><a href="https://www.python.org/">Python</a> &#187;</li> <li class="switchers"> <div class="language_switcher_placeholder"></div> <div class="version_switcher_placeholder"></div> </li> <li> </li> <li id="cpython-language-and-version"> <a href="../index.html">3.13.2 Documentation</a> &#187; </li> <li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li> <li class="nav-item nav-item-this"><a href="">C API Extension Support for Free Threading</a></li> <li class="right"> <div class="inline-search" role="search"> <form class="inline-search" action="../search.html" method="get"> <input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box" /> <input type="submit" value="Go" /> </form> </div> | </li> <li class="right"> <label class="theme-selector-label"> Theme <select class="theme-selector" oninput="activateTheme(this.value)"> <option value="auto" selected>Auto</option> <option value="light">Light</option> <option value="dark">Dark</option> </select> </label> |</li> </ul> </div> <div class="footer"> &copy; <a href="../copyright.html"> Copyright </a> 2001-2025, Python Software Foundation. <br /> This page is licensed under the Python Software Foundation License Version 2. <br /> Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License. <br /> See <a href="/license.html">History and License</a> for more information.<br /> <br /> The Python Software Foundation is a non-profit corporation. <a href="https://www.python.org/psf/donations/">Please donate.</a> <br /> <br /> Last updated on Apr 01, 2025 (14:46 UTC). <a href="/bugs.html">Found a bug</a>? <br /> Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3. </div> <script type="text/javascript" src="../_static/switchers.js"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10