D453 - POSIX thread-specific-data keys; PPSA21564's TBB scheduler stops aborting

measured - 2026-09-01 (user-directed /loop)

PPSA21564, "booting" after D451/D452, did not actually reach a main loop - it raced (the D450 non-determinism) between running to the call budget and aborting: TBB failed to initialize task scheduler TLS -> the guest called abort. Unity ships Intel TBB, whose task scheduler keeps its per-thread state through pthread_key_create/pthread_setspecific. Those were declared in orbistoun-posix but served by nobody (arity 0, provisional), so they answered the placeholder - which TBB read as key allocation failing.

The fix. orbistoun has static ELF TLS (the __thread block, in the loader) but not the POSIX dynamic key API. Implemented the family - pthread_key_create/pthread_setspecific/ pthread_getspecific/pthread_key_delete - in orbistoun-kernel beside the thread registry, and wired the libScePosix delegation. A key is a small integer from a monotonic counter; the value bound to it is per thread, held in a thread_local! map, because a guest thread is a host thread here (D014) and a thread that never set a key must read null - which a fresh map gives, exactly as POSIX requires. The destructor pthread_key_create is handed is recorded nowhere and never run: nothing tears a guest thread down through this layer yet.

The result, and it is now deterministic. The TBB abort is gone ((was the guest called abort)), and - notably - the fault site stopped racing: every run now reaches the same new wall at ~500k calls. So the TLS keys did double duty, removing both the abort and the scheduler-timing nondeterminism D450 first saw on this title.

The new wall, characterised. read of 0x7fff0001 with rdi = 0x7fff0001 - a placeholder dereferenced as a first-argument pointer, in a string compare (strncmp -> c_len, misattributed by nearest-symbol to the adjacent __cxa_guard_acquire). The report also flags "1 system parameter query answered with a placeholder". So an unimplemented pointer-returning call still in this title's set - sceKernelGetGPI, asctime, or localtime are the live suspects - hands back 0x7fff0001, and a C++ static initialiser feeds it to a string compare. This is the same D344 class one layer deeper, reached only because TBB now initialises. asctime/localtime are the awkward ones: they return a char*/struct tm*, and the tm layout is implementation-defined rather than cleanly citable, so the honest fix is readable storage (as with the ctype table) rather than a guessed layout - to be settled next.

fmt/clippy/cargo test/the knowledge audit pass for the additions (the kernel crate's pre-existing fmt drift in test code is untouched and not in these additions). Additive - four new POSIX symbols served - so other titles are unaffected.