| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b38cfb7 commit b1a5ad8
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,6 +14,7 @@ | |||
| 14 | 14 | #include <stdlib.h> // malloc() | |
| 15 | 15 | #include <stdbool.h> | |
| 16 | 16 | #include <stdio.h> // fopen(), fgets(), sscanf() | |
| 17 | + #include <errno.h> // errno | ||
| 17 | 18 | #ifdef WITH_MIMALLOC | |
| 18 | 19 | // Forward declarations of functions used in our mimalloc modifications | |
| 19 | 20 | static void _PyMem_mi_page_clear_qsbr(mi_page_t *page); | |
@@ -648,7 +649,11 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr, | |||
| 648 | 649 | if (ptr == NULL) { | |
| 649 | 650 | return; | |
| 650 | 651 | } | |
| 651 | - munmap(ptr, size); | ||
| 652 | + if (munmap(ptr, size) < 0) { | ||
| 653 | + _Py_FatalErrorFormat(__func__, | ||
| 654 | + "munmap(%p, %zu) failed with errno %d", | ||
| 655 | + ptr, size, errno); | ||
| 656 | + } | ||
| 652 | 657 | #else | |
| 653 | 658 | free(ptr); | |
| 654 | 659 | #endif | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1433,16 +1433,30 @@ tstate_is_alive(PyThreadState *tstate) | |||
| 1433 | 1433 | // lifecycle | |
| 1434 | 1434 | //---------- | |
| 1435 | 1435 | ||
| 1436 | + /* When huge pages are enabled, _PyObject_VirtualAlloc may back small requests | ||
| 1437 | + * with a full 2MB huge page. We must pass the *mapped* size (not the | ||
| 1438 | + * requested size) to _PyObject_VirtualFree, otherwise munmap receives a | ||
| 1439 | + * sub-hugepage length and fails with EINVAL, leaking the huge page. */ | ||
| 1440 | + #if defined(PYMALLOC_USE_HUGEPAGES) && defined(__linux__) | ||
| 1441 | + # define HUGEPAGE_SIZE (2U << 20) /* 2 MB */ | ||
| 1442 | + # define ROUND_UP_HUGEPAGE(n) \ | ||
| 1443 | + (((n) + HUGEPAGE_SIZE - 1) & ~(HUGEPAGE_SIZE - 1)) | ||
| 1444 | + #else | ||
| 1445 | + # define ROUND_UP_HUGEPAGE(n) (n) | ||
| 1446 | + #endif | ||
| 1447 | + | ||
| 1448 | + | ||
| 1436 | 1449 | static _PyStackChunk* | |
| 1437 | 1450 | allocate_chunk(int size_in_bytes, _PyStackChunk* previous) | |
| 1438 | 1451 | { | |
| 1439 | 1452 | assert(size_in_bytes % sizeof(PyObject **) == 0); | |
| 1440 | - _PyStackChunk *res = _PyObject_VirtualAlloc(size_in_bytes); | ||
| 1453 | + size_t mapped_size = ROUND_UP_HUGEPAGE(size_in_bytes); | ||
| 1454 | + _PyStackChunk *res = _PyObject_VirtualAlloc(mapped_size); | ||
| 1441 | 1455 | if (res == NULL) { | |
| 1442 | 1456 | return NULL; | |
| 1443 | 1457 | } | |
| 1444 | 1458 | res->previous = previous; | |
| 1445 | - res->size = size_in_bytes; | ||
| 1459 | + res->size = mapped_size; | ||
| 1446 | 1460 | res->top = 0; | |
| 1447 | 1461 | return res; | |
| 1448 | 1462 | } | |
@@ -3082,7 +3096,7 @@ push_chunk(PyThreadState *tstate, int size) | |||
| 3082 | 3096 | &tstate->datastack_chunk->data[0]; | |
| 3083 | 3097 | } | |
| 3084 | 3098 | tstate->datastack_chunk = new; | |
| 3085 | - tstate->datastack_limit = (PyObject **)(((char *)new) + allocate_size); | ||
| 3099 | + tstate->datastack_limit = (PyObject **)(((char *)new) + new->size); | ||
| 3086 | 3100 | // When new is the "root" chunk (i.e. new->previous == NULL), we can keep | |
| 3087 | 3101 | // _PyThreadState_PopFrame from freeing it later by "skipping" over the | |
| 3088 | 3102 | // first element: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments