summaryrefslogtreecommitdiffstats
path: root/Modules/gcmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/gcmodule.c')
-rw-r--r--Modules/gcmodule.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 832e27e..6e26c7a 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -71,6 +71,10 @@ _PyGC_Initialize(struct _gc_runtime_state *state)
state->generations[i] = generations[i];
};
state->generation0 = GEN_HEAD(0);
+ struct gc_generation permanent_generation = {
+ {{&state->permanent_generation.head, &state->permanent_generation.head, 0}}, 0, 0
+ };
+ state->permanent_generation = permanent_generation;
}
/*--------------------------------------------------------------------------
@@ -813,6 +817,8 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
for (i = 0; i < NUM_GENERATIONS; i++)
PySys_FormatStderr(" %zd",
gc_list_size(GEN_HEAD(i)));
+ PySys_WriteStderr("\ngc: objects in permanent generation: %zd",
+ gc_list_size(&_PyRuntime.gc.permanent_generation.head));
t1 = _PyTime_GetMonotonicClock();
PySys_WriteStderr("\n");
@@ -1405,6 +1411,56 @@ gc_is_tracked(PyObject *module, PyObject *obj)
return result;
}
+/*[clinic input]
+gc.freeze
+
+Freeze all current tracked objects and ignore them for future collections.
+
+This can be used before a POSIX fork() call to make the gc copy-on-write friendly.
+Note: collection before a POSIX fork() call may free pages for future allocation
+which can cause copy-on-write.
+[clinic start generated code]*/
+
+static PyObject *
+gc_freeze_impl(PyObject *module)
+/*[clinic end generated code: output=502159d9cdc4c139 input=b602b16ac5febbe5]*/
+{
+ for (int i = 0; i < NUM_GENERATIONS; ++i) {
+ gc_list_merge(GEN_HEAD(i), &_PyRuntime.gc.permanent_generation.head);
+ _PyRuntime.gc.generations[i].count = 0;
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+gc.unfreeze
+
+Unfreeze all objects in the permanent generation.
+
+Put all objects in the permanent generation back into oldest generation.
+[clinic start generated code]*/
+
+static PyObject *
+gc_unfreeze_impl(PyObject *module)
+/*[clinic end generated code: output=1c15f2043b25e169 input=2dd52b170f4cef6c]*/
+{
+ gc_list_merge(&_PyRuntime.gc.permanent_generation.head, GEN_HEAD(NUM_GENERATIONS-1));
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+gc.get_freeze_count -> int
+
+Return the number of objects in the permanent generation.
+[clinic start generated code]*/
+
+static int
+gc_get_freeze_count_impl(PyObject *module)
+/*[clinic end generated code: output=e4e2ebcc77e5cbf3 input=4b759db880a3c6e4]*/
+{
+ return gc_list_size(&_PyRuntime.gc.permanent_generation.head);
+}
+
PyDoc_STRVAR(gc__doc__,
"This module provides access to the garbage collector for reference cycles.\n"
@@ -1422,7 +1478,10 @@ PyDoc_STRVAR(gc__doc__,
"get_objects() -- Return a list of all objects tracked by the collector.\n"
"is_tracked() -- Returns true if a given object is tracked.\n"
"get_referrers() -- Return the list of objects that refer to an object.\n"
-"get_referents() -- Return the list of objects that an object refers to.\n");
+"get_referents() -- Return the list of objects that an object refers to.\n"
+"freeze() -- Freeze all tracked objects and ignore them for future collections.\n"
+"unfreeze() -- Unfreeze all objects in the permanent generation.\n"
+"get_freeze_count() -- Return the number of objects in the permanent generation.\n");
static PyMethodDef GcMethods[] = {
GC_ENABLE_METHODDEF
@@ -1441,6 +1500,9 @@ static PyMethodDef GcMethods[] = {
gc_get_referrers__doc__},
{"get_referents", gc_get_referents, METH_VARARGS,
gc_get_referents__doc__},
+ GC_FREEZE_METHODDEF
+ GC_UNFREEZE_METHODDEF
+ GC_GET_FREEZE_COUNT_METHODDEF
{NULL, NULL} /* Sentinel */
};