Process address space on AIX 4.3.3 / PowerPC 604e - prediction log. Author: Claude Fable 5.1 (claude-fable-5-1). Series letter: A. Written BEFORE running svmon, reading any header or man page on the box, or reading Opus 5.5's request-cost page beyond its one-line summary ("fork is priced by the parent's memory"). Format: ID [confidence] claim. See ../../PREDICTIONS-GUIDE.md. Don't open other models' logs on this topic until your round is written. --- round 1: the segment map, as I believe AIX built it on the 604e's 16 x 256 MB segments --- A01 [0.95] sysconf(_SC_PAGESIZE) returns 4096. A02 [0.90] The address of main() is in segment 1 (0x10000000-0x1FFFFFFF). A03 [0.85] An initialised global variable is in segment 2 (0x20000000-0x2FFFFFFF). A04 [0.80] The first malloc() result is also in segment 2, below 0x21000000. A05 [0.70] A local variable in main() is between 0x2FF00000 and 0x2FF30000: the stack grows down from just under the u-block at the top of segment 2. A06 [0.85] The address of printf is in segment 0xD (0xD0000000-0xDFFFFFFF): shared library text, the same address in every process on the box. A07 [0.60] The address of errno (libc's data) is in segment 0xF (0xF0000000-0xFFFFFFFF): shared library data, private per process. A08 [0.80] The first shmat() of a 1 MB region returns exactly 0x30000000. A09 [0.70] A second 1 MB shmat() returns exactly 0x40000000: each attach costs a whole 256 MB segment regardless of size. A10 [0.50] The eleventh concurrent shmat() fails (segments 3..0xC = ten), errno ENOMEM. A11 [0.55] With EXTSHM=ON in the environment, more than ten 1 MB attaches succeed. A12 [0.60] mmap(MAP_ANONYMOUS|MAP_PRIVATE, fd -1) is supported and the first mapping lands in the 0x30000000 segment when no shmat is attached. A13 [0.45] Two 1 MB anonymous mmaps land in the same segment (mmap packs, shmat doesn't). A14 [0.75] Reading *(int *)0 does not fault and returns 0 (the low kernel page is readable from user mode); A15 covers writing. A15 [0.90] Writing to address 0 raises SIGSEGV. A16 [0.85] malloc beyond the data ulimit returns NULL with errno ENOMEM rather than being killed. A17 [0.50] The default `ulimit -d` for claude is 131072 KB (128 MB). A18 [0.50] The default `ulimit -s` is 32768 KB (32 MB). A19 [0.75] Linking with -bmaxdata:0x20000000 and raising the data ulimit lets one malloc of 300 MB succeed, and the pointer is in segment 3 (0x3xxxxxxx). A20 [0.65] The largest accepted -bmaxdata on 4.3.3 is 0x80000000 (segments 3..0xA). A21 [0.70] svmon -P of a trivial process lists its segments with esids including 1, 2, d and f, with 4 KB pages as the unit. A22 [0.85] The text of a running program is a file-backed ("pers") segment in svmon, so two instances of the same binary share text pages. A23 [0.80] /usr/bin/pagesize exists and prints 4096. A24 [0.70] genkld exists and lists loaded shared-library text, which persists after the last process using it exits. A25 [0.55] /usr/samples/kernel/vmtune exists (there is no vmo on 4.3). A26 [0.90] lsattr -El sys0 -a realmem reports 393216 (KB). A27 [0.85] lsps -a shows a single paging space on hd6. --- timing, from the mechanism I expect: fork is copy-on-write, not copy --- A28 [0.50] fork()+_exit() of a process with little touched memory costs 1.0-3.0 ms (median of many). A29 [0.55] fork cost grows linearly with the parent's touched pages at 0.5-5 us per 4 KB page: bookkeeping per page, not a 4 KB copy (which would be >10 us). A30 [0.50] The child's first write to an inherited page (the COW fault) costs 20-80 us. A31 [0.55] First touch of a fresh malloc page (zero-fill fault) costs 10-40 us. A32 [0.70] First touch of a MAP_ANONYMOUS page costs the same as A31 within 30%. A33 [0.60] After the data ulimit is raised to unlimited, a single process can touch at least 200 MB in segment 2 without -bmaxdata (the segment is 256 MB minus stack and u-block). Fri Oct 16 08:18:59 AM UTC 2026 --- round 2, after the round-1 look: mmap(MAP_PRIVATE|MAP_ANONYMOUS) pages cost about 108 us on first write, malloc pages about 41 us and a child's COW write about 67 us; written before testing read-then-write --- A34 [0.70] On a MAP_PRIVATE anonymous mapping a read-only first touch costs 30-50 us/page and the first write afterwards costs a further 50-80 us/page: the 108 us is two faults, a zero-fill then a copy-on-write of the zero page. A35 [0.80] On the sbrk heap, after a read-only first touch, the first write costs under 3 us/page: no second fault. A36 [0.65] On a MAP_SHARED anonymous mapping, as A35: no second fault on write. A37 [0.50] With the data ulimit unlimited and no -bmaxdata, the largest malloc that works is between 250 and 256 MB: the brk ceiling ignores the 32 MB stack ulimit. A38 [0.85] printf's code address (0xd0178ef4) is identical in a gcc-built program and in every run: shared-library text is at one address box-wide. A39 [0.60] /proc does not exist on this install. Fri Oct 16 02:24:59 AM MDT 2026 === OUTCOMES (scored 2026-10-16) === A01 HIT [0.95] sysconf 4096; /usr/bin/pagesize prints 4096. A02 PARTIAL [0.90] &main is 0x20000710: a function descriptor, which lives in segment 2. The code it points to is at 0x10000398, in segment 1 as meant. Badly worded. A03 HIT [0.85] g_init at 0x20001050. A04 HIT [0.80] first malloc at 0x20002248. A05 HIT [0.70] &local = 0x2ff22b20; argv at 0x2ff22c50. A06 PARTIAL [0.85] same wording problem: printf's descriptor is 0xf0043be8 (segment 0xF), its code 0xd0178ef4 (segment 0xD), identical in every process (A38). A07 MISS [0.60] errno is at 0x2ff22ff8, a fixed slot at the very top of the stack area in segment 2, the same address in main and inside a pthread. Not shared-library data. A08 HIT [0.80] 0x30000000 (shmonly.c, nothing else attached). A09 HIT [0.70] 0x40000000. A10 MISS [0.50] eleven attaches succeed: segments 3..0xC and 0xE. The twelfth fails with errno 24 EMFILE ("Too many open files"), not ENOMEM. A11 HIT [0.55] with EXTSHM=ON attaches 11-14 return 0x30c00000, 0x30d00000, ...: packed 1 MB apart in segment 3. A12 HIT [0.60] MAP_ANONYMOUS works; first mapping at 0x30000000. A13 HIT [0.45] 0x30000000 and 0x30100000. A14 HIT [0.75] *(int *)0 reads 0; see Not predicted for how much of segment 0 is readable. A15 HIT [0.90] SIGSEGV. A16 HIT [0.85] NULL, errno 12 ENOMEM ("Not enough space"). A17 HIT [0.50] ulimit: data(kbytes) 131072. A18 HIT [0.50] ulimit: stack(kbytes) 32768. A19 HIT [0.75] 300 MB at 0x30000648..0x42c00647, every page touched. A20 HIT [0.65] -bmaxdata:0x80000000 loads and a 2047 MB malloc spans 0x300005b8..0xaff005b7 (sparse touch). Binaries linked with 0x90000000 or 0xB0000000 refuse to exec: "0509-026 System error: There is not enough memory available now." A21 HIT [0.70] svmon -P (root pass, ict's OK): esids 0, d, 2, f, 1, 3 and one unnamed; Inuse in 4 KB pages (262 for the 1 MB heap plus data). Kernel segment 0 is listed first. A22 HIT [0.85] esid 1 is 'pers code,/dev/hd1:180300', Vsid 5de5 in both instances of hold; their private segments differ (96e2, 1073). A23 HIT [0.80] /usr/bin/pagesize, Sep 1997, prints 4096. A24 HIT [0.70] /usr/bin/genkld (root-only) lists loaded shared text. libXi.a and libMrm.a were absent from its 185 lines; two programs importing them ran and exited; genkld then listed both at 0xd16f1100 and 0xd16fb100 and still did 20 s later. A25 HIT [0.55] /usr/samples/kernel/vmtune, Aug 1999, root-only. A26 HIT [0.90] realmem 393216. A27 HIT [0.85] hd6 on hdisk0, 1152 MB, 4% used. A28 MISS [0.50] 783 us min, 817 us median of 50: under 1 ms. A29 HIT [0.55] min fork 817, 1617, 2452, 4159, 7989 us at 0, 1, 2, 4, 8 MB touched: linear at 3.1-3.5 us per 4 KB page. A30 HIT [0.50] 66-70 us/page at 1-16 MB (99 us at 64 MB, when the box had 22 MB free and was stealing pages). A31 PARTIAL [0.55] 33-38 us/page at 1-2 MB, 42-47 us at 4-16 MB: the top of the range and past it. A32 MISS [0.70] 107-117 us/page, 2.5x the heap. Two faults per page (A34). A33 HIT [0.60] 240 MB malloc'd and touched in segment 2; 255 MB with sparse touch (A37). A34 PARTIAL [0.70] two faults, yes: a read-only first touch costs 62 us/page and the first write after it another 77-82 us. The read is above 30-50 and the write sits at the top of 50-80; the sum is the 108 us seen before. A35 HIT [0.80] 1.0 us/page. A36 HIT [0.65] 0.8-1.0 us/page. A37 HIT [0.50] 255 MB works (0x200005b8..0x2ff005b7), 256 MB returns NULL. A38 HIT [0.85] 0xd0178ef4 from a gcc build, an xlc build and separate runs. A39 HIT [0.60] /proc does not exist. === OUTCOMES, round 3 (scored 2026-10-16, root pass) === A40 MISS [0.60] svmon -G: 98,295 frames, 34,479 in use, 63,816 free (249 MB); file pages 14,375 (56 MB, 42% of what is in use, 15% of memory). The 22 MB free seen during the fork tests was that moment, not a policy; page stealing during the tests freed memory. A41 PARTIAL [0.65] the named segments are all there (0 first, then d, 2, f, 1, 3) but it lists 7: the extra is a 'pers' segment for the process's open output file. A42 HIT [0.70] text Vsid 5de5 in both; private 96e2 vs 1073. A43 PARTIAL [0.55] true but no evidence: libpthreads was loaded before the test. The real test was libXi/libMrm (A24). Calibration: <0.50: 1/1 0.50-0.79: 19/28 (5 miss, 4 partial) >=0.80: 12/14 (2 partial) Not predicted (root pass): genkld lists most objects two or three times; the kernel segment has 1,066 of its pages on paging space; a process's open files appear in svmon as unnamed 'pers' segments. Not predicted: a private anonymous mmap page takes two faults (zero-fill, then copy-on-write) where a heap page takes one, so it costs 2.5x; a MAP_PRIVATE mapping of /dev/zero costs 150-200 us/page; MAP_SHARED anonymous and shmat pages cost 53-75 us, more than the heap's 41. errno lives in the kernel-maintained area at the top of segment 2. Segment 0xE is an ordinary shmat segment. A system call like getpid has a "descriptor" in segment 0xD whose code address is 0x37d0 in the kernel segment and whose TOC slot holds 0x15. 362 pages of segment 0 are readable from user mode (first unreadable page 0x5000): the PowerPC exception vectors at 0x100..0xf00 each start with mtsprg1 r15 (0x7df143a6), 0xc00 (system call) starts with li r12,0x10b2, and 0x1000-0x1200 hold branches. Fork cost measured as the median diverges from the minimum above 8 MB because the box keeps only ~22 MB free and starts stealing pages. --- round 3, before the root pass (svmon, genkld); ict gave the OK on 2026-10-16 --- A40 [0.60] svmon -G shows file pages (persistent plus client) holding more than half of the 96 K real-memory frames: that is why only ~22 MB is ever "free". A41 [0.65] svmon -P of my probe lists 5 or 6 segments: kernel 0 is absent or listed first, then 1 (text), 2 (private), d and f, and one per 1 MB shmat. A42 [0.70] The two instances of the same binary report the same segment id (Vsid) for their text, and different ones for segment 2. A43 [0.55] genkld lists libpthreads.a's text after a program that used it has exited. Fri Oct 16 02:38:11 AM MDT 2026