Skip to content

Commit 0224b71

Browse files
naschemeambv
andauthored
bpo-45526: obmalloc radix use 64 addr bits (GH-29062)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parent 887a557 commit 0224b71

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
In obmalloc, set ADDRESS_BITS to not ignore any bits (ignored 16 before). That is
2+
safer in the case that the kernel gives user-space virtual addresses that span
3+
a range greater than 48 bits.

Objects/obmalloc.c

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,21 +1280,30 @@ _Py_GetAllocatedBlocks(void)
12801280

12811281
#if WITH_PYMALLOC_RADIX_TREE
12821282
/*==========================================================================*/
1283-
/* radix tree for tracking arena usage
1283+
/* radix tree for tracking arena usage. If enabled, used to implement
1284+
address_in_range().
12841285
1285-
bit allocation for keys
1286+
memory address bit allocation for keys
12861287
1287-
64-bit pointers and 2^20 arena size:
1288-
16 -> ignored (POINTER_BITS - ADDRESS_BITS)
1289-
10 -> MAP_TOP
1290-
10 -> MAP_MID
1291-
8 -> MAP_BOT
1288+
64-bit pointers, IGNORE_BITS=0 and 2^20 arena size:
1289+
15 -> MAP_TOP_BITS
1290+
15 -> MAP_MID_BITS
1291+
14 -> MAP_BOT_BITS
1292+
20 -> ideal aligned arena
1293+
----
1294+
64
1295+
1296+
64-bit pointers, IGNORE_BITS=16, and 2^20 arena size:
1297+
16 -> IGNORE_BITS
1298+
10 -> MAP_TOP_BITS
1299+
10 -> MAP_MID_BITS
1300+
8 -> MAP_BOT_BITS
12921301
20 -> ideal aligned arena
12931302
----
12941303
64
12951304
12961305
32-bit pointers and 2^18 arena size:
1297-
14 -> MAP_BOT
1306+
14 -> MAP_BOT_BITS
12981307
18 -> ideal aligned arena
12991308
----
13001309
32
@@ -1306,19 +1315,24 @@ _Py_GetAllocatedBlocks(void)
13061315
/* number of bits in a pointer */
13071316
#define POINTER_BITS 64
13081317

1309-
/* Current 64-bit processors are limited to 48-bit physical addresses. For
1310-
* now, the top 17 bits of addresses will all be equal to bit 2**47. If that
1311-
* changes in the future, this must be adjusted upwards.
1318+
/* High bits of memory addresses that will be ignored when indexing into the
1319+
* radix tree. Setting this to zero is the safe default. For most 64-bit
1320+
* machines, setting this to 16 would be safe. The kernel would not give
1321+
* user-space virtual memory addresses that have significant information in
1322+
* those high bits. The main advantage to setting IGNORE_BITS > 0 is that less
1323+
* virtual memory will be used for the top and middle radix tree arrays. Those
1324+
* arrays are allocated in the BSS segment and so will typically consume real
1325+
* memory only if actually accessed.
13121326
*/
1313-
#define ADDRESS_BITS 48
1327+
#define IGNORE_BITS 0
13141328

13151329
/* use the top and mid layers of the radix tree */
13161330
#define USE_INTERIOR_NODES
13171331

13181332
#elif SIZEOF_VOID_P == 4
13191333

13201334
#define POINTER_BITS 32
1321-
#define ADDRESS_BITS 32
1335+
#define IGNORE_BITS 0
13221336

13231337
#else
13241338

@@ -1332,6 +1346,9 @@ _Py_GetAllocatedBlocks(void)
13321346
# error "arena size must be < 2^32"
13331347
#endif
13341348

1349+
/* the lower bits of the address that are not ignored */
1350+
#define ADDRESS_BITS (POINTER_BITS - IGNORE_BITS)
1351+
13351352
#ifdef USE_INTERIOR_NODES
13361353
/* number of bits used for MAP_TOP and MAP_MID nodes */
13371354
#define INTERIOR_BITS ((ADDRESS_BITS - ARENA_BITS + 2) / 3)
@@ -1360,11 +1377,9 @@ _Py_GetAllocatedBlocks(void)
13601377
#define MAP_MID_INDEX(p) ((AS_UINT(p) >> MAP_MID_SHIFT) & MAP_MID_MASK)
13611378
#define MAP_TOP_INDEX(p) ((AS_UINT(p) >> MAP_TOP_SHIFT) & MAP_TOP_MASK)
13621379

1363-
#if ADDRESS_BITS > POINTER_BITS
1364-
/* Return non-physical address bits of a pointer. Those bits should be same
1365-
* for all valid pointers if ADDRESS_BITS set correctly. Linux has support for
1366-
* 57-bit address space (Intel 5-level paging) but will not currently give
1367-
* those addresses to user space.
1380+
#if IGNORE_BITS > 0
1381+
/* Return the ignored part of the pointer address. Those bits should be same
1382+
* for all valid pointers if IGNORE_BITS is set correctly.
13681383
*/
13691384
#define HIGH_BITS(p) (AS_UINT(p) >> ADDRESS_BITS)
13701385
#else
@@ -1416,7 +1431,7 @@ static arena_map_bot_t *
14161431
arena_map_get(block *p, int create)
14171432
{
14181433
#ifdef USE_INTERIOR_NODES
1419-
/* sanity check that ADDRESS_BITS is correct */
1434+
/* sanity check that IGNORE_BITS is correct */
14201435
assert(HIGH_BITS(p) == HIGH_BITS(&arena_map_root));
14211436
int i1 = MAP_TOP_INDEX(p);
14221437
if (arena_map_root.ptrs[i1] == NULL) {
@@ -1476,7 +1491,7 @@ arena_map_get(block *p, int create)
14761491
static int
14771492
arena_map_mark_used(uintptr_t arena_base, int is_used)
14781493
{
1479-
/* sanity check that ADDRESS_BITS is correct */
1494+
/* sanity check that IGNORE_BITS is correct */
14801495
assert(HIGH_BITS(arena_base) == HIGH_BITS(&arena_map_root));
14811496
arena_map_bot_t *n_hi = arena_map_get((block *)arena_base, is_used);
14821497
if (n_hi == NULL) {

0 commit comments

Comments
 (0)