__next_mem_range(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’« __next_mem_range β€” the kernel API manual, but make it make sense πŸ’«

okay bestie, so this is a page from the Kernel API Manual (the <italic>9</italic> section, iykyk) and today's main character is __next_mem_range. she's a helper function, she's lowkey the engine behind for_each_free_mem_range() and friends, and honestly? iconic. let's get into it 🫢


✨ NAME ✨

__next_mem_range β€” the next function for for_each_free_mem_range() etc.

like, literally the "give me the next one" function. that's the vibe. πŸ’…


🌸 SYNOPSIS 🌸

void __next_mem_range (u64 *idx , int nid , enum memblock_flags flags ,
       struct memblock_type *type_a , struct memblock_type *type_b ,
       phys_addr_t *out_start , phys_addr_t *out_end , int *out_nid );

she returns void, so don't go looking for a return value, she gives you her answers through the out-params instead. main character energy fr. πŸŽ€


πŸ¦‹ ARGUMENTS πŸ¦‹

  • idx β€” pointer to a u64 loop variable. this is the tracker, the little bookmark that remembers where we're up to. ✨
  • nid β€” the node selector. pass NUMA_NO_NODE if you want all nodes, no filter, everybody welcome. 🌈
  • flags β€” pick which blocks you want based on their memory attributes. it's giving "choose your fighter". πŸ’…
  • type_a β€” pointer to the memblock_type that the range is taken from. the source, the origin story. πŸ’–
  • type_b β€” pointer to the memblock_type that excludes memory from being taken. the bouncer at the door, ngl. πŸ™ˆ
  • out_start β€” ptr to a phys_addr_t for the start address of the range. can be NULL. βœ…
  • out_end β€” ptr to a phys_addr_t for the end address of the range. can be NULL. βœ…
  • out_nid β€” ptr to an int for the nid of the range. can be NULL. βœ…
yes bestie, all three out-params are optional β€” if you don't need one, just pass NULL and she won't be offended 🫢

πŸ”₯ DESCRIPTION πŸ”₯

so what does she actually do? she finds the first area starting from *idx that matches nid, fills in all those out parameters for you, and then updates *idx so the next iteration knows where to pick up. it's a whole relay race and she's passing the baton. πŸƒβ€β™€οΈπŸ’¨

now here's the crunchy part, and you're gonna want to focus for this one:

the lower 32 bits of *idx contain the index into type_a, and the upper 32 bits index the areas before each region in type_b. two indexes, one u64, no cap. πŸ’€

for example, if the type_b regions look like this:

0:[0-16), 1:[32-48), 2:[128-130)

then the upper 32 bits index these regions:

0:[0-0), 1:[16-32), 2:[48-128), 3:[130-MAX)

see how the gaps are the whole point? she's mapping the spaces between the type_b regions. the negative space. the lore. πŸ¦‹βœ¨

and because both region arrays are sorted, the function advances the two indices in lockstep and returns each intersection. sorted input, synchronized walking, intersection delivered. she ate and left absolutely no crumbs. πŸ‘‘


πŸ’œ SEE ALSO πŸ’œ

okay this is the part where the original page just goes absolutely feral with the cross-references, and I respect it too much to trim a single one. here's the whole squad:

ngl that's a lot of friends, but every single one of them is invited to the group chat πŸ’€πŸ’–

and that's the page!! this one came out of the ./mm source, dated October 2026, so go off and go read the memblock code bestie, she's waiting for you πŸŒΈβœ¨πŸŽ€πŸ¦‹πŸ’…

πŸ“¦ where this page comes from