Skip to content

Claude/upgrade ape c library mm z gd - #715

Merged
staalmannen merged 2 commits into
mainfrom
claude/upgrade-ape-c-library-mmZGd
Nov 5, 2026
Merged

staalmannen merged 2 commits into
mainfrom
claude/upgrade-ape-c-library-mmZGd

Conversation

@staalmannen

Copy link
Copy Markdown
Owner

No description provided.

mmaptrim-probe section 0b, with its prediction written down first --
slots give the same small count at every size, address space gives a
count falling as 1/size -- answers on 9front/amd64:

	 1044480 bytes each: 64 live (array's end)  (63 MB held)
	 2097152 bytes each:  5 live                (10 MB held)
	16777216 bytes each:  5 live                (80 MB held)

The same count at eight times the size, for eight times the memory.
The limit is segment slots and there are five.  The smallest size is
the control: below SEG_THRESHOLD, so malloc-backed, no slot, runs to
the array's end.

The prose above the constant already said so.  __p9_syscall.c opened
with "Plan9 allows only ~8 segments per process (NSEG in the kernel).
Using segattach for every mmap quickly exhausts this limit" -- and
then set SEG_THRESHOLD to 1MB, which spends a slot on anything a
program is at all likely to allocate.  The limit was known and the
constant was chosen as though it were not.  php's Zend allocator
grows its heap in 2MB chunks, so it would have stopped at about 10MB.

64MB now: five simultaneous 64MB mappings to reach the ceiling, and
the detachable path kept for the only case worth a slot.

That exposed a second deviation it had been hiding.  POSIX says mmap
answers a page-aligned address and malloc does not, and the malloc
arm returned the raw malloc pointer -- live for everything under the
old threshold, unnoticed, and about to become the common case.  The
arm over-allocates by a page and rounds up now, which is expressible
only because the munmap table already separates base from addr for
partial unmaps; the two changes pay for each other.

munmaptrim-xcheck grows sections 6, 7 and 8 over the real
p9_mmap_tracked, with a _SEGATTACH fake that answers page-aligned
memory, and its extraction now takes the two defines as well -- the
threshold decides which arm each case exercises, so a harness built
without it would test one path twice.

And one of the new controls did not fire the first time.  Breaking
`*basep = base' to `*basep = p' -- a free of a pointer malloc never
returned -- gave 0 failures, because sections 6 and 7 read
mmap_table[0].base and then checked that what was released matched
it.  Both sides came from the same field, so the check held however
wrong the field was.  The harness wraps malloc now, as it already
wrapped free, and the same break gives 3.  Four deliberate breaks are
recorded in the file: 8, 2, 1 and 3 failures.

Section 0 of the xcheck also had to change what it expects, and the
reason is stated in place rather than as a new constant: `track'
derives is_seg from the length, so which release a 2MB fixture gets
is a fact about the threshold, and it moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
CLAUDE.md gets the measured five-slot limit as an invariant, the
probe's real answer (0 of 8 aligned, and the ceiling section 0b was
added to separate), the two libap fixes in the closed list, and the
asctime_r finding with the reason apdecl-sweep could not have
reported it.  php.md closes its third blocker and records that it
closed the other way round from the one expected: the alignment
question answered no, so the trims run -- they just work now.

The xcheck's control count goes from two deliberate breaks to four,
with the note that the fourth gave 0 failures on its first attempt
because the assertion was phrased against the field under test
instead of against something independent of it.  That is the shape to
look for when a break does not fire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
@staalmannen
staalmannen merged commit b71282d into main Nov 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants