Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/obmalloc.c
Line
Count
Source
1
/* Python's malloc wrappers (see pymem.h) */
2
3
#include "Python.h"
4
#include "pycore_interp.h"        // _PyInterpreterState_HasFeature
5
#include "pycore_mmap.h"          // _PyAnnotateMemoryMap()
6
#include "pycore_object.h"        // _PyDebugAllocatorStats() definition
7
#include "pycore_obmalloc.h"
8
#include "pycore_obmalloc_init.h"
9
#include "pycore_pyerrors.h"      // _Py_FatalErrorFormat()
10
#include "pycore_pymem.h"
11
#include "pycore_pystate.h"       // _PyInterpreterState_GET
12
#include "pycore_stats.h"         // OBJECT_STAT_INC_COND()
13
14
#include <stdlib.h>               // malloc()
15
#include <stdbool.h>
16
#include <stdio.h>                // fopen(), fgets(), sscanf()
17
#include <errno.h>                // errno
18
#ifdef WITH_MIMALLOC
19
// Forward declarations of functions used in our mimalloc modifications
20
static void _PyMem_mi_page_clear_qsbr(mi_page_t *page);
21
static bool _PyMem_mi_page_is_safe_to_free(mi_page_t *page);
22
static bool _PyMem_mi_page_maybe_free(mi_page_t *page, mi_page_queue_t *pq, bool force);
23
static void _PyMem_mi_page_reclaimed(mi_page_t *page);
24
static void _PyMem_mi_heap_collect_qsbr(mi_heap_t *heap);
25
#  include "pycore_mimalloc.h"
26
#  include "mimalloc/static.c"
27
#  include "mimalloc/internal.h"  // for stats
28
#endif
29
30
#if defined(Py_GIL_DISABLED) && !defined(WITH_MIMALLOC)
31
#  error "Py_GIL_DISABLED requires WITH_MIMALLOC"
32
#endif
33
34
#undef  uint
35
2.02G
#define uint pymem_uint
36
37
38
/* Defined in tracemalloc.c */
39
extern void _PyMem_DumpTraceback(int fd, const void *ptr);
40
41
static void _PyObject_DebugDumpAddress(const void *p);
42
static void _PyMem_DebugCheckAddress(const char *func, char api_id, const void *p);
43
44
45
static void set_up_debug_hooks_domain_unlocked(PyMemAllocatorDomain domain);
46
static void set_up_debug_hooks_unlocked(void);
47
static void get_allocator_unlocked(PyMemAllocatorDomain, PyMemAllocatorEx *);
48
static void set_allocator_unlocked(PyMemAllocatorDomain, PyMemAllocatorEx *);
49
50
51
/***************************************/
52
/* low-level allocator implementations */
53
/***************************************/
54
55
/* the default raw allocator (wraps malloc) */
56
57
void *
58
_PyMem_RawMalloc(void *Py_UNUSED(ctx), size_t size)
59
193M
{
60
    /* PyMem_RawMalloc(0) means malloc(1). Some systems would return NULL
61
       for malloc(0), which would be treated as an error. Some platforms would
62
       return a pointer with no memory behind it, which would break pymalloc.
63
       To solve these problems, allocate an extra byte. */
64
193M
    if (size == 0)
65
52.7k
        size = 1;
66
193M
    return malloc(size);
67
193M
}
68
69
void *
70
_PyMem_RawCalloc(void *Py_UNUSED(ctx), size_t nelem, size_t elsize)
71
202k
{
72
    /* PyMem_RawCalloc(0, 0) means calloc(1, 1). Some systems would return NULL
73
       for calloc(0, 0), which would be treated as an error. Some platforms
74
       would return a pointer with no memory behind it, which would break
75
       pymalloc.  To solve these problems, allocate an extra byte. */
76
202k
    if (nelem == 0 || elsize == 0) {
77
1.86k
        nelem = 1;
78
1.86k
        elsize = 1;
79
1.86k
    }
80
202k
    return calloc(nelem, elsize);
81
202k
}
82
83
void *
84
_PyMem_RawRealloc(void *Py_UNUSED(ctx), void *ptr, size_t size)
85
10.6M
{
86
10.6M
    if (size == 0)
87
0
        size = 1;
88
10.6M
    return realloc(ptr, size);
89
10.6M
}
90
91
void
92
_PyMem_RawFree(void *Py_UNUSED(ctx), void *ptr)
93
193M
{
94
193M
    free(ptr);
95
193M
}
96
97
#ifdef WITH_MIMALLOC
98
99
static void
100
_PyMem_mi_page_clear_qsbr(mi_page_t *page)
101
0
{
102
#ifdef Py_GIL_DISABLED
103
    // Clear the QSBR goal and remove the page from the QSBR linked list.
104
    page->qsbr_goal = 0;
105
    if (page->qsbr_node.next != NULL) {
106
        llist_remove(&page->qsbr_node);
107
    }
108
#endif
109
0
}
110
111
// Check if an empty, newly reclaimed page is safe to free now.
112
static bool
113
_PyMem_mi_page_is_safe_to_free(mi_page_t *page)
114
0
{
115
0
    assert(mi_page_all_free(page));
116
#ifdef Py_GIL_DISABLED
117
    assert(page->qsbr_node.next == NULL);
118
    if (page->use_qsbr && page->qsbr_goal != 0) {
119
        _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
120
        if (tstate == NULL) {
121
            return false;
122
        }
123
        return _Py_qbsr_goal_reached(tstate->qsbr, page->qsbr_goal);
124
    }
125
#endif
126
0
    return true;
127
128
0
}
129
130
#ifdef Py_GIL_DISABLED
131
132
// If we are deferring collection of more than this amount of memory for
133
// mimalloc pages, advance the write sequence.  Advancing allows these
134
// pages to be re-used in a different thread or for a different size class.
135
#define QSBR_PAGE_MEM_LIMIT 4096*20
136
137
// Return true if the global write sequence should be advanced for a mimalloc
138
// page that is deferred from collection.
139
static bool
140
should_advance_qsbr_for_page(struct _qsbr_thread_state *qsbr, mi_page_t *page)
141
{
142
    size_t bsize = mi_page_block_size(page);
143
    size_t page_size = page->capacity*bsize;
144
    if (page_size > QSBR_PAGE_MEM_LIMIT) {
145
        qsbr->deferred_page_memory = 0;
146
        return true;
147
    }
148
    qsbr->deferred_page_memory += page_size;
149
    if (qsbr->deferred_page_memory > QSBR_PAGE_MEM_LIMIT) {
150
        qsbr->deferred_page_memory = 0;
151
        return true;
152
    }
153
    return false;
154
}
155
156
static _PyThreadStateImpl *
157
tstate_from_heap(mi_heap_t *heap)
158
{
159
    return _Py_CONTAINER_OF(heap->tld, _PyThreadStateImpl, mimalloc.tld);
160
}
161
#endif
162
163
static bool
164
_PyMem_mi_page_maybe_free(mi_page_t *page, mi_page_queue_t *pq, bool force)
165
0
{
166
#ifdef Py_GIL_DISABLED
167
    assert(mi_page_all_free(page));
168
    if (page->use_qsbr) {
169
        struct _qsbr_thread_state *qsbr = ((_PyThreadStateImpl *)PyThreadState_GET())->qsbr;
170
        if (page->qsbr_goal != 0 && _Py_qbsr_goal_reached(qsbr, page->qsbr_goal)) {
171
            _PyMem_mi_page_clear_qsbr(page);
172
            _mi_page_free(page, pq, force);
173
            return true;
174
        }
175
176
        // gh-145615: since we are not freeing this page yet, we want to
177
        // make it available for allocations. Note that the QSBR goal and
178
        // linked list node remain set even if the page is later used for
179
        // an allocation. We only detect and clear the QSBR goal when the
180
        // page becomes empty again (used == 0).
181
        if (mi_page_is_in_full(page)) {
182
            _mi_page_unfull(page);
183
        }
184
185
        _PyMem_mi_page_clear_qsbr(page);
186
        page->retire_expire = 0;
187
188
        if (should_advance_qsbr_for_page(qsbr, page)) {
189
            page->qsbr_goal = _Py_qsbr_advance(qsbr->shared);
190
        }
191
        else {
192
            page->qsbr_goal = _Py_qsbr_shared_next(qsbr->shared);
193
        }
194
195
        // We may be freeing a page belonging to a different thread during a
196
        // stop-the-world event. Find the _PyThreadStateImpl for the page.
197
        _PyThreadStateImpl *tstate = tstate_from_heap(mi_page_heap(page));
198
        llist_insert_tail(&tstate->mimalloc.page_list, &page->qsbr_node);
199
        return false;
200
    }
201
#endif
202
0
    _mi_page_free(page, pq, force);
203
0
    return true;
204
0
}
205
206
static void
207
_PyMem_mi_page_reclaimed(mi_page_t *page)
208
0
{
209
#ifdef Py_GIL_DISABLED
210
    assert(page->qsbr_node.next == NULL);
211
    if (page->qsbr_goal != 0) {
212
        if (mi_page_all_free(page)) {
213
            assert(page->qsbr_node.next == NULL);
214
            _PyThreadStateImpl *tstate = tstate_from_heap(mi_page_heap(page));
215
            // gh-159462: the owning tstate may differ from the current
216
            // one, but the heap is always owned by the current OS thread,
217
            // so the page list is not shared with other OS threads.
218
            assert(mi_page_heap(page)->thread_id == _Py_ThreadId());
219
            page->retire_expire = 0;
220
            llist_insert_tail(&tstate->mimalloc.page_list, &page->qsbr_node);
221
        }
222
        else {
223
            page->qsbr_goal = 0;
224
        }
225
    }
226
#endif
227
0
}
228
229
static void
230
_PyMem_mi_heap_collect_qsbr(mi_heap_t *heap)
231
0
{
232
#ifdef Py_GIL_DISABLED
233
    if (!heap->page_use_qsbr) {
234
        return;
235
    }
236
237
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
238
    struct llist_node *head = &tstate->mimalloc.page_list;
239
    if (llist_empty(head)) {
240
        return;
241
    }
242
243
    struct llist_node *node;
244
    llist_for_each_safe(node, head) {
245
        mi_page_t *page = llist_data(node, mi_page_t, qsbr_node);
246
        if (!mi_page_all_free(page)) {
247
            // We allocated from this page some point after the delayed free
248
            _PyMem_mi_page_clear_qsbr(page);
249
            continue;
250
        }
251
252
        if (!_Py_qsbr_poll(tstate->qsbr, page->qsbr_goal)) {
253
            return;
254
        }
255
256
        _PyMem_mi_page_clear_qsbr(page);
257
        _mi_page_free(page, mi_page_queue_of(page), false);
258
    }
259
#endif
260
0
}
261
262
void *
263
_PyMem_MiMalloc(void *ctx, size_t size)
264
0
{
265
#ifdef Py_GIL_DISABLED
266
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
267
    mi_heap_t *heap = &tstate->mimalloc.heaps[_Py_MIMALLOC_HEAP_MEM];
268
    return mi_heap_malloc(heap, size);
269
#else
270
0
    return mi_malloc(size);
271
0
#endif
272
0
}
273
274
void *
275
_PyMem_MiCalloc(void *ctx, size_t nelem, size_t elsize)
276
0
{
277
#ifdef Py_GIL_DISABLED
278
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
279
    mi_heap_t *heap = &tstate->mimalloc.heaps[_Py_MIMALLOC_HEAP_MEM];
280
    return mi_heap_calloc(heap, nelem, elsize);
281
#else
282
0
    return mi_calloc(nelem, elsize);
283
0
#endif
284
0
}
285
286
void *
287
_PyMem_MiRealloc(void *ctx, void *ptr, size_t size)
288
0
{
289
#ifdef Py_GIL_DISABLED
290
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
291
    mi_heap_t *heap = &tstate->mimalloc.heaps[_Py_MIMALLOC_HEAP_MEM];
292
    return mi_heap_realloc(heap, ptr, size);
293
#else
294
0
    return mi_realloc(ptr, size);
295
0
#endif
296
0
}
297
298
void
299
_PyMem_MiFree(void *ctx, void *ptr)
300
0
{
301
0
    mi_free(ptr);
302
0
}
303
304
void *
305
_PyObject_MiMalloc(void *ctx, size_t nbytes)
306
0
{
307
#ifdef Py_GIL_DISABLED
308
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
309
    mi_heap_t *heap = tstate->mimalloc.current_object_heap;
310
    return mi_heap_malloc(heap, nbytes);
311
#else
312
0
    return mi_malloc(nbytes);
313
0
#endif
314
0
}
315
316
void *
317
_PyObject_MiCalloc(void *ctx, size_t nelem, size_t elsize)
318
0
{
319
#ifdef Py_GIL_DISABLED
320
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
321
    mi_heap_t *heap = tstate->mimalloc.current_object_heap;
322
    return mi_heap_calloc(heap, nelem, elsize);
323
#else
324
0
    return mi_calloc(nelem, elsize);
325
0
#endif
326
0
}
327
328
329
void *
330
_PyObject_MiRealloc(void *ctx, void *ptr, size_t nbytes)
331
0
{
332
#ifdef Py_GIL_DISABLED
333
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
334
    // Implement our own realloc logic so that we can copy PyObject header
335
    // in a thread-safe way.
336
    size_t size = mi_usable_size(ptr);
337
    if (nbytes <= size && nbytes >= (size / 2) && nbytes > 0) {
338
        return ptr;
339
    }
340
341
    mi_heap_t *heap = tstate->mimalloc.current_object_heap;
342
    void* newp = mi_heap_malloc(heap, nbytes);
343
    if (newp == NULL) {
344
        return NULL;
345
    }
346
347
    // Free threaded Python allows access from other threads to the PyObject reference count
348
    // fields for a period of time after the object is freed (see InternalDocs/qsbr.md).
349
    // These fields are typically initialized by PyObject_Init() using relaxed
350
    // atomic stores. We need to copy these fields in a thread-safe way here.
351
    // We use the "debug_offset" to determine how many bytes to copy -- it
352
    // includes the PyObject header and plus any extra pre-headers.
353
    size_t offset = heap->debug_offset;
354
    assert(offset % sizeof(void*) == 0);
355
356
    size_t copy_size = (size < nbytes ? size : nbytes);
357
    if (copy_size >= offset) {
358
        for (size_t i = 0; i != offset; i += sizeof(void*)) {
359
            // Use memcpy to avoid strict-aliasing issues. However, we probably
360
            // still have unavoidable strict-aliasing issues with
361
            // _Py_atomic_store_ptr_relaxed here.
362
            void *word;
363
            memcpy(&word, (char*)ptr + i, sizeof(void*));
364
            _Py_atomic_store_ptr_relaxed((void**)((char*)newp + i), word);
365
        }
366
        _mi_memcpy((char*)newp + offset, (char*)ptr + offset, copy_size - offset);
367
    }
368
    else {
369
        // memcpy(dst, NULL, 0) is undefined behavior. See gh-151297.
370
        if mi_likely(ptr) {
371
            _mi_memcpy(newp, ptr, copy_size);
372
        }
373
    }
374
    mi_free(ptr);
375
    return newp;
376
#else
377
0
    return mi_realloc(ptr, nbytes);
378
0
#endif
379
0
}
380
381
void
382
_PyObject_MiFree(void *ctx, void *ptr)
383
0
{
384
0
    mi_free(ptr);
385
0
}
386
387
void *
388
_PyMem_MiRawMalloc(void *ctx, size_t size)
389
0
{
390
0
    return mi_malloc(size);
391
0
}
392
393
void *
394
_PyMem_MiRawCalloc(void *ctx, size_t nelem, size_t elsize)
395
0
{
396
0
    return mi_calloc(nelem, elsize);
397
0
}
398
399
void *
400
_PyMem_MiRawRealloc(void *ctx, void *ptr, size_t size)
401
0
{
402
0
    return mi_realloc(ptr, size);
403
0
}
404
405
void
406
_PyMem_MiRawFree(void *ctx, void *ptr)
407
0
{
408
0
    mi_free(ptr);
409
0
}
410
#endif // WITH_MIMALLOC
411
412
413
0
#define MALLOC_ALLOC {NULL, _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree}
414
415
416
#ifdef WITH_MIMALLOC
417
0
#  define MIMALLOC_ALLOC    {NULL, _PyMem_MiMalloc, _PyMem_MiCalloc, _PyMem_MiRealloc, _PyMem_MiFree}
418
0
#  define MIMALLOC_RAWALLOC {NULL, _PyMem_MiRawMalloc, _PyMem_MiRawCalloc, _PyMem_MiRawRealloc, _PyMem_MiRawFree}
419
0
#  define MIMALLOC_OBJALLOC {NULL, _PyObject_MiMalloc, _PyObject_MiCalloc, _PyObject_MiRealloc, _PyObject_MiFree}
420
#endif
421
422
/* the pymalloc allocator */
423
424
// The actual implementation is further down.
425
426
#if defined(WITH_PYMALLOC)
427
void* _PyObject_Malloc(void *ctx, size_t size);
428
void* _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize);
429
void _PyObject_Free(void *ctx, void *p);
430
void* _PyObject_Realloc(void *ctx, void *ptr, size_t size);
431
0
#  define PYMALLOC_ALLOC {NULL, _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free}
432
#endif  // WITH_PYMALLOC
433
434
#if defined(Py_GIL_DISABLED)
435
// Py_GIL_DISABLED requires using mimalloc for "mem" and "obj" domains.
436
#  define PYRAW_ALLOC MIMALLOC_RAWALLOC
437
#  define PYMEM_ALLOC MIMALLOC_ALLOC
438
#  define PYOBJ_ALLOC MIMALLOC_OBJALLOC
439
#elif defined(_Py_ADDRESS_SANITIZER) || defined(_Py_MEMORY_SANITIZER)
440
// ASan and MSan do not track pymalloc blocks, so use malloc by default.
441
// pymalloc can still be selected at runtime.
442
#  define PYRAW_ALLOC MALLOC_ALLOC
443
#  define PYMEM_ALLOC MALLOC_ALLOC
444
#  define PYOBJ_ALLOC MALLOC_ALLOC
445
#elif defined(WITH_PYMALLOC)
446
0
#  define PYRAW_ALLOC MALLOC_ALLOC
447
0
#  define PYMEM_ALLOC PYMALLOC_ALLOC
448
0
#  define PYOBJ_ALLOC PYMALLOC_ALLOC
449
#else
450
#  define PYRAW_ALLOC MALLOC_ALLOC
451
#  define PYMEM_ALLOC MALLOC_ALLOC
452
#  define PYOBJ_ALLOC MALLOC_ALLOC
453
#endif
454
455
456
/* the default debug allocators */
457
458
// The actual implementation is further down.
459
460
void* _PyMem_DebugRawMalloc(void *ctx, size_t size);
461
void* _PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize);
462
void* _PyMem_DebugRawRealloc(void *ctx, void *ptr, size_t size);
463
void _PyMem_DebugRawFree(void *ctx, void *ptr);
464
465
void* _PyMem_DebugMalloc(void *ctx, size_t size);
466
void* _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize);
467
void* _PyMem_DebugRealloc(void *ctx, void *ptr, size_t size);
468
void _PyMem_DebugFree(void *ctx, void *p);
469
470
#define PYDBGRAW_ALLOC \
471
0
    {&_PyRuntime.allocators.debug.raw, _PyMem_DebugRawMalloc, _PyMem_DebugRawCalloc, _PyMem_DebugRawRealloc, _PyMem_DebugRawFree}
472
#define PYDBGMEM_ALLOC \
473
0
    {&_PyRuntime.allocators.debug.mem, _PyMem_DebugMalloc, _PyMem_DebugCalloc, _PyMem_DebugRealloc, _PyMem_DebugFree}
474
#define PYDBGOBJ_ALLOC \
475
0
    {&_PyRuntime.allocators.debug.obj, _PyMem_DebugMalloc, _PyMem_DebugCalloc, _PyMem_DebugRealloc, _PyMem_DebugFree}
476
477
/* default raw allocator (not swappable) */
478
479
void *
480
_PyMem_DefaultRawMalloc(size_t size)
481
296
{
482
#ifdef Py_DEBUG
483
    return _PyMem_DebugRawMalloc(&_PyRuntime.allocators.debug.raw, size);
484
#else
485
296
    return _PyMem_RawMalloc(NULL, size);
486
296
#endif
487
296
}
488
489
void *
490
_PyMem_DefaultRawCalloc(size_t nelem, size_t elsize)
491
0
{
492
#ifdef Py_DEBUG
493
    return _PyMem_DebugRawCalloc(&_PyRuntime.allocators.debug.raw, nelem, elsize);
494
#else
495
0
    return _PyMem_RawCalloc(NULL, nelem, elsize);
496
0
#endif
497
0
}
498
499
void *
500
_PyMem_DefaultRawRealloc(void *ptr, size_t size)
501
0
{
502
#ifdef Py_DEBUG
503
    return _PyMem_DebugRawRealloc(&_PyRuntime.allocators.debug.raw, ptr, size);
504
#else
505
0
    return _PyMem_RawRealloc(NULL, ptr, size);
506
0
#endif
507
0
}
508
509
void
510
_PyMem_DefaultRawFree(void *ptr)
511
333
{
512
#ifdef Py_DEBUG
513
    _PyMem_DebugRawFree(&_PyRuntime.allocators.debug.raw, ptr);
514
#else
515
333
    _PyMem_RawFree(NULL, ptr);
516
333
#endif
517
333
}
518
519
wchar_t*
520
_PyMem_DefaultRawWcsdup(const wchar_t *str)
521
222
{
522
222
    assert(str != NULL);
523
524
222
    size_t len = wcslen(str);
525
222
    if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) {
526
0
        return NULL;
527
0
    }
528
529
222
    size_t size = (len + 1) * sizeof(wchar_t);
530
222
    wchar_t *str2 = _PyMem_DefaultRawMalloc(size);
531
222
    if (str2 == NULL) {
532
0
        return NULL;
533
0
    }
534
535
222
    memcpy(str2, str, size);
536
222
    return str2;
537
222
}
538
539
/* the low-level virtual memory allocator */
540
541
#ifdef WITH_PYMALLOC
542
#  ifdef MS_WINDOWS
543
#    include <windows.h>
544
#  elif defined(HAVE_MMAP)
545
#    include <sys/mman.h>
546
#    ifdef MAP_ANONYMOUS
547
#      define ARENAS_USE_MMAP
548
#    endif
549
#  endif
550
#endif
551
552
/* Return the system's default huge page size in bytes, or 0 if it
553
 * cannot be determined.  The result is cached after the first call.
554
 *
555
 * This is Linux-only (/proc/meminfo).  On other systems that define
556
 * MAP_HUGETLB the caller should skip huge pages gracefully. */
557
#if defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB)
558
static size_t
559
_pymalloc_system_hugepage_size(void)
560
{
561
    static size_t hp_size = 0;
562
    static int initialized = 0;
563
564
    if (initialized) {
565
        return hp_size;
566
    }
567
568
#ifdef __linux__
569
    FILE *f = fopen("/proc/meminfo", "r");
570
    if (f != NULL) {
571
        char line[256];
572
        while (fgets(line, sizeof(line), f)) {
573
            unsigned long size_kb;
574
            if (sscanf(line, "Hugepagesize: %lu kB", &size_kb) == 1) {
575
                hp_size = (size_t)size_kb * 1024;
576
                break;
577
            }
578
        }
579
        fclose(f);
580
    }
581
#endif
582
583
    initialized = 1;
584
    return hp_size;
585
}
586
#endif
587
588
#if (defined(MS_WINDOWS) && defined(PYMALLOC_USE_HUGEPAGES)) || \
589
    (defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB))
590
static size_t
591
_pymalloc_round_up_to_multiple(size_t size, size_t multiple)
592
{
593
    if (multiple == 0 || size == 0) {
594
        return size;
595
    }
596
597
    size_t remainder = size % multiple;
598
    if (remainder == 0) {
599
        return size;
600
    }
601
602
    size_t padding = multiple - remainder;
603
    if (size > SIZE_MAX - padding) {
604
        return 0;
605
    }
606
    return size + padding;
607
}
608
#endif
609
610
static size_t
611
_pymalloc_virtual_alloc_size(size_t size)
612
72.9k
{
613
#if defined(MS_WINDOWS) && defined(PYMALLOC_USE_HUGEPAGES)
614
    if (_PyRuntime.allocators.use_hugepages) {
615
        SIZE_T large_page_size = GetLargePageMinimum();
616
        if (large_page_size > 0) {
617
            return _pymalloc_round_up_to_multiple(size, (size_t)large_page_size);
618
        }
619
    }
620
#elif defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB)
621
    if (_PyRuntime.allocators.use_hugepages) {
622
        size_t hp_size = _pymalloc_system_hugepage_size();
623
        if (hp_size > 0) {
624
            return _pymalloc_round_up_to_multiple(size, hp_size);
625
        }
626
    }
627
#endif
628
72.9k
    return size;
629
72.9k
}
630
631
void *
632
_PyMem_ArenaAlloc(void *Py_UNUSED(ctx), size_t size)
633
46.4k
{
634
#ifdef MS_WINDOWS
635
#  ifdef PYMALLOC_USE_HUGEPAGES
636
    if (_PyRuntime.allocators.use_hugepages) {
637
        SIZE_T lp_size = GetLargePageMinimum();
638
        if (lp_size > 0 && size % lp_size == 0) {
639
            void *ptr = VirtualAlloc(NULL, size,
640
                            MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
641
                            PAGE_READWRITE);
642
            if (ptr != NULL)
643
                return ptr;
644
        }
645
    }
646
    /* Fall back to regular pages */
647
#  endif
648
    return VirtualAlloc(NULL, size,
649
                        MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
650
#elif defined(ARENAS_USE_MMAP)
651
    void *ptr;
652
#  ifdef PYMALLOC_USE_HUGEPAGES
653
#    ifdef MAP_HUGETLB
654
    if (_PyRuntime.allocators.use_hugepages) {
655
        size_t hp_size = _pymalloc_system_hugepage_size();
656
        /* Only use huge pages if the arena size is a multiple of the
657
         * system's default huge page size.  When the arena is smaller
658
         * than the huge page, mmap still succeeds but silently
659
         * allocates an entire huge page; the subsequent munmap with
660
         * the smaller arena size then fails with EINVAL, leaking
661
         * all of that memory. */
662
        if (hp_size > 0 && size % hp_size == 0) {
663
            ptr = mmap(NULL, size, PROT_READ|PROT_WRITE,
664
                       MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0);
665
            if (ptr != MAP_FAILED) {
666
                assert(ptr != NULL);
667
                (void)_PyAnnotateMemoryMap(ptr, size, "cpython:pymalloc:hugepage");
668
                return ptr;
669
            }
670
        }
671
    }
672
    /* Fall back to regular pages */
673
#    endif
674
#  endif
675
46.4k
    ptr = mmap(NULL, size, PROT_READ|PROT_WRITE,
676
46.4k
               MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
677
46.4k
    if (ptr == MAP_FAILED)
678
0
        return NULL;
679
46.4k
    assert(ptr != NULL);
680
46.4k
#ifdef MADV_HUGEPAGE
681
46.4k
    (void)madvise(ptr, size, MADV_HUGEPAGE);
682
46.4k
#endif
683
46.4k
    (void)_PyAnnotateMemoryMap(ptr, size, "cpython:pymalloc");
684
46.4k
    return ptr;
685
#else
686
    return malloc(size);
687
#endif
688
46.4k
}
689
690
void
691
_PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr,
692
#if defined(ARENAS_USE_MMAP)
693
    size_t size
694
#else
695
    size_t Py_UNUSED(size)
696
#endif
697
)
698
45.9k
{
699
#ifdef MS_WINDOWS
700
    /* Unlike free(), VirtualFree() does not special-case NULL to noop. */
701
    if (ptr == NULL) {
702
        return;
703
    }
704
    VirtualFree(ptr, 0, MEM_RELEASE);
705
#elif defined(ARENAS_USE_MMAP)
706
    /* Unlike free(), munmap() does not special-case NULL to noop. */
707
45.9k
    if (ptr == NULL) {
708
0
        return;
709
0
    }
710
45.9k
    if (munmap(ptr, size) < 0) {
711
0
        _Py_FatalErrorFormat(__func__,
712
0
                             "munmap(%p, %zu) failed with errno %d",
713
0
                             ptr, size, errno);
714
0
    }
715
#else
716
    free(ptr);
717
#endif
718
45.9k
}
719
720
/*******************************************/
721
/* end low-level allocator implementations */
722
/*******************************************/
723
724
725
74
#define ALLOCATORS_MUTEX (_PyRuntime.allocators.mutex)
726
795M
#define _PyMem_Raw (_PyRuntime.allocators.standard.raw)
727
2.10G
#define _PyMem (_PyRuntime.allocators.standard.mem)
728
6.24G
#define _PyObject (_PyRuntime.allocators.standard.obj)
729
0
#define _PyMem_Debug (_PyRuntime.allocators.debug)
730
184k
#define _PyObject_Arena (_PyRuntime.allocators.obj_arena)
731
732
733
/***************************/
734
/* managing the allocators */
735
/***************************/
736
737
static int
738
set_default_allocator_unlocked(PyMemAllocatorDomain domain, int debug,
739
                               PyMemAllocatorEx *old_alloc)
740
0
{
741
0
    if (old_alloc != NULL) {
742
0
        get_allocator_unlocked(domain, old_alloc);
743
0
    }
744
745
746
0
    PyMemAllocatorEx new_alloc;
747
0
    switch(domain)
748
0
    {
749
0
    case PYMEM_DOMAIN_RAW:
750
0
        new_alloc = (PyMemAllocatorEx)PYRAW_ALLOC;
751
0
        break;
752
0
    case PYMEM_DOMAIN_MEM:
753
0
        new_alloc = (PyMemAllocatorEx)PYMEM_ALLOC;
754
0
        break;
755
0
    case PYMEM_DOMAIN_OBJ:
756
0
        new_alloc = (PyMemAllocatorEx)PYOBJ_ALLOC;
757
0
        break;
758
0
    default:
759
        /* unknown domain */
760
0
        return -1;
761
0
    }
762
0
    set_allocator_unlocked(domain, &new_alloc);
763
0
    if (debug) {
764
0
        set_up_debug_hooks_domain_unlocked(domain);
765
0
    }
766
0
    return 0;
767
0
}
768
769
770
#ifdef Py_DEBUG
771
static const int pydebug = 1;
772
#else
773
static const int pydebug = 0;
774
#endif
775
776
int
777
_PyMem_GetAllocatorName(const char *name, PyMemAllocatorName *allocator)
778
0
{
779
0
    if (name == NULL || *name == '\0') {
780
        /* PYTHONMALLOC is empty or is not set or ignored (-E/-I command line
781
           nameions): use default memory allocators */
782
0
        *allocator = PYMEM_ALLOCATOR_DEFAULT;
783
0
    }
784
0
    else if (strcmp(name, "default") == 0) {
785
0
        *allocator = PYMEM_ALLOCATOR_DEFAULT;
786
0
    }
787
0
    else if (strcmp(name, "debug") == 0) {
788
0
        *allocator = PYMEM_ALLOCATOR_DEBUG;
789
0
    }
790
0
#if defined(WITH_PYMALLOC) && !defined(Py_GIL_DISABLED)
791
0
    else if (strcmp(name, "pymalloc") == 0) {
792
0
        *allocator = PYMEM_ALLOCATOR_PYMALLOC;
793
0
    }
794
0
    else if (strcmp(name, "pymalloc_debug") == 0) {
795
0
        *allocator = PYMEM_ALLOCATOR_PYMALLOC_DEBUG;
796
0
    }
797
0
#endif
798
0
#ifdef WITH_MIMALLOC
799
0
    else if (strcmp(name, "mimalloc") == 0) {
800
0
        *allocator = PYMEM_ALLOCATOR_MIMALLOC;
801
0
    }
802
0
    else if (strcmp(name, "mimalloc_debug") == 0) {
803
0
        *allocator = PYMEM_ALLOCATOR_MIMALLOC_DEBUG;
804
0
    }
805
0
#endif
806
0
#ifndef Py_GIL_DISABLED
807
0
    else if (strcmp(name, "malloc") == 0) {
808
0
        *allocator = PYMEM_ALLOCATOR_MALLOC;
809
0
    }
810
0
    else if (strcmp(name, "malloc_debug") == 0) {
811
0
        *allocator = PYMEM_ALLOCATOR_MALLOC_DEBUG;
812
0
    }
813
0
#endif
814
0
    else {
815
        /* unknown allocator */
816
0
        return -1;
817
0
    }
818
0
    return 0;
819
0
}
820
821
822
static int
823
set_up_allocators_unlocked(PyMemAllocatorName allocator)
824
0
{
825
0
    switch (allocator) {
826
0
    case PYMEM_ALLOCATOR_NOT_SET:
827
        /* do nothing */
828
0
        break;
829
830
0
    case PYMEM_ALLOCATOR_DEFAULT:
831
0
        (void)set_default_allocator_unlocked(PYMEM_DOMAIN_RAW, pydebug, NULL);
832
0
        (void)set_default_allocator_unlocked(PYMEM_DOMAIN_MEM, pydebug, NULL);
833
0
        (void)set_default_allocator_unlocked(PYMEM_DOMAIN_OBJ, pydebug, NULL);
834
0
        _PyRuntime.allocators.is_debug_enabled = pydebug;
835
0
        break;
836
837
0
    case PYMEM_ALLOCATOR_DEBUG:
838
0
        (void)set_default_allocator_unlocked(PYMEM_DOMAIN_RAW, 1, NULL);
839
0
        (void)set_default_allocator_unlocked(PYMEM_DOMAIN_MEM, 1, NULL);
840
0
        (void)set_default_allocator_unlocked(PYMEM_DOMAIN_OBJ, 1, NULL);
841
0
        _PyRuntime.allocators.is_debug_enabled = 1;
842
0
        break;
843
844
0
#ifdef WITH_PYMALLOC
845
0
    case PYMEM_ALLOCATOR_PYMALLOC:
846
0
    case PYMEM_ALLOCATOR_PYMALLOC_DEBUG:
847
0
    {
848
0
        PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC;
849
0
        set_allocator_unlocked(PYMEM_DOMAIN_RAW, &malloc_alloc);
850
851
0
        PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC;
852
0
        set_allocator_unlocked(PYMEM_DOMAIN_MEM, &pymalloc);
853
0
        set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &pymalloc);
854
855
0
        int is_debug = (allocator == PYMEM_ALLOCATOR_PYMALLOC_DEBUG);
856
0
        _PyRuntime.allocators.is_debug_enabled = is_debug;
857
0
        if (is_debug) {
858
0
            set_up_debug_hooks_unlocked();
859
0
        }
860
0
        break;
861
0
    }
862
0
#endif
863
0
#ifdef WITH_MIMALLOC
864
0
    case PYMEM_ALLOCATOR_MIMALLOC:
865
0
    case PYMEM_ALLOCATOR_MIMALLOC_DEBUG:
866
0
    {
867
0
        PyMemAllocatorEx malloc_alloc = MIMALLOC_RAWALLOC;
868
0
        set_allocator_unlocked(PYMEM_DOMAIN_RAW, &malloc_alloc);
869
870
0
        PyMemAllocatorEx pymalloc = MIMALLOC_ALLOC;
871
0
        set_allocator_unlocked(PYMEM_DOMAIN_MEM, &pymalloc);
872
873
0
        PyMemAllocatorEx objmalloc = MIMALLOC_OBJALLOC;
874
0
        set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &objmalloc);
875
876
0
        int is_debug = (allocator == PYMEM_ALLOCATOR_MIMALLOC_DEBUG);
877
0
        _PyRuntime.allocators.is_debug_enabled = is_debug;
878
0
        if (is_debug) {
879
0
            set_up_debug_hooks_unlocked();
880
0
        }
881
882
0
        break;
883
0
    }
884
0
#endif
885
886
0
    case PYMEM_ALLOCATOR_MALLOC:
887
0
    case PYMEM_ALLOCATOR_MALLOC_DEBUG:
888
0
    {
889
0
        PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC;
890
0
        set_allocator_unlocked(PYMEM_DOMAIN_RAW, &malloc_alloc);
891
0
        set_allocator_unlocked(PYMEM_DOMAIN_MEM, &malloc_alloc);
892
0
        set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &malloc_alloc);
893
894
0
        int is_debug = (allocator == PYMEM_ALLOCATOR_MALLOC_DEBUG);
895
0
        _PyRuntime.allocators.is_debug_enabled = is_debug;
896
0
        if (is_debug) {
897
0
            set_up_debug_hooks_unlocked();
898
0
        }
899
0
        break;
900
0
    }
901
902
0
    default:
903
        /* unknown allocator */
904
0
        return -1;
905
0
    }
906
907
0
    return 0;
908
0
}
909
910
int
911
_PyMem_SetupAllocators(PyMemAllocatorName allocator)
912
0
{
913
0
    PyMutex_Lock(&ALLOCATORS_MUTEX);
914
0
    int res = set_up_allocators_unlocked(allocator);
915
0
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
916
0
    return res;
917
0
}
918
919
920
static int
921
pymemallocator_eq(PyMemAllocatorEx *a, PyMemAllocatorEx *b)
922
0
{
923
0
    return (memcmp(a, b, sizeof(PyMemAllocatorEx)) == 0);
924
0
}
925
926
927
static const char*
928
get_current_allocator_name_unlocked(void)
929
0
{
930
0
    PyMemAllocatorEx malloc_alloc = MALLOC_ALLOC;
931
0
#ifdef WITH_PYMALLOC
932
0
    PyMemAllocatorEx pymalloc = PYMALLOC_ALLOC;
933
0
#endif
934
0
#ifdef WITH_MIMALLOC
935
0
    PyMemAllocatorEx mimalloc = MIMALLOC_ALLOC;
936
0
    PyMemAllocatorEx mimalloc_obj = MIMALLOC_OBJALLOC;
937
0
    PyMemAllocatorEx mimalloc_raw = MIMALLOC_RAWALLOC;
938
0
#endif
939
940
0
    if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) &&
941
0
        pymemallocator_eq(&_PyMem, &malloc_alloc) &&
942
0
        pymemallocator_eq(&_PyObject, &malloc_alloc))
943
0
    {
944
0
        return "malloc";
945
0
    }
946
0
#ifdef WITH_PYMALLOC
947
0
    if (pymemallocator_eq(&_PyMem_Raw, &malloc_alloc) &&
948
0
        pymemallocator_eq(&_PyMem, &pymalloc) &&
949
0
        pymemallocator_eq(&_PyObject, &pymalloc))
950
0
    {
951
0
        return "pymalloc";
952
0
    }
953
0
#endif
954
0
#ifdef WITH_MIMALLOC
955
0
    if (pymemallocator_eq(&_PyMem_Raw, &mimalloc_raw) &&
956
0
        pymemallocator_eq(&_PyMem, &mimalloc) &&
957
0
        pymemallocator_eq(&_PyObject, &mimalloc_obj))
958
0
    {
959
0
        return "mimalloc";
960
0
    }
961
0
#endif
962
963
0
    PyMemAllocatorEx dbg_raw = PYDBGRAW_ALLOC;
964
0
    PyMemAllocatorEx dbg_mem = PYDBGMEM_ALLOC;
965
0
    PyMemAllocatorEx dbg_obj = PYDBGOBJ_ALLOC;
966
967
0
    if (pymemallocator_eq(&_PyMem_Raw, &dbg_raw) &&
968
0
        pymemallocator_eq(&_PyMem, &dbg_mem) &&
969
0
        pymemallocator_eq(&_PyObject, &dbg_obj))
970
0
    {
971
        /* Debug hooks installed */
972
0
        if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &malloc_alloc) &&
973
0
            pymemallocator_eq(&_PyMem_Debug.mem.alloc, &malloc_alloc) &&
974
0
            pymemallocator_eq(&_PyMem_Debug.obj.alloc, &malloc_alloc))
975
0
        {
976
0
            return "malloc_debug";
977
0
        }
978
0
#ifdef WITH_PYMALLOC
979
0
        if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &malloc_alloc) &&
980
0
            pymemallocator_eq(&_PyMem_Debug.mem.alloc, &pymalloc) &&
981
0
            pymemallocator_eq(&_PyMem_Debug.obj.alloc, &pymalloc))
982
0
        {
983
0
            return "pymalloc_debug";
984
0
        }
985
0
#endif
986
0
#ifdef WITH_MIMALLOC
987
0
        if (pymemallocator_eq(&_PyMem_Debug.raw.alloc, &mimalloc_raw) &&
988
0
            pymemallocator_eq(&_PyMem_Debug.mem.alloc, &mimalloc) &&
989
0
            pymemallocator_eq(&_PyMem_Debug.obj.alloc, &mimalloc_obj))
990
0
        {
991
0
            return "mimalloc_debug";
992
0
        }
993
0
#endif
994
0
    }
995
0
    return NULL;
