Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions Doc/c-api/object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,39 @@ Object Protocol

This function is intended to be used soon after *op* is created, by the code that
creates it, such as in the object's :c:member:`~PyTypeObject.tp_new` slot.
It is a fast operation that does not stop other threads. To immortalize an
object that may already be shared, use :c:func:`PyUnstable_Immortalize`.
Returns 1 if the object was made immortal and returns 0 if it was not.
This function cannot fail.

.. versionadded:: 3.15

.. c:function:: int PyUnstable_Immortalize(PyObject *op)

Marks an object *op* :term:`immortal`, even if it is shared across threads.
:class:`str` instances, including subclasses, are not made immortal.
This is intended to reduce reference counting contention in the
:term:`free-threaded build` for objects shared across threads and used in
native code.

This is a slow operation. In the free-threaded build, it stops all other
threads in the interpreter while immortalizing the object. For newly created,
uniquely referenced objects, prefer :c:func:`PyUnstable_SetImmortal`.

This is a one-way process: objects can only be made immortal; they cannot be
made mortal once again. Immortal objects do not participate in reference
counting and will never be garbage collected. If the object is GC-tracked,
it is untracked.

Returns 1 if the object was made immortal and 0 if it was already immortal
or is a :class:`str` instance.
Returns -1 with an exception set if allocating bookkeeping for an immortal
frame or generator fails.

.. warning::

Immortalizing GC-tracked objects (and other objects on the heap) will
result in them being leaked for the remainder of the process, as immortal
objects are not deallocated at interpreter shutdown.

.. versionadded:: next
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,12 @@ C API changes
New features
------------

* Add :c:func:`PyUnstable_Immortalize` to make already shared objects
:term:`immortal`. In free-threaded builds, the function stops other threads
while immortalizing the object. :class:`str` instances are not supported.
Immortalized objects are not deallocated at interpreter shutdown.
(Contributed by Peter Bierma in :gh:`150865`.)

* Add :c:func:`Py_HashBuffer` to the limited C API.
(Contributed by Victor Stinner in :gh:`148233`.)

Expand Down
1 change: 1 addition & 0 deletions Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *);
PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *);

PyAPI_FUNC(int) PyUnstable_SetImmortal(PyObject *op);
PyAPI_FUNC(int) PyUnstable_Immortalize(PyObject *op);

#if defined(Py_GIL_DISABLED)
PyAPI_FUNC(uintptr_t) _Py_GetThreadLocal_Addr(void);
Expand Down
4 changes: 4 additions & 0 deletions Include/internal/pycore_interp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern "C" {

#include "pycore_ast_state.h" // struct ast_state
#include "pycore_llist.h" // struct llist_node
#include "pycore_object_stack.h" // _PyObjectStack
#include "pycore_opcode_utils.h" // NUM_COMMON_CONSTANTS
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
#include "pycore_structs.h" // PyHamtObject
Expand Down Expand Up @@ -235,6 +236,9 @@ struct _gc_runtime_state {
#endif
/* a permanent generation which won't be collected */
struct gc_generation permanent_generation;
// Untracked immortal frames and generators whose references must remain
// visible to GC. Access requires the GIL or a stop-the-world pause.
_PyObjectStack immortal_frames;
struct gc_stats *generation_stats;
#ifdef Py_GIL_DISABLED
/* Protects generation_stats between gc_get_stats_impl() (reader) and
Expand Down
Loading
Loading