Conversation
Three size decisions for the 2026-09-30 pass, each one option apart from the same tree at 994aa0e and measured on the pinned toolchain: micro -5,184 bytes of bsdsocket.library (206,856 -> 201,672) and 2,072 bytes of resident AmiNetStack AMINETXDUO_DNS_CACHE=OFF -3,236 alone AMINETXDUO_IP_FRAGMENTATION=OFF -1,892 alone both -5,184 minimal -3,228 bytes (241,288 -> 238,060): AMINETXDUO_HOT_O2=OFF, which pays that drawer's whole overshoot. The full drawer keeps the hot list -- nothing in this tree has ever measured what it buys, and the full drawer is where it was aimed. micro is 201,672 against a 205,000 budget, minimal 238,060 against 239,000. The full drawer's 2,828-byte overshoot is untouched: it is shared shim code, not a profile feature. The resolver keeps no answer cache in micro, so gethostbyname() and gethostbyaddr() ask the name server every time instead of once per TTL. That is a size decision with a price on a slow link, and it is the one drawer that pays it. Fragmentation off takes the transmit splitter and the receive reassembler out together, because NetX Duo has no receive-only arm. It needs shim work to be honest: with no fragmenter to hand an oversize packet to, nx_ip_driver_packet_send() releases it and returns NX_SUCCESS, so the sender is told the bytes went. bsd_nofrag_maxdgram() (transfer.c) caps UDP and raw sends at the smallest attached interface MTU less the headers and refuses the rest with EMSGSIZE, and src/netstack/netstack.c skips nx_ip_fragment_enable() rather than reporting the NX_NOT_ENABLED it now answers as a fault at every stack start. TCP is unaffected in both directions: a segment's size follows the MTU. Two options and the micro preset carry it; the guide and the changelog say what the user loses. CROSS_CONFIGS gets a nofrag arm because that combination builds the shim's smallest-MTU loop for four interfaces with IPv6 on, which no other arm compiles. The full flag space was swept the same day and is empty; the results, including why -mregparm is unusable as a flag though the attribute form is not, are in CMakeLists.txt. -Oz and -fomit-frame-pointer are each worth exactly nothing, -msmall-code is 800 bytes worse, and -fbaserel does not link. There is no floating-point code in any image. Not addressed here: anxgenet.device (29,096 against 29,000) and usergroup.library (10,172 against 10,000) are over their budgets in all three arms, before this change as after it. Co-Authored-By: Claude Code <noreply@anthropic.com>
tinic
added a commit
that referenced
this pull request
Sep 30, 2026
bsd_stack_ip(), bsd_stack_pool(), bsd_stack_last_opener(), bsd_owner_elect() and bsd_owner_drop() were `static inline` in bsdsocket_internal.h, so every translation unit that touches a base carried its own copy: -O2 inlines a function called once in a TU whatever its size, and bsd_stack_ip() alone has 53 call sites across 16 translation units off LTO. They are shared code with one implementation, so they are one implementation, in base.c, called. Called is not expensive here. Each takes at most two arguments, and each is marked regparm(2), so they arrive in registers rather than on the stack. On this target the convention is address registers for pointers and data registers for integers -- the caller emits `movea.l 8(sp),a0` / `jsr _bsd_stack_ip`, with nothing pushed. The attribute is part of the function type, so it is on the declarations in the header and on the definitions in base.c: a caller that does not see it pushes its arguments into a callee reading registers, which is a miscompile and not a warning. It is also a target attribute -- m68k implements it, host x86-64 gcc and clang do not -- so BSD_REGPARM2 expands to nothing off the Amiga and the host tier compiles base.c unchanged. bsdsocket.library, origin/main c3bb63c, m68k-amigaos-gcc 16.2.0b, -flto: arm before out of line + regparm(2) default 368,896 -- 368,608 -288 minimal 241,320 241,148 241,016 -304 micro 206,860 206,712 206,608 -252 Roughly 100-130 bytes of that is the attribute itself on these five calls (micro -104, minimal -132); the rest is one copy instead of one per translation unit. This is a size lever of its own and does not touch the default drawer's overshoot, which is shared shim code. The branch is on origin/main alone and does not carry the option changes in #120, so minimal's baseline here is still 2,320 over its 239,000 budget. The host tests that compile the callers get base.c: handoff builds and passes (53 checks, 0 failures), and expunge and expunge_cork fail to link on origin/main already, for two symbols out of library.c this does not touch -- the undefined references are identical before and after.
Owner
Author
|
Closing as superseded by current main. The verified f2d14df release-candidate archive contains bsdsocket.library at 346,336 bytes (full), 226,404 (minimal), and 194,216 (micro), all below this PR’s respective 366,000 / 239,000 / 205,000 limits without removing DNS caching or fragmentation. This branch is now far behind main with conflicts and failing checks; its tip is preserved for recovery. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Base
994aa0ed, candidate76806432, one commit,CHANGELOG.mdin it.The minimal and micro drawers were both over their
bsdsocket.librarybudget. Both are now under, by taking options the drawer already promises
away, plus the shim work one of them needs to be honest about it.
AMINETXDUO_HOT_O2=OFF(-3,228)Measured one option apart from the same tree at
994aa0edon the pinnedtoolchain (16.2.0b),
cmake --preset <arm> -B <dir>,--target release_libraries. Full drawer is still 2,828 over and stays that way here:it is shared shim code, not a profile feature.
anxgenet.device(+96) andusergroup.library(+172) are over in all three arms before this change asafter.
micro: no answer cache.
gethostbyname()/gethostbyaddr()ask the nameserver every time rather than once per TTL.
AMINETXDUO_DNS_CACHE=OFFleavesNX_DNS_CACHE_ENABLEundefined, which drops the table and the lookup code fromnx_dns.c;netstack_dns.cguards itsnx_dns_cache_initialize()on the samemacro, so nothing else moves.
micro: no fragmenter.
AMINETXDUO_IP_FRAGMENTATION=OFFtakes the transmitsplitter and the receive reassembler out together (NetX Duo has no
receive-only arm). This one needs shim work, and that is most of the diff:
nx_ip_driver_packet_send()releases it and returns
NX_SUCCESS, so a sender is told the bytes went.bsd_nofrag_maxdgram()(src/bsdsocket/transfer.c) caps UDP and raw sends atthe smallest attached interface MTU less the headers and refuses the rest with
EMSGSIZE. The egress interface is not this layer's to know, so the smallestMTU is exact for the one-interface drawer that takes this and wrong in the safe
direction for a multi-interface build.
nx_ip_fragment_enable()answersNX_NOT_ENABLEDrather than failing, sosrc/netstack/netstack.cskips the call and its warning instead of logging afault at every stack start.
CROSS_CONFIGSgains anofragarm, becauseAMINETXDUO_IP_FRAGMENTATION=OFFfor four interfaces with IPv6 on is the only build that compiles the shim's
smallest-MTU loop and its IPv6 header arithmetic. Gate set: image size,
ram size, option coverage, shipping config, changelog prose, ci arm coverage and
stage coverage all pass; the new arm builds clean.
minimal: the hot
-O2list off. Eight profiled NetX Duo translation unitsbuilt at
-O2after the tree's-Os. Turning that off pays the drawer's wholeovershoot on its own. The full drawer keeps the list, since nothing in this tree
has ever measured what it buys and the full drawer is where it was aimed.
The rest of the compiler-flag space was swept the same day and is empty; the
numbers and the reasoning are written into
CMakeLists.txtnext to the flags.-Ozand-fomit-frame-pointerare each worth exactly nothing (0 bytes,byte-identical output),
-msmall-codeis 800 bytes worse,-fbasereldoes notlink, and there is no floating-point code in any image.
-mregparmis 11,800bytes smaller and unusable as a flag -- it moves the convention for every call
including leads out to Exec and SANA-II -- but
__attribute__((regparm(N)))isselective and is a separate, larger piece of work, deliberately not in this PR.
Two gates are red on
994aa0edand stay red here, both untouched by thischange and both verified against a pristine checkout of the base:
tools/aminet-survey/check-derived.sh(own-tools.tsvno longer matchessrc/tools/src/config), andtools/check-stage-freshness.sh(every workflowbehind every stage has zero successes in its last 20 runs, so the local
hoststage stops before ctest).
🤖 Generated with Claude Code