996
0
}
997
998
const char*
999
_PyMem_GetCurrentAllocatorName(void)
1000
0
{
1001
0
    PyMutex_Lock(&ALLOCATORS_MUTEX);
1002
0
    const char *name = get_current_allocator_name_unlocked();
1003
0
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
1004
0
    return name;
1005
0
}
1006
1007
1008
int
1009
_PyMem_DebugEnabled(void)
1010
0
{
1011
0
    return _PyRuntime.allocators.is_debug_enabled;
1012
0
}
1013
1014
#ifdef WITH_PYMALLOC
1015
static int
1016
_PyMem_PymallocEnabled(void)
1017
0
{
1018
0
    if (_PyMem_DebugEnabled()) {
1019
0
        return (_PyMem_Debug.obj.alloc.malloc == _PyObject_Malloc);
1020
0
    }
1021
0
    else {
1022
0
        return (_PyObject.malloc == _PyObject_Malloc);
1023
0
    }
1024
0
}
1025
1026
#ifdef WITH_MIMALLOC
1027
static int
1028
_PyMem_MimallocEnabled(void)
1029
0
{
1030
#ifdef Py_GIL_DISABLED
1031
    return 1;
1032
#else
1033
0
    if (_PyMem_DebugEnabled()) {
1034
0
        return (_PyMem_Debug.obj.alloc.malloc == _PyObject_MiMalloc);
1035
0
    }
1036
0
    else {
1037
0
        return (_PyObject.malloc == _PyObject_MiMalloc);
1038
0
    }
1039
0
#endif
1040
0
}
1041
#endif  // WITH_MIMALLOC
1042
1043
#endif  // WITH_PYMALLOC
1044
1045
1046
static void
1047
set_up_debug_hooks_domain_unlocked(PyMemAllocatorDomain domain)
1048
0
{
1049
0
    PyMemAllocatorEx alloc;
1050
1051
0
    if (domain == PYMEM_DOMAIN_RAW) {
1052
0
        if (_PyMem_Raw.malloc == _PyMem_DebugRawMalloc) {
1053
0
            return;
1054
0
        }
1055
1056
0
        get_allocator_unlocked(domain, &_PyMem_Debug.raw.alloc);
1057
0
        alloc.ctx = &_PyMem_Debug.raw;
1058
0
        alloc.malloc = _PyMem_DebugRawMalloc;
1059
0
        alloc.calloc = _PyMem_DebugRawCalloc;
1060
0
        alloc.realloc = _PyMem_DebugRawRealloc;
1061
0
        alloc.free = _PyMem_DebugRawFree;
1062
0
        set_allocator_unlocked(domain, &alloc);
1063
0
    }
1064
0
    else if (domain == PYMEM_DOMAIN_MEM) {
1065
0
        if (_PyMem.malloc == _PyMem_DebugMalloc) {
1066
0
            return;
1067
0
        }
1068
1069
0
        get_allocator_unlocked(domain, &_PyMem_Debug.mem.alloc);
1070
0
        alloc.ctx = &_PyMem_Debug.mem;
1071
0
        alloc.malloc = _PyMem_DebugMalloc;
1072
0
        alloc.calloc = _PyMem_DebugCalloc;
1073
0
        alloc.realloc = _PyMem_DebugRealloc;
1074
0
        alloc.free = _PyMem_DebugFree;
1075
0
        set_allocator_unlocked(domain, &alloc);
1076
0
    }
1077
0
    else if (domain == PYMEM_DOMAIN_OBJ)  {
1078
0
        if (_PyObject.malloc == _PyMem_DebugMalloc) {
1079
0
            return;
1080
0
        }
1081
1082
0
        get_allocator_unlocked(domain, &_PyMem_Debug.obj.alloc);
1083
0
        alloc.ctx = &_PyMem_Debug.obj;
1084
0
        alloc.malloc = _PyMem_DebugMalloc;
1085
0
        alloc.calloc = _PyMem_DebugCalloc;
1086
0
        alloc.realloc = _PyMem_DebugRealloc;
1087
0
        alloc.free = _PyMem_DebugFree;
1088
0
        set_allocator_unlocked(domain, &alloc);
1089
0
    }
1090
0
}
1091
1092
1093
static void
1094
set_up_debug_hooks_unlocked(void)
1095
0
{
1096
0
    set_up_debug_hooks_domain_unlocked(PYMEM_DOMAIN_RAW);
1097
0
    set_up_debug_hooks_domain_unlocked(PYMEM_DOMAIN_MEM);
1098
0
    set_up_debug_hooks_domain_unlocked(PYMEM_DOMAIN_OBJ);
1099
0
    _PyRuntime.allocators.is_debug_enabled = 1;
1100
0
}
1101
1102
void
1103
PyMem_SetupDebugHooks(void)
1104
0
{
1105
0
    PyMutex_Lock(&ALLOCATORS_MUTEX);
1106
0
    set_up_debug_hooks_unlocked();
1107
0
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
1108
0
}
1109
1110
static void
1111
get_allocator_unlocked(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
1112
37
{
1113
37
    switch(domain)
1114
37
    {
1115
37
    case PYMEM_DOMAIN_RAW: *allocator = _PyMem_Raw; break;
1116
0
    case PYMEM_DOMAIN_MEM: *allocator = _PyMem; break;
1117
0
    case PYMEM_DOMAIN_OBJ: *allocator = _PyObject; break;
1118
0
    default:
1119
        /* unknown domain: set all attributes to NULL */
1120
0
        allocator->ctx = NULL;
1121
0
        allocator->malloc = NULL;
1122
0
        allocator->calloc = NULL;
1123
0
        allocator->realloc = NULL;
1124
0
        allocator->free = NULL;
1125
37
    }
1126
37
}
1127
1128
static void
1129
set_allocator_unlocked(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
1130
0
{
1131
0
    switch(domain)
1132
0
    {
1133
0
    case PYMEM_DOMAIN_RAW: _PyMem_Raw = *allocator; break;
1134
0
    case PYMEM_DOMAIN_MEM: _PyMem = *allocator; break;
1135
0
    case PYMEM_DOMAIN_OBJ: _PyObject = *allocator; break;
1136
    /* ignore unknown domain */
1137
0
    }
1138
0
}
1139
1140
void
1141
PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
1142
37
{
1143
37
    PyMutex_Lock(&ALLOCATORS_MUTEX);
1144
37
    get_allocator_unlocked(domain, allocator);
1145
37
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
1146
37
}
1147
1148
void
1149
PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
1150
0
{
1151
0
    PyMutex_Lock(&ALLOCATORS_MUTEX);
1152
0
    set_allocator_unlocked(domain, allocator);
1153
0
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
1154
0
}
1155
1156
void
1157
PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)
1158
0
{
1159
0
    PyMutex_Lock(&ALLOCATORS_MUTEX);
1160
0
    *allocator = _PyObject_Arena;
1161
0
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
1162
0
}
1163
1164
void
1165
PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)
1166
0
{
1167
0
    PyMutex_Lock(&ALLOCATORS_MUTEX);
1168
0
    _PyObject_Arena = *allocator;
1169
0
    PyMutex_Unlock(&ALLOCATORS_MUTEX);
1170
0
}
1171
1172
1173
/* Note that there is a possible, but very unlikely, race in any place
1174
 * below where we call one of the allocator functions.  We access two
1175
 * fields in each case:  "malloc", etc. and "ctx".
1176
 *
1177
 * It is unlikely that the allocator will be changed while one of those
1178
 * calls is happening, much less in that very narrow window.
1179
 * Furthermore, the likelihood of a race is drastically reduced by the
1180
 * fact that the allocator may not be changed after runtime init
1181
 * (except with a wrapper).
1182
 *
1183
 * With the above in mind, we currently don't worry about locking
1184
 * around these uses of the runtime-global allocators state. */
1185
1186
1187
/*************************/
1188
/* the "arena" allocator */
1189
/*************************/
1190
1191
void *
1192
_PyObject_VirtualAlloc(size_t size)
1193
36.5k
{
1194
36.5k
    size_t alloc_size = _pymalloc_virtual_alloc_size(size);
1195
36.5k
    if (alloc_size == 0 && size != 0) {
1196
0
        return NULL;
1197
0
    }
1198
36.5k
    return _PyObject_Arena.alloc(_PyObject_Arena.ctx, alloc_size);
1199
36.5k
}
1200
1201
void
1202
_PyObject_VirtualFree(void *obj, size_t size)
1203
36.4k
{
1204
36.4k
    size_t alloc_size = _pymalloc_virtual_alloc_size(size);
1205
36.4k
    assert(alloc_size != 0 || size == 0);
1206
36.4k
    _PyObject_Arena.free(_PyObject_Arena.ctx, obj, alloc_size);
1207
36.4k
}
1208
1209
1210
/***********************/
1211
/* the "raw" allocator */
1212
/***********************/
1213
1214
void *
1215
PyMem_RawMalloc(size_t size)
1216
193M
{
1217
    /*
1218
     * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.
1219
     * Most python internals blindly use a signed Py_ssize_t to track
1220
     * things without checking for overflows or negatives.
1221
     * As size_t is unsigned, checking for size < 0 is not required.
1222
     */
1223
193M
    if (size > (size_t)PY_SSIZE_T_MAX)
1224
0
        return NULL;
1225
193M
    return _PyMem_Raw.malloc(_PyMem_Raw.ctx, size);
1226
193M
}
1227
1228
void *
1229
PyMem_RawCalloc(size_t nelem, size_t elsize)
1230
202k
{
1231
    /* see PyMem_RawMalloc() */
1232
202k
    if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize)
1233
0
        return NULL;
1234
202k
    return _PyMem_Raw.calloc(_PyMem_Raw.ctx, nelem, elsize);
1235
202k
}
1236
1237
void*
1238
PyMem_RawRealloc(void *ptr, size_t new_size)
1239
10.6M
{
1240
    /* see PyMem_RawMalloc() */
1241
10.6M
    if (new_size > (size_t)PY_SSIZE_T_MAX)
1242
0
        return NULL;
1243
10.6M
    return _PyMem_Raw.realloc(_PyMem_Raw.ctx, ptr, new_size);
1244
10.6M
}
1245
1246
void PyMem_RawFree(void *ptr)
1247
193M
{
1248
193M
    _PyMem_Raw.free(_PyMem_Raw.ctx, ptr);
1249
193M
}
1250
1251
1252
/***********************/
1253
/* the "mem" allocator */
1254
/***********************/
1255
1256
void *
1257
PyMem_Malloc(size_t size)
1258
212M
{
1259
    /* see PyMem_RawMalloc() */
1260
212M
    if (size > (size_t)PY_SSIZE_T_MAX)
1261
0
        return NULL;
1262
212M
    OBJECT_STAT_INC_COND(allocations512, size < 512);
1263
212M
    OBJECT_STAT_INC_COND(allocations4k, size >= 512 && size < 4094);
1264
212M
    OBJECT_STAT_INC_COND(allocations_big, size >= 4094);
1265
212M
    OBJECT_STAT_INC(allocations);
1266
212M
    return _PyMem.malloc(_PyMem.ctx, size);
1267
212M
}
1268
1269
void *
1270
PyMem_Calloc(size_t nelem, size_t elsize)
1271
47.5M
{
1272
    /* see PyMem_RawMalloc() */
1273
47.5M
    if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize)
1274
0
        return NULL;
1275
47.5M
    OBJECT_STAT_INC_COND(allocations512, elsize < 512);
1276
47.5M
    OBJECT_STAT_INC_COND(allocations4k, elsize >= 512 && elsize < 4094);
1277
47.5M
    OBJECT_STAT_INC_COND(allocations_big, elsize >= 4094);
1278
47.5M
    OBJECT_STAT_INC(allocations);
1279
47.5M
    return _PyMem.calloc(_PyMem.ctx, nelem, elsize);
1280
47.5M
}
1281
1282
void *
1283
PyMem_Realloc(void *ptr, size_t new_size)
1284
254M
{
1285
    /* see PyMem_RawMalloc() */
1286
254M
    if (new_size > (size_t)PY_SSIZE_T_MAX)
1287
0
        return NULL;
1288
254M
    return _PyMem.realloc(_PyMem.ctx, ptr, new_size);
1289
254M
}
1290
1291
void
1292
PyMem_Free(void *ptr)
1293
536M
{
1294
536M
    OBJECT_STAT_INC(frees);
1295
536M
    _PyMem.free(_PyMem.ctx, ptr);
1296
536M
}
1297
1298
1299
/***************************/
1300
/* pymem utility functions */
1301
/***************************/
1302
1303
wchar_t*
1304
_PyMem_RawWcsdup(const wchar_t *str)
1305
1.48k
{
1306
1.48k
    assert(str != NULL);
1307
1308
1.48k
    size_t len = wcslen(str);
1309
1.48k
    if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) {
1310
0
        return NULL;
1311
0
    }
1312
1313
1.48k
    size_t size = (len + 1) * sizeof(wchar_t);
1314
1.48k
    wchar_t *str2 = PyMem_RawMalloc(size);
1315
1.48k
    if (str2 == NULL) {
1316
0
        return NULL;
1317
0
    }
1318
1319
1.48k
    memcpy(str2, str, size);
1320
1.48k
    return str2;
1321
1.48k
}
1322
1323
char *
1324
_PyMem_RawStrdup(const char *str)
1325
111
{
1326
111
    assert(str != NULL);
1327
111
    size_t size = strlen(str) + 1;
1328
111
    char *copy = PyMem_RawMalloc(size);
1329
111
    if (copy == NULL) {
1330
0
        return NULL;
1331
0
    }
1332
111
    memcpy(copy, str, size);
1333
111
    return copy;
1334
111
}
1335
1336
char *
1337
_PyMem_Strdup(const char *str)
1338
10
{
1339
10
    assert(str != NULL);
1340
10
    size_t size = strlen(str) + 1;
1341
10
    char *copy = PyMem_Malloc(size);
1342
10
    if (copy == NULL) {
1343
0
        return NULL;
1344
0
    }
1345
10
    memcpy(copy, str, size);
1346
10
    return copy;
1347
10
}
1348
1349
/***********************************************/
1350
/* Delayed freeing support for Py_GIL_DISABLED */
1351
/***********************************************/
1352
1353
// So that sizeof(struct _mem_work_chunk) is 4096 bytes on 64-bit platforms.
1354
#define WORK_ITEMS_PER_CHUNK 254
1355
1356
// A pointer to be freed once the QSBR read sequence reaches qsbr_goal.
1357
struct _mem_work_item {
1358
    uintptr_t ptr; // lowest bit tagged 1 for objects freed with PyObject_Free
1359
    uint64_t qsbr_goal;
1360
};
1361
1362
// A fixed-size buffer of pointers to be freed
1363
struct _mem_work_chunk {
1364
    // Linked list node of chunks in queue
1365
    struct llist_node node;
1366
1367
    Py_ssize_t rd_idx;  // index of next item to read
1368
    Py_ssize_t wr_idx;  // index of next item to write
1369
    struct _mem_work_item array[WORK_ITEMS_PER_CHUNK];
1370
};
1371
1372
static int
1373
work_item_should_decref(uintptr_t ptr)
1374
1.52M
{
1375
1.52M
    return ptr & 0x01;
1376
1.52M
}
1377
1378
static void
1379
free_work_item(uintptr_t ptr, delayed_dealloc_cb cb, void *state)
1380
1.52M
{
1381
1.52M
    if (work_item_should_decref(ptr)) {
1382
0
        PyObject *obj = (PyObject *)(ptr - 1);
1383
#ifdef Py_GIL_DISABLED
1384
        if (cb == NULL) {
1385
            assert(!_PyInterpreterState_GET()->stoptheworld.world_stopped);
1386
            Py_DECREF(obj);
1387
            return;
1388
        }
1389
        assert(_PyInterpreterState_GET()->stoptheworld.world_stopped);
1390
        if (_Py_IsImmortal(obj)) {
1391
            // The object may have become immortal after it was queued.
1392
            return;
1393
        }
1394
        Py_ssize_t refcount = _Py_ExplicitMergeRefcount(obj, -1);
1395
        if (refcount == 0) {
1396
            cb(obj, state);
1397
        }
1398
#else
1399
0
        Py_DECREF(obj);
1400
0
#endif
1401
0
    }
1402
1.52M
    else {
1403
1.52M
        PyMem_Free((void *)ptr);
1404
1.52M
    }
1405
1.52M
}
1406
1407
1408
#ifdef Py_GIL_DISABLED
1409
1410
// For deferred advance on free: the number of deferred items before advancing
1411
// the write sequence.  This is based on WORK_ITEMS_PER_CHUNK.  We ideally
1412
// want to process a chunk before it overflows.
1413
#define QSBR_DEFERRED_LIMIT 127
1414
1415
// If the deferred memory exceeds 1 MiB, advance the write sequence.  This
1416
// helps limit memory usage due to QSBR delaying frees too long.
1417
#define QSBR_FREE_MEM_LIMIT 1024*1024
1418
1419
// Return true if the global write sequence should be advanced for a deferred
1420
// memory free.
1421
static bool
1422
should_advance_qsbr_for_free(struct _qsbr_thread_state *qsbr, size_t size)
1423
{
1424
    if (size > QSBR_FREE_MEM_LIMIT) {
1425
        qsbr->deferred_count = 0;
1426
        qsbr->deferred_memory = 0;
1427
        qsbr->should_process = true;
1428
        return true;
1429
    }
1430
    qsbr->deferred_count++;
1431
    qsbr->deferred_memory += size;
1432
    if (qsbr->deferred_count > QSBR_DEFERRED_LIMIT ||
1433
            qsbr->deferred_memory > QSBR_FREE_MEM_LIMIT) {
1434
        qsbr->deferred_count = 0;
1435
        qsbr->deferred_memory = 0;
1436
        qsbr->should_process = true;
1437
        return true;
1438
    }
1439
    return false;
1440
}
1441
#endif
1442
1443
static void
1444
free_delayed(uintptr_t ptr, size_t size)
1445
1.52M
{
1446
1.52M
#ifndef Py_GIL_DISABLED
1447
1.52M
    free_work_item(ptr, NULL, NULL);
1448
#else
1449
    PyInterpreterState *interp = _PyInterpreterState_GET();
1450
    if (_PyInterpreterState_GetFinalizing(interp) != NULL ||
1451
        interp->stoptheworld.world_stopped)
1452
    {
1453
        // Free immediately during interpreter shutdown or if the world is
1454
        // stopped.
1455
        assert(!interp->stoptheworld.world_stopped || !work_item_should_decref(ptr));
1456
        free_work_item(ptr, NULL, NULL);
1457
        return;
1458
    }
1459
1460
    _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
1461
    struct llist_node *head = &tstate->mem_free_queue;
1462
1463
    struct _mem_work_chunk *buf = NULL;
1464
    if (!llist_empty(head)) {
1465
        // Try to re-use the last buffer
1466
        buf = llist_data(head->prev, struct _mem_work_chunk, node);
1467
        if (buf->wr_idx == WORK_ITEMS_PER_CHUNK) {
1468
            // already full
1469
            buf = NULL;
1470
        }
1471
    }
1472
1473
    if (buf == NULL) {
1474
        buf = PyMem_Calloc(1, sizeof(*buf));
1475
        if (buf != NULL) {
1476
            llist_insert_tail(head, &buf->node);
1477
        }
1478
    }
1479
1480
    if (buf == NULL) {
1481
        // failed to allocate a buffer, free immediately
1482
        PyObject *to_dealloc = NULL;
1483
        _PyEval_StopTheWorld(tstate->base.interp);
1484
        if (work_item_should_decref(ptr)) {
1485
            PyObject *obj = (PyObject *)(ptr - 1);
1486
            if (!_Py_IsImmortal(obj)) {
1487
                Py_ssize_t refcount = _Py_ExplicitMergeRefcount(obj, -1);
1488
                if (refcount == 0) {
1489
                    to_dealloc = obj;
1490
                }
1491
            }
1492
        }
1493
        else {
1494
            PyMem_Free((void *)ptr);
1495
        }
1496
        _PyEval_StartTheWorld(tstate->base.interp);
1497
        if (to_dealloc != NULL) {
1498
            _Py_Dealloc(to_dealloc);
1499
        }
1500
        return;
1501
    }
1502
1503
    assert(buf != NULL && buf->wr_idx < WORK_ITEMS_PER_CHUNK);
1504
    uint64_t seq;
1505
    if (should_advance_qsbr_for_free(tstate->qsbr, size)) {
1506
        seq = _Py_qsbr_advance(tstate->qsbr->shared);
1507
    }
1508
    else {
1509
        seq = _Py_qsbr_shared_next(tstate->qsbr->shared);
1510
    }
1511
    buf->array[buf->wr_idx].ptr = ptr;
1512
    buf->array[buf->wr_idx].qsbr_goal = seq;
1513
    buf->wr_idx++;
1514
1515
    if (buf->wr_idx == WORK_ITEMS_PER_CHUNK) {
1516
        // Normally the processing of delayed items is done from the eval
1517
        // breaker.  Processing here is a safety measure to ensure too much
1518
        // work does not accumulate.
1519
        _PyMem_ProcessDelayed((PyThreadState *)tstate);
1520
    }
1521
#endif
1522
1.52M
}
1523
1524
void
1525
_PyMem_FreeDelayed(void *ptr, size_t size)
1526
1.52M
{
1527
1.52M
    assert(!((uintptr_t)ptr & 0x01));
1528
1.52M
    if (ptr != NULL) {
1529
1.52M
        free_delayed((uintptr_t)ptr, size);
1530
1.52M
    }
1531
1.52M
}
1532
1533
#ifdef Py_GIL_DISABLED
1534
void
1535
_PyObject_XDecRefDelayed(PyObject *ptr)
1536
{
1537
    assert(!((uintptr_t)ptr & 0x01));
1538
    if (ptr != NULL && !_Py_IsImmortal(ptr)) {
1539
        // We use 0 as the size since we don't have an easy way to know the
1540
        // actual size.  If we are freeing many objects, the write sequence
1541
        // will be advanced due to QSBR_DEFERRED_LIMIT.
1542
        free_delayed(((uintptr_t)ptr)|0x01, 0);
1543
    }
1544
}
1545
#endif
1546
1547
#ifdef Py_GIL_DISABLED
1548
void
1549
_PyObject_XSetRefDelayed(PyObject **ptr, PyObject *value)
1550
{
1551
    PyObject *old = *ptr;
1552
    FT_ATOMIC_STORE_PTR_RELEASE(*ptr, value);
1553
    _PyObject_XDecRefDelayed(old);
1554
}
1555
#endif
1556
1557
static struct _mem_work_chunk *
1558
work_queue_first(struct llist_node *head)
1559
0
{
1560
0
    return llist_data(head->next, struct _mem_work_chunk, node);
1561
0
}
1562
1563
static void
1564
process_queue(struct llist_node *head, _PyThreadStateImpl *tstate,
1565
              bool keep_empty, delayed_dealloc_cb cb, void *state)
1566
0
{
1567
0
    while (!llist_empty(head)) {
1568
0
        struct _mem_work_chunk *buf = work_queue_first(head);
1569
1570
0
        if (buf->rd_idx < buf->wr_idx) {
1571
0
            struct _mem_work_item *item = &buf->array[buf->rd_idx];
1572
0
            if (!_Py_qsbr_poll(tstate->qsbr, item->qsbr_goal)) {
1573
0
                return;
1574
0
            }
1575
1576
0
            buf->rd_idx++;
1577
            // NB: free_work_item may re-enter or execute arbitrary code
1578
0
            free_work_item(item->ptr, cb, state);
1579
0
            continue;
1580
0
        }
1581
1582
0
        assert(buf->rd_idx == buf->wr_idx);
1583
0
        if (keep_empty && buf->node.next == head) {
1584
            // Keep the last buffer in the queue to reduce re-allocations
1585
0
            buf->rd_idx = buf->wr_idx = 0;
1586
0
            return;
1587
0
        }
1588
1589
0
        llist_remove(&buf->node);
1590
0
        PyMem_Free(buf);
1591
0
    }
1592
0
}
1593
1594
static void
1595
process_interp_queue(struct _Py_mem_interp_free_queue *queue,
1596
                     _PyThreadStateImpl *tstate, delayed_dealloc_cb cb,
1597
                     void *state)
1598
0
{
1599
0
    assert(PyMutex_IsLocked(&queue->mutex));
1600
0
    process_queue(&queue->head, tstate, false, cb, state);
1601
1602
0
    int more_work = !llist_empty(&queue->head);
1603
0
    _Py_atomic_store_int_relaxed(&queue->has_work, more_work);
1604
0
}
1605
1606
static void
1607
maybe_process_interp_queue(struct _Py_mem_interp_free_queue *queue,
1608
                           _PyThreadStateImpl *tstate, delayed_dealloc_cb cb,
1609
                           void *state)
1610
0
{
1611
0
    if (!_Py_atomic_load_int_relaxed(&queue->has_work)) {
1612
0
        return;
1613
0
    }
1614
1615
    // Try to acquire the lock, but don't block if it's already held.
1616
0
    if (_PyMutex_LockTimed(&queue->mutex, 0, 0) == PY_LOCK_ACQUIRED) {
1617
0
        process_interp_queue(queue, tstate, cb, state);
1618
0
        PyMutex_Unlock(&queue->mutex);
1619
0
    }
1620
0
}
1621
1622
void
1623
_PyMem_ProcessDelayed(PyThreadState *tstate)
1624
0
{
1625
0
    PyInterpreterState *interp = tstate->interp;
1626
0
    _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
1627
1628
0
    tstate_impl->qsbr->should_process = false;
1629
1630
    // Process thread-local work
1631
0
    process_queue(&tstate_impl->mem_free_queue, tstate_impl, true, NULL, NULL);
1632
1633
    // Process shared interpreter work
1634
0
    maybe_process_interp_queue(&interp->mem_free_queue, tstate_impl, NULL, NULL);
1635
0
}
1636
1637
void
1638
_PyMem_ProcessDelayedNoDealloc(PyThreadState *tstate, delayed_dealloc_cb cb, void *state)
1639
0
{
1640
0
    PyInterpreterState *interp = tstate->interp;
1641
0
    _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
1642
1643
    // Process thread-local work
1644
0
    process_queue(&tstate_impl->mem_free_queue, tstate_impl, true, cb, state);
1645
1646
    // Process shared interpreter work
1647
0
    maybe_process_interp_queue(&interp->mem_free_queue, tstate_impl, cb, state);
1648
0
}
1649
1650
void
1651
_PyMem_AbandonDelayed(PyThreadState *tstate)
1652
0
{
1653
0
    PyInterpreterState *interp = tstate->interp;
1654
0
    struct llist_node *queue = &((_PyThreadStateImpl *)tstate)->mem_free_queue;
1655
1656
0
    if (llist_empty(queue)) {
1657
0
        return;
1658
0
    }
1659
1660
    // Check if the queue contains one empty buffer
1661
0
    struct _mem_work_chunk *buf = work_queue_first(queue);
1662
0
    if (buf->rd_idx == buf->wr_idx) {
1663
0
        llist_remove(&buf->node);
1664
0
        PyMem_Free(buf);
1665
0
        assert(llist_empty(queue));
1666
0
        return;
1667
0
    }
1668
1669
0
    PyMutex_Lock(&interp->mem_free_queue.mutex);
1670
1671
    // Merge the thread's work queue into the interpreter's work queue.
1672
0
    llist_concat(&interp->mem_free_queue.head, queue);
1673
1674
    // Process the merged queue now (see gh-130794).
1675
0
    _PyThreadStateImpl *this_tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
1676
0
    process_interp_queue(&interp->mem_free_queue, this_tstate, NULL, NULL);
1677
1678
0
    PyMutex_Unlock(&interp->mem_free_queue.mutex);
1679
1680
0
    assert(llist_empty(queue));  // the thread's queue is now empty
1681
0
}
1682
1683
void
1684
_PyMem_FiniDelayed(PyInterpreterState *interp)
1685
0
{
1686
0
    struct llist_node *head = &interp->mem_free_queue.head;
1687
0
    while (!llist_empty(head)) {
1688
0
        struct _mem_work_chunk *buf = work_queue_first(head);
1689
1690
0
        if (buf->rd_idx < buf->wr_idx) {
1691
            // Free the remaining items immediately. There should be no other
1692
            // threads accessing the memory at this point during shutdown.
1693
0
            struct _mem_work_item *item = &buf->array[buf->rd_idx];
1694
0
            buf->rd_idx++;
1695
            // NB: free_work_item may re-enter or execute arbitrary code
1696
0
            free_work_item(item->ptr, NULL, NULL);
1697
0
            continue;
1698
0
        }
1699
1700
0
        llist_remove(&buf->node);
1701
0
        PyMem_Free(buf);
1702
0
    }
1703
0
}
1704
1705
/**************************/
1706
/* the "object" allocator */
1707
/**************************/
1708
1709
void *
1710
PyObject_Malloc(size_t size)
1711
1.53G
{
1712
    /* see PyMem_RawMalloc() */
1713
1.53G
    if (size > (size_t)PY_SSIZE_T_MAX)
1714
0
        return NULL;
1715
1.53G
    OBJECT_STAT_INC_COND(allocations512, size < 512);
1716
1.53G
    OBJECT_STAT_INC_COND(allocations4k, size >= 512 && size < 4094);
1717
1.53G
    OBJECT_STAT_INC_COND(allocations_big, size >= 4094);
1718
1.53G
    OBJECT_STAT_INC(allocations);
1719
1.53G
    return _PyObject.malloc(_PyObject.ctx, size);
1720
1.53G
}
1721
1722
void *
1723
PyObject_Calloc(size_t nelem, size_t elsize)
1724
0
{
1725
    /* see PyMem_RawMalloc() */
1726
0
    if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize)
1727
0
        return NULL;
1728
0
    OBJECT_STAT_INC_COND(allocations512, elsize < 512);
1729
0
    OBJECT_STAT_INC_COND(allocations4k, elsize >= 512 && elsize < 4094);
1730
0
    OBJECT_STAT_INC_COND(allocations_big, elsize >= 4094);
1731
0
    OBJECT_STAT_INC(allocations);
1732
0
    return _PyObject.calloc(_PyObject.ctx, nelem, elsize);
1733
0
}
1734
1735
void *
1736
PyObject_Realloc(void *ptr, size_t new_size)
1737
63.0M
{
1738
    /* see PyMem_RawMalloc() */
1739
63.0M
    if (new_size > (size_t)PY_SSIZE_T_MAX)
1740
0
        return NULL;
1741
63.0M
    return _PyObject.realloc(_PyObject.ctx, ptr, new_size);
1742
63.0M
}
1743
1744
void
1745
PyObject_Free(void *ptr)
1746
1.52G
{
1747
1.52G
    OBJECT_STAT_INC(frees);
1748
1.52G
    _PyObject.free(_PyObject.ctx, ptr);
1749
1.52G
}
1750
1751
1752
/* Use __builtin_expect() where available to reduce overhead of
1753
   the valgrind checks */
1754
#if (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))) && defined(__OPTIMIZE__)
1755
12.4G
#  define UNLIKELY(value) __builtin_expect((value), 0)
1756
5.72G
#  define LIKELY(value) __builtin_expect((value), 1)
1757
#else
1758
#  define UNLIKELY(value) (value)
1759
#  define LIKELY(value) (value)
1760
#endif
1761
1762
#ifdef WITH_PYMALLOC
1763
1764
#ifdef WITH_VALGRIND
1765
#include <valgrind/valgrind.h>
1766
1767
/* -1 indicates that we haven't checked that we're running on valgrind yet. */
1768
static int running_on_valgrind = -1;
1769
#endif
1770
1771
typedef struct _obmalloc_state OMState;
1772
1773
/* obmalloc state for main interpreter and shared by all interpreters without
1774
 * their own obmalloc state.  By not explicitly initializing this structure, it
1775
 * will be allocated in the BSS which is a small performance win.  The radix
1776
 * tree arrays are fairly large but are sparsely used.  */
1777
static struct _obmalloc_state obmalloc_state_main;
1778
static bool obmalloc_state_initialized;
1779
1780
static inline int
1781
has_own_state(PyInterpreterState *interp)
1782
0
{
1783
0
    return (_Py_IsMainInterpreter(interp) ||
1784
0
            !(interp->feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC) ||
1785
0
            _Py_IsMainInterpreterFinalizing(interp));
1786
0
}
1787
1788
static inline OMState *
1789
get_state(void)
1790
4.25G
{
1791
4.25G
    PyInterpreterState *interp = _PyInterpreterState_GET();
1792
4.25G
    assert(interp->obmalloc != NULL); // otherwise not initialized or freed
1793
4.25G
    return interp->obmalloc;
1794
4.25G
}
1795
1796
// These macros all rely on a local "state" variable.
1797
2.02G
#define usedpools (state->pools.used)
1798
5.45M
#define allarenas (state->mgmt.arenas)
1799
377
#define maxarenas (state->mgmt.maxarenas)
1800
48.9k
#define unused_arena_objects (state->mgmt.unused_arena_objects)
1801
46.2M
#define usable_arenas (state->mgmt.usable_arenas)
1802
33.3M
#define nfp2lasta (state->mgmt.nfp2lasta)
1803
30.6k
#define narenas_currently_allocated (state->mgmt.narenas_currently_allocated)
1804
9.93k
#define ntimes_arena_allocated (state->mgmt.ntimes_arena_allocated)
1805
11.2k
#define narenas_highwater (state->mgmt.narenas_highwater)
1806
385M
#define raw_allocated_blocks (state->mgmt.raw_allocated_blocks)
1807
1808
#ifdef WITH_MIMALLOC
1809
static bool count_blocks(
1810
    const mi_heap_t* heap, const mi_heap_area_t* area,
1811
    void* block, size_t block_size, void* allocated_blocks)
1812
0
{
1813
0
    *(size_t *)allocated_blocks += area->used;
1814
0
    return 1;
1815
0
}
1816
1817
static Py_ssize_t
1818
get_mimalloc_allocated_blocks(PyInterpreterState *interp)
1819
0
{
1820
0
    size_t allocated_blocks = 0;
1821
#ifdef Py_GIL_DISABLED
1822
    _Py_FOR_EACH_TSTATE_UNLOCKED(interp, t) {
1823
        _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)t;
1824
        for (int i = 0; i < _Py_MIMALLOC_HEAP_COUNT; i++) {
1825
            mi_heap_t *heap = &tstate->mimalloc.heaps[i];
1826
            mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks);
1827
        }
1828
    }
1829
1830
    mi_subproc_t *subproc = interp->mimalloc.subproc;
1831
    for (int tag = 0; tag < _Py_MIMALLOC_HEAP_COUNT; tag++) {
1832
        mi_abandoned_visit_blocks(subproc, tag, false, &count_blocks,
1833
                                  &allocated_blocks);
1834
    }
1835
#else
1836
    // TODO(sgross): this only counts the current thread's blocks.
1837
0
    mi_heap_t *heap = mi_heap_get_default();
1838
0
    mi_heap_visit_blocks(heap, false, &count_blocks, &allocated_blocks);
1839
0
#endif
1840
0
    return allocated_blocks;
1841
0
}
1842
#endif
1843
1844
Py_ssize_t
1845
_PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *interp)
1846
0
{
1847
0
#ifdef WITH_MIMALLOC
1848
0
    if (_PyMem_MimallocEnabled()) {
1849
0
        return get_mimalloc_allocated_blocks(interp);
1850
0
    }
1851
0
#endif
1852
1853
#ifdef Py_DEBUG
1854
    assert(has_own_state(interp));
1855
#else
1856
0
    if (!has_own_state(interp)) {
1857
0
        _Py_FatalErrorFunc(__func__,
1858
0
                           "the interpreter doesn't have its own allocator");
1859
0
    }
1860
0
#endif
1861
0
    OMState *state = interp->obmalloc;
1862
1863
0
    if (state == NULL) {
1864
0
        return 0;
1865
0
    }
1866
1867
0
    Py_ssize_t n = raw_allocated_blocks;
1868
    /* add up allocated blocks for used pools */
1869
0
    for (uint i = 0; i < maxarenas; ++i) {
1870
        /* Skip arenas which are not allocated. */
1871
0
        if (allarenas[i].address == 0) {
1872
0
            continue;
1873
0
        }
1874
1875
0
        uintptr_t base = (uintptr_t)_Py_ALIGN_UP(allarenas[i].address, POOL_SIZE);
1876
1877
        /* visit every pool in the arena */
1878
0
        assert(base <= (uintptr_t) allarenas[i].pool_address);
1879
0
        for (; base < (uintptr_t) allarenas[i].pool_address; base += POOL_SIZE) {
1880
0
            poolp p = (poolp)base;
1881
0
            n += p->ref.count;
1882
0
        }
1883
0
    }
1884
0
    return n;
1885
0
}
1886
1887
static void free_obmalloc_arenas(PyInterpreterState *interp);
1888
1889
void
1890
_PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *interp)
1891
0
{
1892
0
#ifdef WITH_MIMALLOC
1893
0
    if (_PyMem_MimallocEnabled()) {
1894
0
        Py_ssize_t leaked = _PyInterpreterState_GetAllocatedBlocks(interp);
1895
0
        interp->runtime->obmalloc.interpreter_leaks += leaked;
1896
0
        return;
1897
0
    }
1898
0
#endif
1899
0
    if (has_own_state(interp) && interp->obmalloc != NULL) {
1900
0
        Py_ssize_t leaked = _PyInterpreterState_GetAllocatedBlocks(interp);
1901
0
        assert(has_own_state(interp) || leaked == 0);
1902
0
        interp->runtime->obmalloc.interpreter_leaks += leaked;
1903
0
        if (_PyMem_obmalloc_state_on_heap(interp) && leaked == 0) {
1904
            // free the obmalloc arenas and radix tree nodes.  If leaked > 0
1905
            // then some of the memory allocated by obmalloc has not been
1906
            // freed.  It might be safe to free the arenas in that case but
1907
            // it's possible that extension modules are still using that
1908
            // memory.  So, it is safer to not free and to leak.  Perhaps there
1909
            // should be warning when this happens.  It should be possible to
1910
            // use a tool like "-fsanitize=address" to track down these leaks.
1911
0
            free_obmalloc_arenas(interp);
1912
0
        }
1913
0
    }
1914
0
}
1915
1916
static Py_ssize_t get_num_global_allocated_blocks(_PyRuntimeState *);
1917
1918
/* We preserve the number of blocks leaked during runtime finalization,
1919
   so they can be reported if the runtime is initialized again. */
1920
// XXX We don't lose any information by dropping this,
1921
// so we should consider doing so.
1922
static Py_ssize_t last_final_leaks = 0;
1923
1924
void
1925
_Py_FinalizeAllocatedBlocks(_PyRuntimeState *runtime)
1926
0
{
1927
0
    last_final_leaks = get_num_global_allocated_blocks(runtime);
1928
0
    runtime->obmalloc.interpreter_leaks = 0;
1929
0
}
1930
1931
static Py_ssize_t
1932
get_num_global_allocated_blocks(_PyRuntimeState *runtime)
1933
0
{
1934
0
    Py_ssize_t total = 0;
1935
0
    if (_PyRuntimeState_GetFinalizing(runtime) != NULL) {
1936
0
        PyInterpreterState *interp = _PyInterpreterState_Main();
1937
0
        if (interp == NULL) {
1938
            /* We are at the very end of runtime finalization.
1939
               We can't rely on finalizing->interp since that thread
1940
               state is probably already freed, so we don't worry
1941
               about it. */
1942
0
            assert(PyInterpreterState_Head() == NULL);
1943
0
        }
1944
0
        else {
1945
0
            assert(interp != NULL);
1946
            /* It is probably the last interpreter but not necessarily. */
1947
0
            assert(PyInterpreterState_Next(interp) == NULL);
1948
0
            total += _PyInterpreterState_GetAllocatedBlocks(interp);
1949
0
        }
1950
0
    }
1951
0
    else {
1952
0
        _PyEval_StopTheWorldAll(&_PyRuntime);
1953
0
        HEAD_LOCK(runtime);
1954
0
        PyInterpreterState *interp = PyInterpreterState_Head();
1955
0
        assert(interp != NULL);
1956
#ifdef Py_DEBUG
1957
        int got_main = 0;
1958
#endif
1959
0
        for (; interp != NULL; interp = PyInterpreterState_Next(interp)) {
1960
#ifdef Py_DEBUG
1961
            if (_Py_IsMainInterpreter(interp)) {
1962
                assert(!got_main);
1963
                got_main = 1;
1964
                assert(has_own_state(interp));
1965
            }
1966
#endif
1967
0
            if (has_own_state(interp)) {
1968
0
                total += _PyInterpreterState_GetAllocatedBlocks(interp);
1969
0
            }
1970
0
        }
1971
0
        HEAD_UNLOCK(runtime);
1972
0
        _PyEval_StartTheWorldAll(&_PyRuntime);
1973
#ifdef Py_DEBUG
1974
        assert(got_main);
1975
#endif
1976
0
    }
1977
0
    total += runtime->obmalloc.interpreter_leaks;
1978
0
    total += last_final_leaks;
1979
0
    return total;
1980
0
}
1981
1982
Py_ssize_t
1983
_Py_GetGlobalAllocatedBlocks(void)
1984
0
{
1985
0
    return get_num_global_allocated_blocks(&_PyRuntime);
1986
0
}
1987
1988
#if WITH_PYMALLOC_RADIX_TREE
1989
/*==========================================================================*/
1990
/* radix tree for tracking arena usage. */
1991
1992
6.32G
#define arena_map_root (state->usage.arena_map_root)
1993
#ifdef USE_INTERIOR_NODES
1994
37
#define arena_map_mid_count (state->usage.arena_map_mid_count)
1995
37
#define arena_map_bot_count (state->usage.arena_map_bot_count)
1996
#endif
1997
1998
/* Return a pointer to a bottom tree node, return NULL if it doesn't exist or
1999
 * it cannot be created */
2000
static inline Py_ALWAYS_INLINE arena_map_bot_t *
2001
arena_map_get(OMState *state, pymem_block *p, int create)
2002
2.17G
{
2003
2.17G
#ifdef USE_INTERIOR_NODES
2004
    /* sanity check that IGNORE_BITS is correct */
2005
2.17G
    assert(HIGH_BITS(p) == HIGH_BITS(&arena_map_root));
2006
2.17G
    int i1 = MAP_TOP_INDEX(p);
2007
2.17G
    if (arena_map_root.ptrs[i1] == NULL) {
2008
37
        if (!create) {
2009
0
            return NULL;
2010
0
        }
2011
37
        arena_map_mid_t *n = PyMem_RawCalloc(1, sizeof(arena_map_mid_t));
2012
37
        if (n == NULL) {
2013
0
            return NULL;
2014
0
        }
2015
37
        arena_map_root.ptrs[i1] = n;
2016
37
        arena_map_mid_count++;
2017
37
    }
2018
2.17G
    int i2 = MAP_MID_INDEX(p);
2019
2.17G
    if (arena_map_root.ptrs[i1]->ptrs[i2] == NULL) {
2020
203M
        if (!create) {
2021
203M
            return NULL;
2022
203M
        }
2023
37
        arena_map_bot_t *n = PyMem_RawCalloc(1, sizeof(arena_map_bot_t));
2024
37
        if (n == NULL) {
2025
0
            return NULL;
2026
0
        }
2027
37
        arena_map_root.ptrs[i1]->ptrs[i2] = n;
2028
37
        arena_map_bot_count++;
2029
37
    }
2030
1.97G
    return arena_map_root.ptrs[i1]->ptrs[i2];
2031
#else
2032
    return &arena_map_root;
2033
#endif
2034
2.17G
}
2035
2036
2037
/* The radix tree only tracks arenas.  So, for 16 MiB arenas, we throw
2038
 * away 24 bits of the address.  That reduces the space requirement of
2039
 * the tree compared to similar radix tree page-map schemes.  In
2040
 * exchange for slashing the space requirement, it needs more
2041
 * computation to check an address.
2042
 *
2043
 * Tracking coverage is done by "ideal" arena address.  It is easier to
2044
 * explain in decimal so let's say that the arena size is 100 bytes.
2045
 * Then, ideal addresses are 100, 200, 300, etc.  For checking if a
2046
 * pointer address is inside an actual arena, we have to check two ideal
2047
 * arena addresses.  E.g. if pointer is 357, we need to check 200 and
2048
 * 300.  In the rare case that an arena is aligned in the ideal way
2049
 * (e.g. base address of arena is 200) then we only have to check one
2050
 * ideal address.
2051
 *
2052
 * The tree nodes for 200 and 300 both store the address of arena.
2053
 * There are two cases: the arena starts at a lower ideal arena and
2054
 * extends to this one, or the arena starts in this arena and extends to
2055
 * the next ideal arena.  The tail_lo and tail_hi members correspond to
2056
 * these two cases.
2057
 */
2058
2059
2060
/* mark or unmark addresses covered by arena */
2061
static int
2062
arena_map_mark_used(OMState *state, uintptr_t arena_base, int is_used)
2063
19.4k
{
2064
    /* sanity check that IGNORE_BITS is correct */
2065
19.4k
    assert(HIGH_BITS(arena_base) == HIGH_BITS(&arena_map_root));
2066
19.4k
    arena_map_bot_t *n_hi = arena_map_get(
2067
19.4k
            state, (pymem_block *)arena_base, is_used);
2068
19.4k
    if (n_hi == NULL) {
2069
0
        assert(is_used); /* otherwise node should already exist */
2070
0
        return 0; /* failed to allocate space for node */
2071
0
    }
2072
19.4k
    int i3 = MAP_BOT_INDEX((pymem_block *)arena_base);
2073
19.4k
    int32_t tail = (int32_t)(arena_base & ARENA_SIZE_MASK);
2074
19.4k
    if (tail == 0) {
2075
        /* is ideal arena address */
2076
74
        n_hi->arenas[i3].tail_hi = is_used ? -1 : 0;
2077
74
    }
2078
19.3k
    else {
2079
        /* arena_base address is not ideal (aligned to arena size) and
2080
         * so it potentially covers two MAP_BOT nodes.  Get the MAP_BOT node
2081
         * for the next arena.  Note that it might be in different MAP_TOP
2082
         * and MAP_MID nodes as well so we need to call arena_map_get()
2083
         * again (do the full tree traversal).
2084
         */
2085
19.3k
        n_hi->arenas[i3].tail_hi = is_used ? tail : 0;
2086
19.3k
        uintptr_t arena_base_next = arena_base + ARENA_SIZE;
2087
        /* If arena_base is a legit arena address, so is arena_base_next - 1
2088
         * (last address in arena).  If arena_base_next overflows then it
2089
         * must overflow to 0.  However, that would mean arena_base was
2090
         * "ideal" and we should not be in this case. */
2091
19.3k
        assert(arena_base < arena_base_next);
2092
19.3k
        arena_map_bot_t *n_lo = arena_map_get(
2093
19.3k
                state, (pymem_block *)arena_base_next, is_used);
2094
19.3k
        if (n_lo == NULL) {
2095
0
            assert(is_used); /* otherwise should already exist */
2096
0
            n_hi->arenas[i3].tail_hi = 0;
2097
0
            return 0; /* failed to allocate space for node */
2098
0
        }
2099
19.3k
        int i3_next = MAP_BOT_INDEX(arena_base_next);
2100
19.3k
        n_lo->arenas[i3_next].tail_lo = is_used ? tail : 0;
2101
19.3k
    }
2102
19.4k
    return 1;
2103
19.4k
}
2104
2105
/* Return true if 'p' is a pointer inside an obmalloc arena.
2106
 * _PyObject_Free() calls this so it needs to be very fast. */
2107
static int
2108
arena_map_is_used(OMState *state, pymem_block *p)
2109
2.17G
{
2110
2.17G
    arena_map_bot_t *n = arena_map_get(state, p, 0);
2111
2.17G
    if (n == NULL) {
2112
203M
        return 0;
2113
203M
    }
2114
1.97G
    int i3 = MAP_BOT_INDEX(p);
2115
    /* ARENA_BITS must be < 32 so that the tail is a non-negative int32_t. */
2116
1.97G
    int32_t hi = n->arenas[i3].tail_hi;
2117
1.97G
    int32_t lo = n->arenas[i3].tail_lo;
2118
1.97G
    int32_t tail = (int32_t)(AS_UINT(p) & ARENA_SIZE_MASK);
2119
1.97G
    return (tail < lo) || (tail >= hi && hi != 0);
2120
2.17G
}
2121
2122
/* end of radix tree logic */
2123
/*==========================================================================*/
2124
#endif /* WITH_PYMALLOC_RADIX_TREE */
2125
2126
2127
/* Allocate a new arena.  If we run out of memory, return NULL.  Else
2128
 * allocate a new arena, and return the address of an arena_object
2129
 * describing the new arena.  It's expected that the caller will set
2130
 * `usable_arenas` to the return value.
2131
 */
2132
static struct arena_object*
2133
new_arena(OMState *state)
2134
9.93k
{
2135
9.93k
    struct arena_object* arenaobj;
2136
9.93k
    uint excess;        /* number of bytes above pool alignment */
2137
9.93k
    void *address;
2138
2139
9.93k
    int debug_stats = _PyRuntime.obmalloc.dump_debug_stats;
2140
9.93k
    if (debug_stats == -1) {
2141
37
        const char *opt = Py_GETENV("PYTHONMALLOCSTATS");
2142
37
        debug_stats = (opt != NULL && *opt != '\0');
2143
37
        _PyRuntime.obmalloc.dump_debug_stats = debug_stats;
2144
37
    }
2145
9.93k
    if (debug_stats) {
2146
0
        _PyObject_DebugMallocStats(stderr);
2147
0
    }
2148
2149
9.93k
    if (unused_arena_objects == NULL) {
2150
69
        uint i;
2151
69
        uint numarenas;
2152
69
        size_t nbytes;
2153
2154
        /* Double the number of arena objects on each allocation.
2155
         * Note that it's possible for `numarenas` to overflow.
2156
         */
2157
69
        numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS;
2158
69
        if (numarenas <= maxarenas)
2159
0
            return NULL;                /* overflow */
2160
#if SIZEOF_SIZE_T <= SIZEOF_INT
2161
        if (numarenas > SIZE_MAX / sizeof(*allarenas))
2162
            return NULL;                /* overflow */
2163
#endif
2164
69
        nbytes = numarenas * sizeof(*allarenas);
2165
69
        arenaobj = (struct arena_object *)PyMem_RawRealloc(allarenas, nbytes);
2166
69
        if (arenaobj == NULL)
2167
0
            return NULL;
2168
69
        allarenas = arenaobj;
2169
2170
        /* We might need to fix pointers that were copied.  However,
2171
         * new_arena only gets called when all the pages in the
2172
         * previous arenas are full.  Thus, there are *no* pointers
2173
         * into the old array. Thus, we don't have to worry about
2174
         * invalid pointers.  Just to be sure, some asserts:
2175
         */
2176
69
        assert(usable_arenas == NULL);
2177
69
        assert(unused_arena_objects == NULL);
2178
2179
        /* Put the new arenas on the unused_arena_objects list. */
2180
2.32k
        for (i = maxarenas; i < numarenas; ++i) {
2181
2.25k
            allarenas[i].address = 0;              /* mark as unassociated */
2182
2.25k
            allarenas[i].nextarena = i < numarenas - 1 ?
2183
2.25k
                                        &allarenas[i+1] : NULL;
2184
2.25k
        }
2185
2186
        /* Update globals. */
2187
69
        unused_arena_objects = &allarenas[maxarenas];
2188
69
        maxarenas = numarenas;
2189
69
    }
2190
2191
    /* Take the next available arena object off the head of the list. */
2192
9.93k
    assert(unused_arena_objects != NULL);
2193
9.93k
    arenaobj = unused_arena_objects;
2194
9.93k
    unused_arena_objects = arenaobj->nextarena;
2195
9.93k
    assert(arenaobj->address == 0);
2196
9.93k
    address = _PyObject_Arena.alloc(_PyObject_Arena.ctx, ARENA_SIZE);
2197
9.93k
#if WITH_PYMALLOC_RADIX_TREE
2198
9.93k
    if (address != NULL) {
2199
9.93k
        if (!arena_map_mark_used(state, (uintptr_t)address, 1)) {
2200
            /* marking arena in radix tree failed, abort */
2201
0
            _PyObject_Arena.free(_PyObject_Arena.ctx, address, ARENA_SIZE);
2202
0
            address = NULL;
2203
0
        }
2204
9.93k
    }
2205
9.93k
#endif
2206
9.93k
    if (address == NULL) {
2207
        /* The allocation failed: return NULL after putting the
2208
         * arenaobj back.
2209
         */
2210
0
        arenaobj->nextarena = unused_arena_objects;
2211
0
        unused_arena_objects = arenaobj;
2212
0
        return NULL;
2213
0
    }
2214
9.93k
    arenaobj->address = (uintptr_t)address;
2215
2216
9.93k
    ++narenas_currently_allocated;
2217
9.93k
    ++ntimes_arena_allocated;
2218
9.93k
    if (narenas_currently_allocated > narenas_highwater)
2219
1.28k
        narenas_highwater = narenas_currently_allocated;
2220
9.93k
    arenaobj->freepools = NULL;
2221
    /* pool_address <- first pool-aligned address in the arena
2222
       nfreepools <- number of whole pools that fit after alignment */
2223
9.93k
    arenaobj->pool_address = (pymem_block*)arenaobj->address;
2224
9.93k
    arenaobj->nfreepools = MAX_POOLS_IN_ARENA;
2225
9.93k
    excess = (uint)(arenaobj->address & POOL_SIZE_MASK);
2226
9.93k
    if (excess != 0) {
2227
7.04k
        --arenaobj->nfreepools;
2228
7.04k
        arenaobj->pool_address += POOL_SIZE - excess;
2229
7.04k
    }
2230
9.93k
    arenaobj->ntotalpools = arenaobj->nfreepools;
2231
2232
9.93k
    return arenaobj;
2233
9.93k
}
2234
2235
2236
2237
#if WITH_PYMALLOC_RADIX_TREE
2238
/* Return true if and only if P is an address that was allocated by
2239
   pymalloc.  When the radix tree is used, 'poolp' is unused.
2240
 */
2241
static bool
2242
address_in_range(OMState *state, void *p, poolp Py_UNUSED(pool))
2243
2.17G
{
2244
2.17G
    return arena_map_is_used(state, p);
2245
2.17G
}
2246
#else
2247
/*
2248
address_in_range(P, POOL)
2249
2250
Return true if and only if P is an address that was allocated by pymalloc.
2251
POOL must be the pool address associated with P, i.e., POOL = POOL_ADDR(P)
2252
(the caller is asked to compute this because the macro expands POOL more than
2253
once, and for efficiency it's best for the caller to assign POOL_ADDR(P) to a
2254
variable and pass the latter to the macro; because address_in_range is
2255
called on every alloc/realloc/free, micro-efficiency is important here).
2256
2257
Tricky:  Let B be the arena base address associated with the pool, B =
2258
arenas[(POOL)->arenaindex].address.  Then P belongs to the arena if and only if
2259
2260
    B <= P < B + ARENA_SIZE
2261
2262
Subtracting B throughout, this is true iff
2263
2264
    0 <= P-B < ARENA_SIZE
2265
2266
By using unsigned arithmetic, the "0 <=" half of the test can be skipped.
2267
2268
Obscure:  A PyMem "free memory" function can call the pymalloc free or realloc
2269
before the first arena has been allocated.  `arenas` is still NULL in that
2270
case.  We're relying on that maxarenas is also 0 in that case, so that
2271
(POOL)->arenaindex < maxarenas  must be false, saving us from trying to index
2272
into a NULL arenas.
2273
2274
Details:  given P and POOL, the arena_object corresponding to P is AO =
2275
arenas[(POOL)->arenaindex].  Suppose obmalloc controls P.  Then (barring wild
2276
stores, etc), POOL is the correct address of P's pool, AO.address is the
2277
correct base address of the pool's arena, and P must be within ARENA_SIZE of
2278
AO.address.  In addition, AO.address is not 0 (no arena can start at address 0
2279
(NULL)).  Therefore address_in_range correctly reports that obmalloc
2280
controls P.
2281
2282
Now suppose obmalloc does not control P (e.g., P was obtained via a direct
2283
call to the system malloc() or realloc()).  (POOL)->arenaindex may be anything
2284
in this case -- it may even be uninitialized trash.  If the trash arenaindex
2285
is >= maxarenas, the macro correctly concludes at once that obmalloc doesn't
2286
control P.
2287
2288
Else arenaindex is < maxarena, and AO is read up.  If AO corresponds to an
2289
allocated arena, obmalloc controls all the memory in slice AO.address :
2290
AO.address+ARENA_SIZE.  By case assumption, P is not controlled by obmalloc,
2291
so P doesn't lie in that slice, so the macro correctly reports that P is not
2292
controlled by obmalloc.
2293
2294
Finally, if P is not controlled by obmalloc and AO corresponds to an unused
2295
arena_object (one not currently associated with an allocated arena),
2296
AO.address is 0, and the second test in the macro reduces to:
2297
2298
    P < ARENA_SIZE
2299
2300
If P >= ARENA_SIZE (extremely likely), the macro again correctly concludes
2301
that P is not controlled by obmalloc.  However, if P < ARENA_SIZE, this part
2302
of the test still passes, and the third clause (AO.address != 0) is necessary
2303
to get the correct result:  AO.address is 0 in this case, so the macro
2304
correctly reports that P is not controlled by obmalloc (despite that P lies in
2305
slice AO.address : AO.address + ARENA_SIZE).
2306
2307
Note:  The third (AO.address != 0) clause was added in Python 2.5.  Before
2308
2.5, arenas were never free()'ed, and an arenaindex < maxarena always
2309
corresponded to a currently-allocated arena, so the "P is not controlled by
2310
obmalloc, AO corresponds to an unused arena_object, and P < ARENA_SIZE" case
2311
was impossible.
2312
2313
Note that the logic is excruciating, and reading up possibly uninitialized
2314
memory when P is not controlled by obmalloc (to get at (POOL)->arenaindex)
2315
creates problems for some memory debuggers.  The overwhelming advantage is
2316
that this test determines whether an arbitrary address is controlled by
2317
obmalloc in a small constant time, independent of the number of arenas
2318
obmalloc controls.  Since this test is needed at every entry point, it's
2319
extremely desirable that it be this fast.
2320
*/
2321
2322
static bool _Py_NO_SANITIZE_ADDRESS
2323
            _Py_NO_SANITIZE_THREAD
2324
            _Py_NO_SANITIZE_MEMORY
2325
address_in_range(OMState *state, void *p, poolp pool)
2326
{
2327
    // Since address_in_range may be reading from memory which was not allocated
2328
    // by Python, it is important that pool->arenaindex is read only once, as
2329
    // another thread may be concurrently modifying the value without holding
2330
    // the GIL. The following dance forces the compiler to read pool->arenaindex
2331
    // only once.
2332
    uint arenaindex = *((volatile uint *)&pool->arenaindex);
2333
    return arenaindex < maxarenas &&
2334
        (uintptr_t)p - allarenas[arenaindex].address < ARENA_SIZE &&
2335
        allarenas[arenaindex].address != 0;
2336
}
2337
2338
#endif /* !WITH_PYMALLOC_RADIX_TREE */
2339
2340
/*==========================================================================*/
2341
2342
// Called when freelist is exhausted.  Extend the freelist if there is
2343
// space for a block.  Otherwise, remove this pool from usedpools.
2344
static void
2345
pymalloc_pool_extend(poolp pool, uint size)
2346
387M
{
2347
387M
    if (UNLIKELY(pool->nextoffset <= pool->maxnextoffset)) {
2348
        /* There is room for another block. */
2349
252M
        pool->freeblock = (pymem_block*)pool + pool->nextoffset;
2350
252M
        pool->nextoffset += INDEX2SIZE(size);
2351
252M
        *(pymem_block **)(pool->freeblock) = NULL;
2352
252M
        return;
2353
252M
    }
2354
2355
    /* Pool is full, unlink from used pools. */
2356
134M
    poolp next;
2357
134M
    next = pool->nextpool;
2358
134M
    pool = pool->prevpool;
2359
134M
    next->prevpool = pool;
2360
134M
    pool->nextpool = next;
2361
134M
}
2362
2363
/* called when pymalloc_alloc can not allocate a block from usedpool.
2364
 * This function takes new pool and allocate a block from it.
2365
 */
2366
static void*
2367
allocate_from_new_pool(OMState *state, uint size)
2368
4.84M
{
2369
    /* There isn't a pool of the right size class immediately
2370
     * available:  use a free pool.
2371
     */
2372
4.84M
    if (UNLIKELY(usable_arenas == NULL)) {
2373
        /* No arena has a free pool:  allocate a new arena. */
2374
#ifdef WITH_MEMORY_LIMITS
2375
        if (narenas_currently_allocated >= MAX_ARENAS) {
2376
            return NULL;
2377
        }
2378
#endif
2379
9.93k
        usable_arenas = new_arena(state);
2380
9.93k
        if (usable_arenas == NULL) {
2381
0
            return NULL;
2382
0
        }
2383
9.93k
        usable_arenas->nextarena = usable_arenas->prevarena = NULL;
2384
9.93k
        assert(nfp2lasta[usable_arenas->nfreepools] == NULL);
2385
9.93k
        nfp2lasta[usable_arenas->nfreepools] = usable_arenas;
2386
9.93k
    }
2387
4.84M
    assert(usable_arenas->address != 0);
2388
2389
    /* This arena already had the smallest nfreepools value, so decreasing
2390
     * nfreepools doesn't change that, and we don't need to rearrange the
2391
     * usable_arenas list.  However, if the arena becomes wholly allocated,
2392
     * we need to remove its arena_object from usable_arenas.
2393
     */
2394
4.84M
    assert(usable_arenas->nfreepools > 0);
2395
4.84M
    if (nfp2lasta[usable_arenas->nfreepools] == usable_arenas) {
2396
        /* It's the last of this size, so there won't be any. */
2397
4.81M
        nfp2lasta[usable_arenas->nfreepools] = NULL;
2398
4.81M
    }
2399
    /* If any free pools will remain, it will be the new smallest. */
2400
4.84M
    if (usable_arenas->nfreepools > 1) {
2401
4.71M
        assert(nfp2lasta[usable_arenas->nfreepools - 1] == NULL);
2402
4.71M
        nfp2lasta[usable_arenas->nfreepools - 1] = usable_arenas;
2403
4.71M
    }
2404
2405
    /* Try to get a cached free pool. */
2406
4.84M
    poolp pool = usable_arenas->freepools;
2407
4.84M
    if (LIKELY(pool != NULL)) {
2408
        /* Unlink from cached pools. */
2409
4.21M
        usable_arenas->freepools = pool->nextpool;
2410
4.21M
        usable_arenas->nfreepools--;
2411
4.21M
        if (UNLIKELY(usable_arenas->nfreepools == 0)) {
2412
            /* Wholly allocated:  remove. */
2413
116k
            assert(usable_arenas->freepools == NULL);
2414
116k
            assert(usable_arenas->nextarena == NULL ||
2415
116k
                   usable_arenas->nextarena->prevarena ==
2416
116k
                   usable_arenas);
2417
116k
            usable_arenas = usable_arenas->nextarena;
2418
116k
            if (usable_arenas != NULL) {
2419
99.8k
                usable_arenas->prevarena = NULL;
2420
99.8k
                assert(usable_arenas->address != 0);
2421
99.8k
            }
2422
116k
        }
2423
4.10M
        else {
2424
            /* nfreepools > 0:  it must be that freepools
2425
             * isn't NULL, or that we haven't yet carved
2426
             * off all the arena's pools for the first
2427
             * time.
2428
             */
2429
4.10M
            assert(usable_arenas->freepools != NULL ||
2430
4.10M
                   usable_arenas->pool_address <=
2431
4.10M
                   (pymem_block*)usable_arenas->address +
2432
4.10M
                       ARENA_SIZE - POOL_SIZE);
2433
4.10M
        }
2434
4.21M
    }
2435
622k
    else {
2436
        /* Carve off a new pool. */
2437
622k
        assert(usable_arenas->nfreepools > 0);
2438
622k
        assert(usable_arenas->freepools == NULL);
2439
622k
        pool = (poolp)usable_arenas->pool_address;
2440
622k
        assert((pymem_block*)pool <= (pymem_block*)usable_arenas->address +
2441
622k
                                 ARENA_SIZE - POOL_SIZE);
2442
622k
        pool->arenaindex = (uint)(usable_arenas - allarenas);
2443
622k
        assert(&allarenas[pool->arenaindex] == usable_arenas);
2444
622k
        pool->szidx = DUMMY_SIZE_IDX;
2445
622k
        usable_arenas->pool_address += POOL_SIZE;
2446
622k
        --usable_arenas->nfreepools;
2447
2448
622k
        if (usable_arenas->nfreepools == 0) {
2449
9.73k
            assert(usable_arenas->nextarena == NULL ||
2450
9.73k
                   usable_arenas->nextarena->prevarena ==
2451
9.73k
                   usable_arenas);
2452
            /* Unlink the arena:  it is completely allocated. */
2453
9.73k
            usable_arenas = usable_arenas->nextarena;
2454
9.73k
            if (usable_arenas != NULL) {
2455
283
                usable_arenas->prevarena = NULL;
2456
283
                assert(usable_arenas->address != 0);
2457
283
            }
2458
9.73k
        }
2459
622k
    }
2460
2461
    /* Frontlink to used pools. */
2462
4.84M
    pymem_block *bp;
2463
4.84M
    poolp next = usedpools[size + size]; /* == prev */
2464
4.84M
    pool->nextpool = next;
2465
4.84M
    pool->prevpool = next;
2466
4.84M
    next->nextpool = pool;
2467
4.84M
    next->prevpool = pool;
2468
4.84M
    pool->ref.count = 1;
2469
4.84M
    if (pool->szidx == size) {
2470
        /* Luckily, this pool last contained blocks
2471
         * of the same size class, so its header
2472
         * and free list are already initialized.
2473
         */
2474
3.64M
        bp = pool->freeblock;
2475
3.64M
        assert(bp != NULL);
2476
3.64M
        pool->freeblock = *(pymem_block **)bp;
2477
3.64M
        return bp;
2478
3.64M
    }
2479
    /*
2480
     * Initialize the pool header, set up the free list to
2481
     * contain just the second block, and return the first
2482
     * block.
2483
     */
2484
1.20M
    pool->szidx = size;
2485
1.20M
    size = INDEX2SIZE(size);
2486
1.20M
    bp = (pymem_block *)pool + POOL_OVERHEAD;
2487
1.20M
    pool->nextoffset = POOL_OVERHEAD + (size << 1);
2488
1.20M
    pool->maxnextoffset = POOL_SIZE - size;
2489
1.20M
    pool->freeblock = bp + size;
2490
1.20M
    *(pymem_block **)(pool->freeblock) = NULL;
2491
1.20M
    return bp;
2492
4.84M
}
2493
2494
/* pymalloc allocator
2495
2496
   Return a pointer to newly allocated memory if pymalloc allocated memory.
2497
2498
   Return NULL if pymalloc failed to allocate the memory block: on bigger
2499
   requests, on error in the code below (as a last chance to serve the request)
2500
   or when the max memory limit has been reached.
2501
*/
2502
static inline void*
2503
pymalloc_alloc(OMState *state, void *Py_UNUSED(ctx), size_t nbytes)
2504
2.08G
{
2505
#ifdef WITH_VALGRIND
2506
    if (UNLIKELY(running_on_valgrind == -1)) {
2507
        running_on_valgrind = RUNNING_ON_VALGRIND;
2508
    }
2509
    if (UNLIKELY(running_on_valgrind)) {
2510
        return NULL;
2511
    }
2512
#endif
2513
2514
2.08G
    if (UNLIKELY(nbytes == 0)) {
2515
54.6k
        return NULL;
2516
54.6k
    }
2517
2.08G
    if (UNLIKELY(nbytes > SMALL_REQUEST_THRESHOLD)) {
2518
192M
        return NULL;
2519
192M
    }
2520
2521
1.88G
    uint size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT;
2522
1.88G
    poolp pool = usedpools[size + size];
2523
1.88G
    pymem_block *bp;
2524
2525
1.88G
    if (LIKELY(pool != pool->nextpool)) {
2526
        /*
2527
         * There is a used pool for this size class.
2528
         * Pick up the head block of its free list.
2529
         */
2530
1.88G
        ++pool->ref.count;
2531
1.88G
        bp = pool->freeblock;
2532
1.88G
        assert(bp != NULL);
2533
2534
1.88G
        if (UNLIKELY((pool->freeblock = *(pymem_block **)bp) == NULL)) {
2535
            // Reached the end of the free list, try to extend it.
2536
387M
            pymalloc_pool_extend(pool, size);
2537
387M
        }
2538
1.88G
    }
2539
4.84M
    else {
2540
        /* There isn't a pool of the right size class immediately
2541
         * available:  use a free pool.
2542
         */
2543
4.84M
        bp = allocate_from_new_pool(state, size);
2544
4.84M
    }
2545
2546
1.88G
    return (void *)bp;
2547
2.08G
}
2548
2549
2550
void *
2551
_PyObject_Malloc(void *ctx, size_t nbytes)
2552
2.03G
{
2553
2.03G
    OMState *state = get_state();
2554
2.03G
    void* ptr = pymalloc_alloc(state, ctx, nbytes);
2555
2.03G
    if (LIKELY(ptr != NULL)) {
2556
1.84G
        return ptr;
2557
1.84G
    }
2558
2559
192M
    ptr = PyMem_RawMalloc(nbytes);
2560
192M
    if (ptr != NULL) {
2561
192M
        raw_allocated_blocks++;
2562
192M
    }
2563
192M
    return ptr;
2564
2.03G
}
2565
2566
2567
void *
2568
_PyObject_Calloc(void *ctx, size_t nelem, size_t elsize)
2569
47.5M
{
2570
47.5M
    assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize);
2571
47.5M
    size_t nbytes = nelem * elsize;
2572
2573
47.5M
    OMState *state = get_state();
2574
47.5M
    void* ptr = pymalloc_alloc(state, ctx, nbytes);
2575
47.5M
    if (LIKELY(ptr != NULL)) {
2576
47.3M
        memset(ptr, 0, nbytes);
2577
47.3M
        return ptr;
2578
47.3M
    }
2579
2580
201k
    ptr = PyMem_RawCalloc(nelem, elsize);
2581
201k
    if (ptr != NULL) {
2582
201k
        raw_allocated_blocks++;
2583
201k
    }
2584
201k
    return ptr;
2585
47.5M
}
2586
2587
2588
static void
2589
insert_to_usedpool(OMState *state, poolp pool)
2590
134M
{
2591
134M
    assert(pool->ref.count > 0);            /* else the pool is empty */
2592
2593
134M
    uint size = pool->szidx;
2594
134M
    poolp next = usedpools[size + size];
2595
134M
    poolp prev = next->prevpool;
2596
2597
    /* insert pool before next:   prev <-> pool <-> next */
2598
134M
    pool->nextpool = next;
2599
134M
    pool->prevpool = prev;
2600
134M
    next->prevpool = pool;
2601
134M
    prev->nextpool = pool;
2602
134M
}
2603
2604
static void
2605
insert_to_freepool(OMState *state, poolp pool)
2606
4.82M
{
2607
4.82M
    poolp next = pool->nextpool;
2608
4.82M
    poolp prev = pool->prevpool;
2609
4.82M
    next->prevpool = prev;
2610
4.82M
    prev->nextpool = next;
2611
2612
    /* Link the pool to freepools.  This is a singly-linked
2613
     * list, and pool->prevpool isn't used there.
2614
     */
2615
4.82M
    struct arena_object *ao = &allarenas[pool->arenaindex];
2616
4.82M
    pool->nextpool = ao->freepools;
2617
4.82M
    ao->freepools = pool;
2618
4.82M
    uint nf = ao->nfreepools;
2619
    /* If this is the rightmost arena with this number of free pools,
2620
     * nfp2lasta[nf] needs to change.  Caution:  if nf is 0, there
2621
     * are no arenas in usable_arenas with that value.
2622
     */
2623
4.82M
    struct arena_object* lastnf = nfp2lasta[nf];
2624
4.82M
    assert((nf == 0 && lastnf == NULL) ||
2625
4.82M
           (nf > 0 &&
2626
4.82M
            lastnf != NULL &&
2627
4.82M
            lastnf->nfreepools == nf &&
2628
4.82M
            (lastnf->nextarena == NULL ||
2629
4.82M
             nf < lastnf->nextarena->nfreepools)));
2630
4.82M
    if (lastnf == ao) {  /* it is the rightmost */
2631
4.60M
        struct arena_object* p = ao->prevarena;
2632
4.60M
        nfp2lasta[nf] = (p != NULL && p->nfreepools == nf) ? p : NULL;
2633
4.60M
    }
2634
4.82M
    ao->nfreepools = ++nf;
2635
2636
    /* All the rest is arena management.  We just freed
2637
     * a pool, and there are 4 cases for arena mgmt:
2638
     * 1. If all the pools are free, return the arena to
2639
     *    the system free().  Except if this is the last
2640
     *    arena in the list, keep it to avoid thrashing:
2641
     *    keeping one wholly free arena in the list avoids
2642
     *    pathological cases where a simple loop would
2643
     *    otherwise provoke needing to allocate and free an
2644
     *    arena on every iteration.  See bpo-37257.
2645
     * 2. If this is the only free pool in the arena,
2646
     *    add the arena back to the `usable_arenas` list.
2647
     * 3. If the "next" arena has a smaller count of free
2648
     *    pools, we have to "slide this arena right" to
2649
     *    restore that usable_arenas is sorted in order of
2650
     *    nfreepools.
2651
     * 4. Else there's nothing more to do.
2652
     */
2653
4.82M
    if (nf == ao->ntotalpools && ao->nextarena != NULL) {
2654
        /* Case 1.  First unlink ao from usable_arenas.
2655
         */
2656
9.52k
        assert(ao->prevarena == NULL ||
2657
9.52k
               ao->prevarena->address != 0);
2658
9.52k
        assert(ao ->nextarena == NULL ||
2659
9.52k
               ao->nextarena->address != 0);
2660
2661
        /* Fix the pointer in the prevarena, or the
2662
         * usable_arenas pointer.
2663
         */
2664
9.52k
        if (ao->prevarena == NULL) {
2665
1.73k
            usable_arenas = ao->nextarena;
2666
1.73k
            assert(usable_arenas == NULL ||
2667
1.73k
                   usable_arenas->address != 0);
2668
1.73k
        }
2669
7.79k
        else {
2670
7.79k
            assert(ao->prevarena->nextarena == ao);
2671
7.79k
            ao->prevarena->nextarena =
2672
7.79k
                ao->nextarena;
2673
7.79k
        }
2674
        /* Fix the pointer in the nextarena. */
2675
9.52k
        if (ao->nextarena != NULL) {
2676
9.52k
            assert(ao->nextarena->prevarena == ao);
2677
9.52k
            ao->nextarena->prevarena =
2678
9.52k
                ao->prevarena;
2679
9.52k
        }
2680
        /* Record that this arena_object slot is
2681
         * available to be reused.
2682
         */
2683
9.52k
        ao->nextarena = unused_arena_objects;
2684
9.52k
        unused_arena_objects = ao;
2685
2686
9.52k
#if WITH_PYMALLOC_RADIX_TREE
2687
        /* mark arena region as not under control of obmalloc */
2688
9.52k
        arena_map_mark_used(state, ao->address, 0);
2689
9.52k
#endif
2690
2691
        /* Free the entire arena. */
2692
9.52k
        _PyObject_Arena.free(_PyObject_Arena.ctx,
2693
9.52k
                             (void *)ao->address, ARENA_SIZE);
2694
9.52k
        ao->address = 0;                        /* mark unassociated */
2695
9.52k
        --narenas_currently_allocated;
2696
2697
9.52k
        return;
2698
9.52k
    }
2699
2700
4.81M
    if (nf == 1) {
2701
        /* Case 2.  Put ao at the head of
2702
         * usable_arenas.  Note that because
2703
         * ao->nfreepools was 0 before, ao isn't
2704
         * currently on the usable_arenas list.
2705
         */
2706
126k
        ao->nextarena = usable_arenas;
2707
126k
        ao->prevarena = NULL;
2708
126k
        if (usable_arenas)
2709
109k
            usable_arenas->prevarena = ao;
2710
126k
        usable_arenas = ao;
2711
126k
        assert(usable_arenas->address != 0);
2712
126k
        if (nfp2lasta[1] == NULL) {
2713
120k
            nfp2lasta[1] = ao;
2714
120k
        }
2715
2716
126k
        return;
2717
126k
    }
2718
2719
    /* If this arena is now out of order, we need to keep
2720
     * the list sorted.  The list is kept sorted so that
2721
     * the "most full" arenas are used first, which allows
2722
     * the nearly empty arenas to be completely freed.  In
2723
     * a few un-scientific tests, it seems like this
2724
     * approach allowed a lot more memory to be freed.
2725
     */
2726
    /* If this is the only arena with nf, record that. */
2727
4.68M
    if (nfp2lasta[nf] == NULL) {
2728
4.57M
        nfp2lasta[nf] = ao;
2729
4.57M
    } /* else the rightmost with nf doesn't change */
2730
    /* If this was the rightmost of the old size, it remains in place. */
2731
4.68M
    if (ao == lastnf) {
2732
        /* Case 4.  Nothing to do. */
2733
4.60M
        return;
2734
4.60M
    }
2735
    /* If ao were the only arena in the list, the last block would have
2736
     * gotten us out.
2737
     */
2738
4.68M
    assert(ao->nextarena != NULL);
2739
2740
    /* Case 3:  We have to move the arena towards the end of the list,
2741
     * because it has more free pools than the arena to its right.  It needs
2742
     * to move to follow lastnf.
2743
     * First unlink ao from usable_arenas.
2744
     */
2745
81.8k
    if (ao->prevarena != NULL) {
2746
        /* ao isn't at the head of the list */
2747
63.7k
        assert(ao->prevarena->nextarena == ao);
2748
63.7k
        ao->prevarena->nextarena = ao->nextarena;
2749
63.7k
    }
2750
18.1k
    else {
2751
        /* ao is at the head of the list */
2752
18.1k
        assert(usable_arenas == ao);
2753
18.1k
        usable_arenas = ao->nextarena;
2754
18.1k
    }
2755
81.8k
    ao->nextarena->prevarena = ao->prevarena;
2756
    /* And insert after lastnf. */
2757
81.8k
    ao->prevarena = lastnf;
2758
81.8k
    ao->nextarena = lastnf->nextarena;
2759
81.8k
    if (ao->nextarena != NULL) {
2760
80.2k
        ao->nextarena->prevarena = ao;
2761
80.2k
    }
2762
81.8k
    lastnf->nextarena = ao;
2763
    /* Verify that the swaps worked. */
2764
81.8k
    assert(ao->nextarena == NULL || nf <= ao->nextarena->nfreepools);
2765
81.8k
    assert(ao->prevarena == NULL || nf > ao->prevarena->nfreepools);
2766
81.8k
    assert(ao->nextarena == NULL || ao->nextarena->prevarena == ao);
2767
81.8k
    assert((usable_arenas == ao && ao->prevarena == NULL)
2768
81.8k
           || ao->prevarena->nextarena == ao);
2769
81.8k
}
2770
2771
/* Free a memory block allocated by pymalloc_alloc().
2772
   Return 1 if it was freed.
2773
   Return 0 if the block was not allocated by pymalloc_alloc(). */
2774
static inline int
2775
pymalloc_free(OMState *state, void *Py_UNUSED(ctx), void *p)
2776
2.07G
{
2777
2.07G
    assert(p != NULL);
2778
2779
#ifdef WITH_VALGRIND
2780
    if (UNLIKELY(running_on_valgrind > 0)) {
2781
        return 0;
2782
    }
2783
#endif
2784
2785
2.07G
    poolp pool = POOL_ADDR(p);
2786
2.07G
    if (UNLIKELY(!address_in_range(state, p, pool))) {
2787
192M
        return 0;
2788
192M
    }
2789
    /* We allocated this address. */
2790
2791
    /* Link p to the start of the pool's freeblock list.  Since
2792
     * the pool had at least the p block outstanding, the pool
2793
     * wasn't empty (so it's already in a usedpools[] list, or
2794
     * was full and is in no list -- it's not in the freeblocks
2795
     * list in any case).
2796
     */
2797
2.07G
    assert(pool->ref.count > 0);            /* else it was empty */
2798
1.88G
    pymem_block *lastfree = pool->freeblock;
2799
1.88G
    *(pymem_block **)p = lastfree;
2800
1.88G
    pool->freeblock = (pymem_block *)p;
2801
1.88G
    pool->ref.count--;
2802
2803
1.88G
    if (UNLIKELY(lastfree == NULL)) {
2804
        /* Pool was full, so doesn't currently live in any list:
2805
         * link it to the front of the appropriate usedpools[] list.
2806
         * This mimics LRU pool usage for new allocations and
2807
         * targets optimal filling when several pools contain
2808
         * blocks of the same size class.
2809
         */
2810
134M
        insert_to_usedpool(state, pool);
2811
134M
        return 1;
2812
134M
    }
2813
2814
    /* freeblock wasn't NULL, so the pool wasn't full,
2815
     * and the pool is in a usedpools[] list.
2816
     */
2817
1.75G
    if (LIKELY(pool->ref.count != 0)) {
2818
        /* pool isn't empty:  leave it in usedpools */
2819
1.74G
        return 1;
2820
1.74G
    }
2821
2822
    /* Pool is now empty:  unlink from usedpools, and
2823
     * link to the front of freepools.  This ensures that
2824
     * previously freed pools will be allocated later
2825
     * (being not referenced, they are perhaps paged out).
2826
     */
2827
4.82M
    insert_to_freepool(state, pool);
2828
4.82M
    return 1;
2829
1.75G
}
2830
2831
2832
void
2833
_PyObject_Free(void *ctx, void *p)
2834
2.13G
{
2835
    /* PyObject_Free(NULL) has no effect */
2836
2.13G
    if (p == NULL) {
2837
55.9M
        return;
2838
55.9M
    }
2839
2840
2.07G
    OMState *state = get_state();
2841
2.07G
    if (UNLIKELY(!pymalloc_free(state, ctx, p))) {
2842
        /* pymalloc didn't allocate this address */
2843
192M
        PyMem_RawFree(p);
2844
192M
        raw_allocated_blocks--;
2845
192M
    }
2846
2.07G
}
2847
2848
2849
/* pymalloc realloc.
2850
2851
   If nbytes==0, then as the Python docs promise, we do not treat this like
2852
   free(p), and return a non-NULL result.
2853
2854
   Return 1 if pymalloc reallocated memory and wrote the new pointer into
2855
   newptr_p.
2856
2857
   Return 0 if pymalloc didn't allocated p. */
2858
static int
2859
pymalloc_realloc(OMState *state, void *ctx,
2860
                 void **newptr_p, void *p, size_t nbytes)
