summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2002-04-18 22:25:03 (GMT)
committerTim Peters <tim.peters@gmail.com>2002-04-18 22:25:03 (GMT)
commit08d821582faab8f3b6eeab1b1fd7520417b82b80 (patch)
tree6a3a04ff2da63cca2ab214b49855f586763c3119 /Objects
parent64d80c9f40465f9bed18712bc2b792f28dcac162 (diff)
downloadcpython-08d821582faab8f3b6eeab1b1fd7520417b82b80.zip
cpython-08d821582faab8f3b6eeab1b1fd7520417b82b80.tar.gz
cpython-08d821582faab8f3b6eeab1b1fd7520417b82b80.tar.bz2
_PyObject_DebugMallocStats(): Added some potentially expensive internal
consistency checks, enabled only in a debug (Py_DEBUG) build. Note that this never gets called automatically unless PYMALLOC_DEBUG is #define'd too, and the envar PYTHONMALLOCSTATS exists.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/obmalloc.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 602b3c3..c39a823 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -908,6 +908,31 @@ write4(void *p, ulong n)
q[3] = (uchar)( n & 0xff);
}
+#ifdef Py_DEBUG
+/* Is target in the list? The list is traversed via the nextpool pointers.
+ * The list may be NULL-terminated, or circular. Return 1 if target is in
+ * list, else 0.
+ */
+static int
+pool_is_in_list(const poolp target, poolp list)
+{
+ poolp origlist = list;
+ assert(target != NULL);
+ if (list == NULL)
+ return 0;
+ do {
+ if (target == list)
+ return 1;
+ list = list->nextpool;
+ } while (list != NULL && list != origlist);
+ return 0;
+}
+
+#else
+#define pool_is_in_list(X, Y) 1
+
+#endif /* Py_DEBUG */
+
/* The debug malloc asks for 16 extra bytes and fills them with useful stuff,
here calling the underlying malloc's result p:
@@ -1200,7 +1225,10 @@ printone(const char* msg, ulong value)
return origvalue;
}
-/* Print summary info to stderr about the state of pymalloc's structures. */
+/* Print summary info to stderr about the state of pymalloc's structures.
+ * In Py_DEBUG mode, also perform some expensive internal consistency
+ * checks.
+ */
void
_PyObject_DebugMallocStats(void)
{
@@ -1262,15 +1290,23 @@ _PyObject_DebugMallocStats(void)
/* visit every pool in the arena */
for (j = 0; j < poolsinarena; ++j, base += POOL_SIZE) {
poolp p = (poolp)base;
+ const uint sz = p->szidx;
+ uint freeblocks;
+
if (p->ref.count == 0) {
/* currently unused */
++numfreepools;
+ assert(pool_is_in_list(p, freepools));
continue;
}
- ++numpools[p->szidx];
- numblocks[p->szidx] += p->ref.count;
- numfreeblocks[p->szidx] += NUMBLOCKS(p->szidx) -
- p->ref.count;
+ ++numpools[sz];
+ numblocks[sz] += p->ref.count;
+ freeblocks = NUMBLOCKS(sz) - p->ref.count;
+ numfreeblocks[sz] += freeblocks;
+#ifdef Py_DEBUG
+ if (freeblocks > 0)
+ assert(pool_is_in_list(p, usedpools[sz + sz]));
+#endif
}
}