sceKernelStartModule, sceKernelStopModule and the self-stop calls now
check their option first: with SDK 2.08 or later its size must be 0x14,
and attribute bits outside 0x00F06000 are an error.
The option's attribute is added to the module's thread attribute rather
than ignored (or, when stopping, replacing it), and the default attribute
is 0 rather than the module's own attribute. A nonzero mpidstack puts the
stack in that partition, which has to be user-accessible for a user
module and kernel-only for a kernel module.
A failed thread creation is now returned instead of asserting.
Hardware test: modules/startoptions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The third argument is a timeout pointer, as threadman.prx shows. A kernel
address from user mode is ILLEGAL_ADDR there; we used to write through it.
Also, no lookup by index: the syscall requires the exact uid.
Adds the threads/tls/allocate test, recorded on hardware.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This is the syscall usersystemlib's sceKernelGetTlsAddr makes when the
thread's cached TLS address is null, as (uid, &addr, 0). Code that has to
run before usersystemlib.prx is loaded (like plugins built with a Rust SDK)
inlines sceKernelGetTlsAddr and imports this directly.
Shares the allocation with sceKernelGetTlsAddr. A thread waiting on a full
pool stores its address pointer as the wait value, so no state changes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Calling allocate on the same thread gives the same ptr, but on a different
one it waits or returns a new ptr.
Let's call it thread local storage for now.
Couldn't think of a better way to do this, maybe there's some fancy
one I don't know about.
Also finished up a couple left over kernel objects.
Maybe a quarter the way there?