2861
96.5M
{
2862
96.5M
    void *bp;
2863
96.5M
    poolp pool;
2864
96.5M
    size_t size;
2865
2866
96.5M
    assert(p != NULL);
2867
2868
#ifdef WITH_VALGRIND
2869
    /* Treat running_on_valgrind == -1 the same as 0 */
2870
    if (UNLIKELY(running_on_valgrind > 0)) {
2871
        return 0;
2872
    }
2873
#endif
2874
2875
96.5M
    pool = POOL_ADDR(p);
2876
96.5M
    if (!address_in_range(state, p, pool)) {
2877
        /* pymalloc is not managing this block.
2878
2879
           If nbytes <= SMALL_REQUEST_THRESHOLD, it's tempting to try to take
2880
           over this block.  However, if we do, we need to copy the valid data
2881
           from the C-managed block to one of our blocks, and there's no
2882
           portable way to know how much of the memory space starting at p is
2883
           valid.
2884
2885
           As bug 1185883 pointed out the hard way, it's possible that the
2886
           C-managed block is "at the end" of allocated VM space, so that a
2887
           memory fault can occur if we try to copy nbytes bytes starting at p.
2888
           Instead we punt: let C continue to manage this block. */
2889
10.6M
        return 0;
2890
10.6M
    }
2891
2892
    /* pymalloc is in charge of this block */
2893
85.8M
    size = INDEX2SIZE(pool->szidx);
2894
85.8M
    if (nbytes <= size) {
2895
        /* The block is staying the same or shrinking.
2896
2897
           If it's shrinking, there's a tradeoff: it costs cycles to copy the
2898
           block to a smaller size class, but it wastes memory not to copy it.
2899
2900
           The compromise here is to copy on shrink only if at least 25% of
2901
           size can be shaved off. */
2902
52.1M
        if (4 * nbytes > 3 * size) {
2903
            /* It's the same, or shrinking and new/old > 3/4. */
2904
17.1M
            *newptr_p = p;
2905
17.1M
            return 1;
2906
17.1M
        }
2907
34.9M
        size = nbytes;
2908
34.9M
    }
2909
2910
68.6M
    bp = _PyObject_Malloc(ctx, nbytes);
2911
68.6M
    if (bp != NULL) {
2912
68.6M
        memcpy(bp, p, size);
2913
68.6M
        _PyObject_Free(ctx, p);
2914
68.6M
    }
2915
68.6M
    *newptr_p = bp;
2916
68.6M
    return 1;
2917
85.8M
}
2918
2919
2920
void *
2921
_PyObject_Realloc(void *ctx, void *ptr, size_t nbytes)
2922
317M
{
2923
317M
    void *ptr2;
2924
2925
317M
    if (ptr == NULL) {
2926
220M
        return _PyObject_Malloc(ctx, nbytes);
2927
220M
    }
2928
2929
96.5M
    OMState *state = get_state();
2930
96.5M
    if (pymalloc_realloc(state, ctx, &ptr2, ptr, nbytes)) {
2931
85.8M
        return ptr2;
2932
85.8M
    }
2933
2934
10.6M
    return PyMem_RawRealloc(ptr, nbytes);
2935
96.5M
}
2936
2937
#else   /* ! WITH_PYMALLOC */
2938
2939
/*==========================================================================*/
2940
/* pymalloc not enabled:  Redirect the entry points to malloc.  These will
2941
 * only be used by extensions that are compiled with pymalloc enabled. */
2942
2943
Py_ssize_t
2944
_PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *Py_UNUSED(interp))
2945
{
2946
    return 0;
2947
}
2948
2949
Py_ssize_t
2950
_Py_GetGlobalAllocatedBlocks(void)
2951
{
2952
    return 0;
2953
}
2954
2955
void
2956
_PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *Py_UNUSED(interp))
2957
{
2958
    return;
2959
}
2960
2961
void
2962
_Py_FinalizeAllocatedBlocks(_PyRuntimeState *Py_UNUSED(runtime))
2963
{
2964
    return;
2965
}
2966
2967
#endif /* WITH_PYMALLOC */
2968
2969
2970
/*==========================================================================*/
2971
/* A x-platform debugging allocator.  This doesn't manage memory directly,
2972
 * it wraps a real allocator, adding extra debugging info to the memory blocks.
2973
 */
2974
2975
/* Uncomment this define to add the "serialno" field */
2976
/* #define PYMEM_DEBUG_SERIALNO */
2977
2978
#ifdef PYMEM_DEBUG_SERIALNO
2979
static size_t serialno = 0;     /* incremented on each debug {m,re}alloc */
2980
2981
/* serialno is always incremented via calling this routine.  The point is
2982
 * to supply a single place to set a breakpoint.
2983
 */
2984
static void
2985
bumpserialno(void)
2986
{
2987
    ++serialno;
2988
}
2989
#endif
2990
2991
0
#define SST SIZEOF_SIZE_T
2992
2993
#ifdef PYMEM_DEBUG_SERIALNO
2994
#  define PYMEM_DEBUG_EXTRA_BYTES 4 * SST
2995
#else
2996
0
#  define PYMEM_DEBUG_EXTRA_BYTES 3 * SST
2997
#endif
2998
2999
/* Read sizeof(size_t) bytes at p as a big-endian size_t. */
3000
static size_t
3001
read_size_t(const void *p)
3002
0
{
3003
0
    const uint8_t *q = (const uint8_t *)p;
3004
0
    size_t result = *q++;
3005
0
    int i;
3006
3007
0
    for (i = SST; --i > 0; ++q)
3008
0
        result = (result << 8) | *q;
3009
0
    return result;
3010
0
}
3011
3012
/* Write n as a big-endian size_t, MSB at address p, LSB at
3013
 * p + sizeof(size_t) - 1.
3014
 */
3015
static void
3016
write_size_t(void *p, size_t n)
3017
0
{
3018
0
    uint8_t *q = (uint8_t *)p + SST - 1;
3019
0
    int i;
3020
3021
0
    for (i = SST; --i >= 0; --q) {
3022
0
        *q = (uint8_t)(n & 0xff);
3023
0
        n >>= 8;
3024
0
    }
3025
0
}
3026
3027
static void
3028
fill_mem_debug(debug_alloc_api_t *api, void *data, int c, size_t nbytes,
3029
               bool is_alloc)
3030
0
{
3031
#ifdef Py_GIL_DISABLED
3032
    if (api->api_id == 'o') {
3033
        // Don't overwrite the first few bytes of a PyObject allocation in the
3034
        // free-threaded build
3035
        _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
3036
        size_t debug_offset;
3037
        if (is_alloc) {
3038
            debug_offset = tstate->mimalloc.current_object_heap->debug_offset;
3039
        }
3040
        else {
3041
            char *alloc = (char *)data - 2*SST;  // start of the allocation
3042
            debug_offset = _mi_ptr_page(alloc)->debug_offset;
3043
        }
3044
        debug_offset -= 2*SST;  // account for pymalloc extra bytes
3045
        if (debug_offset < nbytes) {
3046
            memset((char *)data + debug_offset, c, nbytes - debug_offset);
3047
        }
3048
        return;
3049
    }
3050
#endif
3051
0
    memset(data, c, nbytes);
3052
0
}
3053
3054
/* Let S = sizeof(size_t).  The debug malloc asks for 4 * S extra bytes and
3055
   fills them with useful stuff, here calling the underlying malloc's result p:
3056
3057
p[0: S]
3058
    Number of bytes originally asked for.  This is a size_t, big-endian (easier
3059
    to read in a memory dump).
3060
p[S]
3061
    API ID.  See PEP 445.  This is a character, but seems undocumented.
3062
p[S+1: 2*S]
3063
    Copies of PYMEM_FORBIDDENBYTE.  Used to catch under- writes and reads.
3064
p[2*S: 2*S+n]
3065
    The requested memory, filled with copies of PYMEM_CLEANBYTE.
3066
    Used to catch reference to uninitialized memory.
3067
    &p[2*S] is returned.  Note that this is 8-byte aligned if pymalloc
3068
    handled the request itself.
3069
p[2*S+n: 2*S+n+S]
3070
    Copies of PYMEM_FORBIDDENBYTE.  Used to catch over- writes and reads.
3071
p[2*S+n+S: 2*S+n+2*S]
3072
    A serial number, incremented by 1 on each call to _PyMem_DebugMalloc
3073
    and _PyMem_DebugRealloc.
3074
    This is a big-endian size_t.
3075
    If "bad memory" is detected later, the serial number gives an
3076
    excellent way to set a breakpoint on the next run, to capture the
3077
    instant at which this block was passed out.
3078
3079
If PYMEM_DEBUG_SERIALNO is not defined (default), the debug malloc only asks
3080
for 3 * S extra bytes, and omits the last serialno field.
3081
*/
3082
3083
static void *
3084
_PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
3085
0
{
3086
0
    debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
3087
0
    uint8_t *p;           /* base address of malloc'ed pad block */
3088
0
    uint8_t *data;        /* p + 2*SST == pointer to data bytes */
3089
0
    uint8_t *tail;        /* data + nbytes == pointer to tail pad bytes */
3090
0
    size_t total;         /* nbytes + PYMEM_DEBUG_EXTRA_BYTES */
3091
3092
0
    if (nbytes > (size_t)PY_SSIZE_T_MAX - PYMEM_DEBUG_EXTRA_BYTES) {
3093
        /* integer overflow: can't represent total as a Py_ssize_t */
3094
0
        return NULL;
3095
0
    }
3096
0
    total = nbytes + PYMEM_DEBUG_EXTRA_BYTES;
3097
3098
    /* Layout: [SSSS IFFF CCCC...CCCC FFFF NNNN]
3099
                ^--- p    ^--- data   ^--- tail
3100
       S: nbytes stored as size_t
3101
       I: API identifier (1 byte)
3102
       F: Forbidden bytes (size_t - 1 bytes before, size_t bytes after)
3103
       C: Clean bytes used later to store actual data
3104
       N: Serial number stored as size_t
3105
3106
       If PYMEM_DEBUG_SERIALNO is not defined (default), the last NNNN field
3107
       is omitted. */
3108
3109
0
    if (use_calloc) {
3110
0
        p = (uint8_t *)api->alloc.calloc(api->alloc.ctx, 1, total);
3111
0
    }
3112
0
    else {
3113
0
        p = (uint8_t *)api->alloc.malloc(api->alloc.ctx, total);
3114
0
    }
3115
0
    if (p == NULL) {
3116
0
        return NULL;
3117
0
    }
3118
0
    data = p + 2*SST;
3119
3120
#ifdef PYMEM_DEBUG_SERIALNO
3121
    bumpserialno();
3122
#endif
3123
3124
    /* at p, write size (SST bytes), id (1 byte), pad (SST-1 bytes) */
3125
0
    write_size_t(p, nbytes);
3126
0
    p[SST] = (uint8_t)api->api_id;
3127
0
    memset(p + SST + 1, PYMEM_FORBIDDENBYTE, SST-1);
3128
3129
0
    if (nbytes > 0 && !use_calloc) {
3130
0
        fill_mem_debug(api, data, PYMEM_CLEANBYTE, nbytes, true);
3131
0
    }
3132
3133
    /* at tail, write pad (SST bytes) and serialno (SST bytes) */
3134
0
    tail = data + nbytes;
3135
0
    memset(tail, PYMEM_FORBIDDENBYTE, SST);
3136
#ifdef PYMEM_DEBUG_SERIALNO
3137
    write_size_t(tail + SST, serialno);
3138
#endif
3139
3140
0
    return data;
3141
0
}
3142
3143
void *
3144
_PyMem_DebugRawMalloc(void *ctx, size_t nbytes)
3145
0
{
3146
0
    return _PyMem_DebugRawAlloc(0, ctx, nbytes);
3147
0
}
3148
3149
void *
3150
_PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize)
3151
0
{
3152
0
    size_t nbytes;
3153
0
    assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize);
3154
0
    nbytes = nelem * elsize;
3155
0
    return _PyMem_DebugRawAlloc(1, ctx, nbytes);
3156
0
}
3157
3158
3159
/* The debug free first checks the 2*SST bytes on each end for sanity (in
3160
   particular, that the FORBIDDENBYTEs with the api ID are still intact).
3161
   Then fills the original bytes with PYMEM_DEADBYTE.
3162
   Then calls the underlying free.
3163
*/
3164
void
3165
_PyMem_DebugRawFree(void *ctx, void *p)
3166
0
{
3167
    /* PyMem_Free(NULL) has no effect */
3168
0
    if (p == NULL) {
3169
0
        return;
3170
0
    }
3171
3172
0
    debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
3173
0
    uint8_t *q = (uint8_t *)p - 2*SST;  /* address returned from malloc */
3174
0
    size_t nbytes;
3175
3176
0
    _PyMem_DebugCheckAddress(__func__, api->api_id, p);
3177
0
    nbytes = read_size_t(q);
3178
0
    nbytes += PYMEM_DEBUG_EXTRA_BYTES - 2*SST;
3179
0
    memset(q, PYMEM_DEADBYTE, 2*SST);
3180
0
    fill_mem_debug(api, p, PYMEM_DEADBYTE, nbytes, false);
3181
0
    api->alloc.free(api->alloc.ctx, q);
3182
0
}
3183
3184
3185
void *
3186
_PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
3187
0
{
3188
0
    if (p == NULL) {
3189
0
        return _PyMem_DebugRawAlloc(0, ctx, nbytes);
3190
0
    }
3191
3192
0
    debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
3193
0
    uint8_t *head;        /* base address of malloc'ed pad block */
3194
0
    uint8_t *data;        /* pointer to data bytes */
3195
0
    uint8_t *r;
3196
0
    uint8_t *tail;        /* data + nbytes == pointer to tail pad bytes */
3197
0
    size_t total;         /* 2 * SST + nbytes + 2 * SST */
3198
0
    size_t original_nbytes;
3199
0
#define ERASED_SIZE 64
3200
3201
0
    _PyMem_DebugCheckAddress(__func__, api->api_id, p);
3202
3203
0
    data = (uint8_t *)p;
3204
0
    head = data - 2*SST;
3205
0
    original_nbytes = read_size_t(head);
3206
0
    if (nbytes > (size_t)PY_SSIZE_T_MAX - PYMEM_DEBUG_EXTRA_BYTES) {
3207
        /* integer overflow: can't represent total as a Py_ssize_t */
3208
0
        return NULL;
3209
0
    }
3210
0
    total = nbytes + PYMEM_DEBUG_EXTRA_BYTES;
3211
3212
0
    tail = data + original_nbytes;
3213
#ifdef PYMEM_DEBUG_SERIALNO
3214
    size_t block_serialno = read_size_t(tail + SST);
3215
#endif
3216
0
#ifndef Py_GIL_DISABLED
3217
    /* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
3218
       ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
3219
     */
3220
0
    uint8_t save[2*ERASED_SIZE];  /* A copy of erased bytes. */
3221
0
    if (original_nbytes <= sizeof(save)) {
3222
0
        memcpy(save, data, original_nbytes);
3223
0
        memset(data - 2 * SST, PYMEM_DEADBYTE,
3224
0
               original_nbytes + PYMEM_DEBUG_EXTRA_BYTES);
3225
0
    }
3226
0
    else {
3227
0
        memcpy(save, data, ERASED_SIZE);
3228
0
        memset(head, PYMEM_DEADBYTE, ERASED_SIZE + 2 * SST);
3229
0
        memcpy(&save[ERASED_SIZE], tail - ERASED_SIZE, ERASED_SIZE);
3230
0
        memset(tail - ERASED_SIZE, PYMEM_DEADBYTE,
3231
0
               ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST);
3232
0
    }
3233
0
#endif
3234
3235
    /* Resize and add decorations. */
3236
0
    r = (uint8_t *)api->alloc.realloc(api->alloc.ctx, head, total);
3237
0
    if (r == NULL) {
3238
        /* if realloc() failed: rewrite header and footer which have
3239
           just been erased */
3240
0
        nbytes = original_nbytes;
3241
0
    }
3242
0
    else {
3243
0
        head = r;
3244
#ifdef PYMEM_DEBUG_SERIALNO
3245
        bumpserialno();
3246
        block_serialno = serialno;
3247
#endif
3248
0
    }
3249
0
    data = head + 2*SST;
3250
3251
0
    write_size_t(head, nbytes);
3252
0
    head[SST] = (uint8_t)api->api_id;
3253
0
    memset(head + SST + 1, PYMEM_FORBIDDENBYTE, SST-1);
3254
3255
0
    tail = data + nbytes;
3256
0
    memset(tail, PYMEM_FORBIDDENBYTE, SST);
3257
#ifdef PYMEM_DEBUG_SERIALNO
3258
    write_size_t(tail + SST, block_serialno);
3259
#endif
3260
3261
0
#ifndef Py_GIL_DISABLED
3262
    /* Restore saved bytes. */
3263
0
    if (original_nbytes <= sizeof(save)) {
3264
0
        memcpy(data, save, Py_MIN(nbytes, original_nbytes));
3265
0
    }
3266
0
    else {
3267
0
        size_t i = original_nbytes - ERASED_SIZE;
3268
0
        memcpy(data, save, Py_MIN(nbytes, (size_t)ERASED_SIZE));
3269
0
        if (nbytes > i) {
3270
0
            memcpy(data + i, &save[ERASED_SIZE],
3271
0
                   Py_MIN(nbytes - i, (size_t)ERASED_SIZE));
3272
0
        }
3273
0
    }
3274
0
#endif
3275
3276
0
    if (r == NULL) {
3277
0
        return NULL;
3278
0
    }
3279
3280
0
    if (nbytes > original_nbytes) {
3281
        /* growing: mark new extra memory clean */
3282
0
        memset(data + original_nbytes, PYMEM_CLEANBYTE,
3283
0
               nbytes - original_nbytes);
3284
0
    }
3285
3286
0
    return data;
3287
0
}
3288
3289
static inline void
3290
_PyMem_DebugCheckGIL(const char *func)
3291
0
{
3292
0
    PyThreadState *tstate = _PyThreadState_GET();
3293
0
    if (tstate == NULL) {
3294
0
#ifndef Py_GIL_DISABLED
3295
0
        _Py_FatalErrorFunc(func,
3296
0
                           "Python memory allocator called "
3297
0
                           "without holding the GIL");
3298
#else
3299
        _Py_FatalErrorFunc(func,
3300
                           "Python memory allocator called "
3301
                           "without an active thread state. "
3302
                           "Are you trying to call it inside of a Py_BEGIN_ALLOW_THREADS block?");
3303
#endif
3304
0
    }
3305
0
}
3306
3307
void *
3308
_PyMem_DebugMalloc(void *ctx, size_t nbytes)
3309
0
{
3310
0
    _PyMem_DebugCheckGIL(__func__);
3311
0
    return _PyMem_DebugRawMalloc(ctx, nbytes);
3312
0
}
3313
3314
void *
3315
_PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize)
3316
0
{
3317
0
    _PyMem_DebugCheckGIL(__func__);
3318
0
    return _PyMem_DebugRawCalloc(ctx, nelem, elsize);
3319
0
}
3320
3321
3322
void
3323
_PyMem_DebugFree(void *ctx, void *ptr)
3324
0
{
3325
0
    _PyMem_DebugCheckGIL(__func__);
3326
0
    _PyMem_DebugRawFree(ctx, ptr);
3327
0
}
3328
3329
3330
void *
3331
_PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
3332
0
{
3333
0
    _PyMem_DebugCheckGIL(__func__);
3334
0
    return _PyMem_DebugRawRealloc(ctx, ptr, nbytes);
3335
0
}
3336
3337
/* Check the forbidden bytes on both ends of the memory allocated for p.
3338
 * If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress,
3339
 * and call Py_FatalError to kill the program.
3340
 * The API id, is also checked.
3341
 */
3342
static void
3343
_PyMem_DebugCheckAddress(const char *func, char api, const void *p)
3344
0
{
3345
0
    assert(p != NULL);
3346
3347
0
    const uint8_t *q = (const uint8_t *)p;
3348
0
    size_t nbytes;
3349
0
    const uint8_t *tail;
3350
0
    int i;
3351
0
    char id;
3352
3353
    /* Check the API id */
3354
0
    id = (char)q[-SST];
3355
0
    if (id != api) {
3356
0
        _PyObject_DebugDumpAddress(p);
3357
0
        _Py_FatalErrorFormat(func,
3358
0
                             "bad ID: Allocated using API '%c', "
3359
0
                             "verified using API '%c'",
3360
0
                             id, api);
3361
0
    }
3362
3363
    /* Check the stuff at the start of p first:  if there's underwrite
3364
     * corruption, the number-of-bytes field may be nuts, and checking
3365
     * the tail could lead to a segfault then.
3366
     */
3367
0
    for (i = SST-1; i >= 1; --i) {
3368
0
        if (*(q-i) != PYMEM_FORBIDDENBYTE) {
3369
0
            _PyObject_DebugDumpAddress(p);
3370
0
            _Py_FatalErrorFunc(func, "bad leading pad byte");
3371
0
        }
3372
0
    }
3373
3374
0
    nbytes = read_size_t(q - 2*SST);
3375
0
    tail = q + nbytes;
3376
0
    for (i = 0; i < SST; ++i) {
3377
0
        if (tail[i] != PYMEM_FORBIDDENBYTE) {
3378
0
            _PyObject_DebugDumpAddress(p);
3379
0
            _Py_FatalErrorFunc(func, "bad trailing pad byte");
3380
0
        }
3381
0
    }
3382
0
}
3383
3384
/* Display info to stderr about the memory block at p. */
3385
static void
3386
_PyObject_DebugDumpAddress(const void *p)
3387
0
{
3388
0
    const uint8_t *q = (const uint8_t *)p;
3389
0
    const uint8_t *tail;
3390
0
    size_t nbytes;
3391
0
    int i;
3392
0
    int ok;
3393
0
    char id;
3394
3395
0
    fprintf(stderr, "Debug memory block at address p=%p:", p);
3396
0
    if (p == NULL) {
3397
0
        fprintf(stderr, "\n");
3398
0
        return;
3399
0
    }
3400
0
    id = (char)q[-SST];
3401
0
    fprintf(stderr, " API '%c'\n", id);
3402
3403
0
    nbytes = read_size_t(q - 2*SST);
3404
0
    fprintf(stderr, "    %zu bytes originally requested\n", nbytes);
3405
3406
    /* In case this is nuts, check the leading pad bytes first. */
3407
0
    fprintf(stderr, "    The %d pad bytes at p-%d are ", SST-1, SST-1);
3408
0
    ok = 1;
3409
0
    for (i = 1; i <= SST-1; ++i) {
3410
0
        if (*(q-i) != PYMEM_FORBIDDENBYTE) {
3411
0
            ok = 0;
3412
0
            break;
3413
0
        }
3414
0
    }
3415
0
    if (ok)
3416
0
        fputs("FORBIDDENBYTE, as expected.\n", stderr);
3417
0
    else {
3418
0
        fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
3419
0
            PYMEM_FORBIDDENBYTE);
3420
0
        for (i = SST-1; i >= 1; --i) {
3421
0
            const uint8_t byte = *(q-i);
3422
0
            fprintf(stderr, "        at p-%d: 0x%02x", i, byte);
3423
0
            if (byte != PYMEM_FORBIDDENBYTE)
3424
0
                fputs(" *** OUCH", stderr);
3425
0
            fputc('\n', stderr);
3426
0
        }
3427
3428
0
        fputs("    Because memory is corrupted at the start, the "
3429
0
              "count of bytes requested\n"
3430
0
              "       may be bogus, and checking the trailing pad "
3431
0
              "bytes may segfault.\n", stderr);
3432
0
    }
3433
3434
0
    tail = q + nbytes;
3435
0
    fprintf(stderr, "    The %d pad bytes at tail=%p are ", SST, (void *)tail);
3436
0
    ok = 1;
3437
0
    for (i = 0; i < SST; ++i) {
3438
0
        if (tail[i] != PYMEM_FORBIDDENBYTE) {
3439
0
            ok = 0;
3440
0
            break;
3441
0
        }
3442
0
    }
3443
0
    if (ok)
3444
0
        fputs("FORBIDDENBYTE, as expected.\n", stderr);
3445
0
    else {
3446
0
        fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
3447
0
                PYMEM_FORBIDDENBYTE);
3448
0
        for (i = 0; i < SST; ++i) {
3449
0
            const uint8_t byte = tail[i];
3450
0
            fprintf(stderr, "        at tail+%d: 0x%02x",
3451
0
                    i, byte);
3452
0
            if (byte != PYMEM_FORBIDDENBYTE)
3453
0
                fputs(" *** OUCH", stderr);
3454
0
            fputc('\n', stderr);
3455
0
        }
3456
0
    }
3457
3458
#ifdef PYMEM_DEBUG_SERIALNO
3459
    size_t serial = read_size_t(tail + SST);
3460
    fprintf(stderr,
3461
            "    The block was made by call #%zu to debug malloc/realloc.\n",
3462
            serial);
3463
#endif
3464
3465
0
    if (nbytes > 0) {
3466
0
        i = 0;
3467
0
        fputs("    Data at p:", stderr);
3468
        /* print up to 8 bytes at the start */
3469
0
        while (q < tail && i < 8) {
3470
0
            fprintf(stderr, " %02x", *q);
3471
0
            ++i;
3472
0
            ++q;
3473
0
        }
3474
        /* and up to 8 at the end */
3475
0
        if (q < tail) {
3476
0
            if (tail - q > 8) {
3477
0
                fputs(" ...", stderr);
3478
0
                q = tail - 8;
3479
0
            }
3480
0
            while (q < tail) {
3481
0
                fprintf(stderr, " %02x", *q);
3482
0
                ++q;
3483
0
            }
3484
0
        }
3485
0
        fputc('\n', stderr);
3486
0
    }
3487
0
    fputc('\n', stderr);
3488
3489
0
    fflush(stderr);
3490
0
    _PyMem_DumpTraceback(fileno(stderr), p);
3491
0
}
3492
3493
3494
static size_t
3495
printone(FILE *out, const char* msg, size_t value)
3496
0
{
3497
0
    int i, k;
3498
0
    char buf[100];
3499
0
    size_t origvalue = value;
3500
3501
0
    fputs(msg, out);
3502
0
    for (i = (int)strlen(msg); i < 35; ++i)
3503
0
        fputc(' ', out);
3504
0
    fputc('=', out);
3505
3506
    /* Write the value with commas. */
3507
0
    i = 22;
3508
0
    buf[i--] = '\0';
3509
0
    buf[i--] = '\n';
3510
0
    k = 3;
3511
0
    do {
3512
0
        size_t nextvalue = value / 10;
3513
0
        unsigned int digit = (unsigned int)(value - nextvalue * 10);
3514
0
        value = nextvalue;
3515
0
        buf[i--] = (char)(digit + '0');
3516
0
        --k;
3517
0
        if (k == 0 && value && i >= 0) {
3518
0
            k = 3;
3519
0
            buf[i--] = ',';
3520
0
        }
3521
0
    } while (value && i >= 0);
3522
3523
0
    while (i >= 0)
3524
0
        buf[i--] = ' ';
3525
0
    fputs(buf, out);
3526
3527
0
    return origvalue;
3528
0
}
3529
3530
void
3531
_PyDebugAllocatorStats(FILE *out,
3532
                       const char *block_name, int num_blocks, size_t sizeof_block)
3533
0
{
3534
0
    char buf1[128];
3535
0
    char buf2[128];
3536
0
    PyOS_snprintf(buf1, sizeof(buf1),
3537
0
                  "%d %ss * %zd bytes each",
3538
0
                  num_blocks, block_name, sizeof_block);
3539
0
    PyOS_snprintf(buf2, sizeof(buf2),
3540
0
                  "%48s ", buf1);
3541
0
    (void)printone(out, buf2, num_blocks * sizeof_block);
3542
0
}
3543
3544
// Return true if the obmalloc state structure is heap allocated,
3545
// by PyMem_RawCalloc().  For the main interpreter, this structure
3546
// allocated in the BSS.  Allocating that way gives some memory savings
3547
// and a small performance win (at least on a demand paged OS).  On
3548
// 64-bit platforms, the obmalloc structure is 256 kB. Most of that
3549
// memory is for the arena_map_top array.  Since normally only one entry
3550
// of that array is used, only one page of resident memory is actually
3551
// used, rather than the full 256 kB.
3552
bool _PyMem_obmalloc_state_on_heap(PyInterpreterState *interp)
3553
0
{
3554
0
#if WITH_PYMALLOC
3555
0
    return interp->obmalloc && interp->obmalloc != &obmalloc_state_main;
3556
#else
3557
    return false;
3558
#endif
3559
0
}
3560
3561
#ifdef WITH_PYMALLOC
3562
static void
3563
init_obmalloc_pools(PyInterpreterState *interp)
3564
37
{
3565
    // initialize the obmalloc->pools structure.  This must be done
3566
    // before the obmalloc alloc/free functions can be called.
3567
37
    poolp temp[OBMALLOC_USED_POOLS_SIZE] =
3568
37
        _obmalloc_pools_INIT(interp->obmalloc->pools);
3569
37
    memcpy(&interp->obmalloc->pools.used, temp, sizeof(temp));
3570
37
}
3571
#endif /* WITH_PYMALLOC */
3572
3573
int _PyMem_init_obmalloc(PyInterpreterState *interp)
3574
37
{
3575
37
#ifdef WITH_PYMALLOC
3576
    /* Initialize obmalloc, but only for subinterpreters,
3577
       since the main interpreter is initialized statically. */
3578
37
    if (_Py_IsMainInterpreter(interp)
3579
0
            || _PyInterpreterState_HasFeature(interp,
3580
37
                                              Py_RTFLAGS_USE_MAIN_OBMALLOC)) {
3581
37
        interp->obmalloc = &obmalloc_state_main;
3582
37
        if (!obmalloc_state_initialized) {
3583
37
            init_obmalloc_pools(interp);
3584
37
            obmalloc_state_initialized = true;
3585
37
        }
3586
37
    } else {
3587
0
        interp->obmalloc = PyMem_RawCalloc(1, sizeof(struct _obmalloc_state));
3588
0
        if (interp->obmalloc == NULL) {
3589
0
            return -1;
3590
0
        }
3591
0
        init_obmalloc_pools(interp);
3592
0
    }
3593
37
#endif /* WITH_PYMALLOC */
3594
37
    return 0; // success
3595
37
}
3596
3597
3598
#ifdef WITH_PYMALLOC
3599
3600
static void
3601
free_obmalloc_arenas(PyInterpreterState *interp)
3602
0
{
3603
0
    OMState *state = interp->obmalloc;
3604
0
    for (uint i = 0; i < maxarenas; ++i) {
3605
        // free each obmalloc memory arena
3606
0
        struct arena_object *ao = &allarenas[i];
3607
0
        _PyObject_Arena.free(_PyObject_Arena.ctx,
3608
0
                             (void *)ao->address, ARENA_SIZE);
3609
0
    }
3610
    // free the array containing pointers to all arenas
3611
0
    PyMem_RawFree(allarenas);
3612
0
#if WITH_PYMALLOC_RADIX_TREE
3613
0
#ifdef USE_INTERIOR_NODES
3614
    // Free the middle and bottom nodes of the radix tree.  These are allocated
3615
    // by arena_map_mark_used() but not freed when arenas are freed.
3616
0
    for (int i1 = 0; i1 < MAP_TOP_LENGTH; i1++) {
3617
0
         arena_map_mid_t *mid = arena_map_root.ptrs[i1];
3618
0
         if (mid == NULL) {
3619
0
             continue;
3620
0
         }
3621
0
         for (int i2 = 0; i2 < MAP_MID_LENGTH; i2++) {
3622
0
            arena_map_bot_t *bot = arena_map_root.ptrs[i1]->ptrs[i2];
3623
0
            if (bot == NULL) {
3624
0
                continue;
3625
0
            }
3626
0
            PyMem_RawFree(bot);
3627
0
         }
3628
0
         PyMem_RawFree(mid);
3629
0
    }
3630
0
#endif
3631
0
#endif
3632
0
}
3633
3634
#ifdef Py_DEBUG
3635
/* Is target in the list?  The list is traversed via the nextpool pointers.
3636
 * The list may be NULL-terminated, or circular.  Return 1 if target is in
3637
 * list, else 0.
3638
 */
3639
static int
3640
pool_is_in_list(const poolp target, poolp list)
3641
{
3642
    poolp origlist = list;
3643
    assert(target != NULL);
3644
    if (list == NULL)
3645
        return 0;
3646
    do {
3647
        if (target == list)
3648
            return 1;
3649
        list = list->nextpool;
3650
    } while (list != NULL && list != origlist);
3651
    return 0;
3652
}
3653
#endif
3654
3655
#ifdef WITH_MIMALLOC
3656
struct _alloc_stats {
3657
    size_t allocated_blocks;
3658
    size_t allocated_bytes;
3659
    size_t allocated_with_overhead;
3660
    size_t bytes_reserved;
3661
    size_t bytes_committed;
3662
};
3663
3664
static bool _collect_alloc_stats(
3665
    const mi_heap_t* heap, const mi_heap_area_t* area,
3666
    void* block, size_t block_size, void* arg)
3667
0
{
3668
0
    struct _alloc_stats *stats = (struct _alloc_stats *)arg;
3669
0
    stats->allocated_blocks += area->used;
3670
0
    stats->allocated_bytes += area->used * area->block_size;
3671
0
    stats->allocated_with_overhead += area->used * area->full_block_size;
3672
0
    stats->bytes_reserved += area->reserved;
3673
0
    stats->bytes_committed += area->committed;
3674
0
    return 1;
3675
0
}
3676
3677
static void
3678
py_mimalloc_print_stats(FILE *out)
3679
0
{
3680
0
    fprintf(out, "Small block threshold = %zu, in %u size classes.\n",
3681
0
        (size_t)MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE);
3682
0
    fprintf(out, "Medium block threshold = %zu\n",
3683
0
            (size_t)MI_MEDIUM_OBJ_SIZE_MAX);
3684
0
    fprintf(out, "Large object max size = %zu\n",
3685
0
            (size_t)MI_LARGE_OBJ_SIZE_MAX);
3686
3687
0
    mi_heap_t *heap = mi_heap_get_default();
3688
0
    struct _alloc_stats stats;
3689
0
    memset(&stats, 0, sizeof(stats));
3690
0
    mi_heap_visit_blocks(heap, false, &_collect_alloc_stats, &stats);
3691
3692
0
    fprintf(out, "    Allocated Blocks: %zd\n", stats.allocated_blocks);
3693
0
    fprintf(out, "    Allocated Bytes: %zd\n", stats.allocated_bytes);
3694
0
    fprintf(out, "    Allocated Bytes w/ Overhead: %zd\n", stats.allocated_with_overhead);
3695
0
    fprintf(out, "    Bytes Reserved: %zd\n", stats.bytes_reserved);
3696
0
    fprintf(out, "    Bytes Committed: %zd\n", stats.bytes_committed);
3697
0
}
3698
#endif
3699
3700
3701
static void
3702
pymalloc_print_stats(FILE *out)
3703
0
{
3704
0
    OMState *state = get_state();
3705
3706
0
    uint i;
3707
0
    const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
3708
    /* # of pools, allocated blocks, and free blocks per class index */
3709
0
    size_t numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
3710
0
    size_t numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
3711
0
    size_t numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
3712
    /* total # of allocated bytes in used and full pools */
3713
0
    size_t allocated_bytes = 0;
3714
    /* total # of available bytes in used pools */
3715
0
    size_t available_bytes = 0;
3716
    /* # of free pools + pools not yet carved out of current arena */
3717
0
    uint numfreepools = 0;
3718
    /* # of bytes for arena alignment padding */
3719
0
    size_t arena_alignment = 0;
3720
    /* # of bytes in used and full pools used for pool_headers */
3721
0
    size_t pool_header_bytes = 0;
3722
    /* # of bytes in used and full pools wasted due to quantization,
3723
     * i.e. the necessarily leftover space at the ends of used and
3724
     * full pools.
3725
     */
3726
0
    size_t quantization = 0;
3727
    /* # of arenas actually allocated. */
3728
0
    size_t narenas = 0;
3729
    /* running total -- should equal narenas * ARENA_SIZE */
3730
0
    size_t total;
3731
0
    char buf[128];
3732
3733
0
    fprintf(out, "Small block threshold = %d, in %u size classes.\n",
3734
0
            SMALL_REQUEST_THRESHOLD, numclasses);
3735
3736
0
    for (i = 0; i < numclasses; ++i)
3737
0
        numpools[i] = numblocks[i] = numfreeblocks[i] = 0;
3738
3739
    /* Because full pools aren't linked to from anything, it's easiest
3740
     * to march over all the arenas.  If we're lucky, most of the memory
3741
     * will be living in full pools -- would be a shame to miss them.
3742
     */
3743
0
    for (i = 0; i < maxarenas; ++i) {
3744
0
        uintptr_t base = allarenas[i].address;
3745
3746
        /* Skip arenas which are not allocated. */
3747
0
        if (allarenas[i].address == (uintptr_t)NULL)
3748
0
            continue;
3749
0
        narenas += 1;
3750
3751
0
        numfreepools += allarenas[i].nfreepools;
3752
3753
        /* round up to pool alignment */
3754
0
        if (base & (uintptr_t)POOL_SIZE_MASK) {
3755
0
            arena_alignment += POOL_SIZE;
3756
0
            base &= ~(uintptr_t)POOL_SIZE_MASK;
3757
0
            base += POOL_SIZE;
3758
0
        }
3759
3760
        /* visit every pool in the arena */
3761
0
        assert(base <= (uintptr_t) allarenas[i].pool_address);
3762
0
        for (; base < (uintptr_t) allarenas[i].pool_address; base += POOL_SIZE) {
3763
0
            poolp p = (poolp)base;
3764
0
            const uint sz = p->szidx;
3765
0
            uint freeblocks;
3766
3767
0
            if (p->ref.count == 0) {
3768
                /* currently unused */
3769
#ifdef Py_DEBUG
3770
                assert(pool_is_in_list(p, allarenas[i].freepools));
3771
#endif
3772
0
                continue;
3773
0
            }
3774
0
            ++numpools[sz];
3775
0
            numblocks[sz] += p->ref.count;
3776
0
            freeblocks = NUMBLOCKS(sz) - p->ref.count;
3777
0
            numfreeblocks[sz] += freeblocks;
3778
#ifdef Py_DEBUG
3779
            if (freeblocks > 0)
3780
                assert(pool_is_in_list(p, usedpools[sz + sz]));
3781
#endif
3782
0
        }
3783
0
    }
3784
0
    assert(narenas == narenas_currently_allocated);
3785
3786
0
    fputc('\n', out);
3787
0
    fputs("class   size   num pools   blocks in use  avail blocks\n"
3788
0
          "-----   ----   ---------   -------------  ------------\n",
3789
0
          out);
3790
3791
0
    for (i = 0; i < numclasses; ++i) {
3792
0
        size_t p = numpools[i];
3793
0
        size_t b = numblocks[i];
3794
0
        size_t f = numfreeblocks[i];
3795
0
        uint size = INDEX2SIZE(i);
3796
0
        if (p == 0) {
3797
0
            assert(b == 0 && f == 0);
3798
0
            continue;
3799
0
        }
3800
0
        fprintf(out, "%5u %6u %11zu %15zu %13zu\n",
3801
0
                i, size, p, b, f);
3802
0
        allocated_bytes += b * size;
3803
0
        available_bytes += f * size;
3804
0
        pool_header_bytes += p * POOL_OVERHEAD;
3805
0
        quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
3806
0
    }
3807
0
    fputc('\n', out);
3808
#ifdef PYMEM_DEBUG_SERIALNO
3809
    if (_PyMem_DebugEnabled()) {
3810
        (void)printone(out, "# times object malloc called", serialno);
3811
    }
3812
#endif
3813
0
    (void)printone(out, "# arenas allocated total", ntimes_arena_allocated);
3814
0
    (void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas);
3815
0
    (void)printone(out, "# arenas highwater mark", narenas_highwater);
3816
0
    (void)printone(out, "# arenas allocated current", narenas);
3817
3818
0
    PyOS_snprintf(buf, sizeof(buf),
3819
0
                  "%zu arenas * %d bytes/arena",
3820
0
                  narenas, ARENA_SIZE);
3821
0
    (void)printone(out, buf, narenas * ARENA_SIZE);
3822
3823
0
    fputc('\n', out);
3824
3825
    /* Account for what all of those arena bytes are being used for. */
3826
0
    total = printone(out, "# bytes in allocated blocks", allocated_bytes);
3827
0
    total += printone(out, "# bytes in available blocks", available_bytes);
3828
3829
0
    PyOS_snprintf(buf, sizeof(buf),
3830
0
        "%u unused pools * %d bytes", numfreepools, POOL_SIZE);
3831
0
    total += printone(out, buf, (size_t)numfreepools * POOL_SIZE);
3832
3833
0
    total += printone(out, "# bytes lost to pool headers", pool_header_bytes);
3834
0
    total += printone(out, "# bytes lost to quantization", quantization);
3835
0
    total += printone(out, "# bytes lost to arena alignment", arena_alignment);
3836
0
    (void)printone(out, "Total", total);
3837
0
    assert(narenas * ARENA_SIZE == total);
3838
3839
0
#if WITH_PYMALLOC_RADIX_TREE
3840
0
    fputs("\narena map counts\n", out);
3841
0
#ifdef USE_INTERIOR_NODES
3842
0
    (void)printone(out, "# arena map mid nodes", arena_map_mid_count);
3843
0
    (void)printone(out, "# arena map bot nodes", arena_map_bot_count);
3844
0
    fputc('\n', out);
3845
0
#endif
3846
0
    total = printone(out, "# bytes lost to arena map root", sizeof(arena_map_root));
3847
0
#ifdef USE_INTERIOR_NODES
3848
0
    total += printone(out, "# bytes lost to arena map mid",
3849
0
                      sizeof(arena_map_mid_t) * arena_map_mid_count);
3850
0
    total += printone(out, "# bytes lost to arena map bot",
3851
0
                      sizeof(arena_map_bot_t) * arena_map_bot_count);
3852
0
    (void)printone(out, "Total", total);
3853
0
#endif
3854
0
#endif
3855
3856
0
}
3857
3858
/* Print summary info to "out" about the state of pymalloc's structures.
3859
 * In Py_DEBUG mode, also perform some expensive internal consistency
3860
 * checks.
3861
 *
3862
 * Return 0 if the memory debug hooks are not installed or no statistics was
3863
 * written into out, return 1 otherwise.
3864
 */
3865
int
3866
_PyObject_DebugMallocStats(FILE *out)
3867
0
{
3868
0
#ifdef WITH_MIMALLOC
3869
0
    if (_PyMem_MimallocEnabled()) {
3870
0
        py_mimalloc_print_stats(out);
3871
0
        return 1;
3872
0
    }
3873
0
    else
3874
0
#endif
3875
0
    if (_PyMem_PymallocEnabled()) {
3876
0
        pymalloc_print_stats(out);
3877
0
        return 1;
3878
0
    }
3879
0
    else {
3880
0
        return 0;
3881
0
    }
3882
0
}
3883
3884
#endif /* #ifdef WITH_PYMALLOC */