-
Notifications
You must be signed in to change notification settings - Fork 0
PSP Threading Semantics
This page is the Nakagawa-specific public summary of PSP CreateThread and StartThread research. It is title-neutral and separates measured behavior, public declarations, open implementation comparators, Nakagawa source facts, and inference.
Status: the CreateThread and StartThread hardware-oracle specifications below are planned and not run. Emulator agreement is useful comparator evidence, not silicon proof.
| Class | Meaning |
|---|---|
| HARDWARE_MEASURED | Observed on a real PSP within the stated, bounded scope. |
| PUBLIC_HEADER_FACT | Declared by a public SDK/header or generated public reference. |
| OPEN_FIRMWARE_IMPLEMENTATION | Behavior visible in an open emulator or firmware-like implementation. |
| EMULATOR_CONSENSUS | PPSSPP and JPCSP model the same behavior; still comparator evidence. |
| IMPLEMENTATION_DISAGREEMENT | Public models differ. |
| SOURCE_VERIFIED_NAKAGAWA | Confirmed in the reviewed Nakagawa source tree. |
| INFERENCE | Reasoned interpretation not directly measured or declared. |
| HARDWARE_UNKNOWN | Available evidence does not establish real-PSP behavior. |
A successful route, local test, or emulator match must not be promoted to hardware validation.
- The measured PSP user-call ABI places arguments 5 through 8 in $t0 through $t3: HARDWARE_MEASURED within that user-call scope.
- A real-firmware sceKernelCreateThread measurement established its fifth argument in $t0: HARDWARE_MEASURED. Arguments 6 through 8 were not separately measured in that run.
- Nakagawa stack_arg() extracts arguments 5 through 8 from $t0 through $t3 and later arguments from the caller stack: SOURCE_VERIFIED_NAKAGAWA.
- An ordinary sceKernelWaitEventFlag wait does not dispatch a callback; a subsequent sceKernelCheckCallback() does: HARDWARE_MEASURED for that sequence.
- At the measured non-delete exit seam, positive 0x77 exits as 0x77, while error-shaped 0x800201ac exits as 0x800200d2: HARDWARE_MEASURED for that exact seam only.
The public header declares the following values:
| Attribute | Value | Class | Open question |
|---|---|---|---|
| PSP_THREAD_ATTR_VFPU | 0x00004000 | PUBLIC_HEADER_FACT | Hardware context consequences are unmeasured here. |
| PSP_THREAD_ATTR_USER | 0x80000000 | PUBLIC_HEADER_FACT | Legal mask and normalization remain unknown. |
| PSP_THREAD_ATTR_USBWLAN | 0xa0000000 | PUBLIC_HEADER_FACT | Acceptance and normalization remain unknown. |
| PSP_THREAD_ATTR_VSH | 0xc0000000 | PUBLIC_HEADER_FACT | Acceptance and normalization remain unknown. |
| PSP_THREAD_ATTR_SCRATCH_SRAM | 0x00008000 | PUBLIC_HEADER_FACT | Legality for the tested caller remains unknown. |
| PSP_THREAD_ATTR_NO_FILLSTACK | 0x00100000 | PUBLIC_HEADER_FACT | Requires a bounded in-allocation observation. |
| PSP_THREAD_ATTR_CLEAR_STACK | 0x00200000 | PUBLIC_HEADER_FACT | Pattern and precedence require measurement. |
PPSSPP and JPCSP additionally model KERNEL=0x00001000 and LOW_STACK=0x00400000. Those values are EMULATOR_CONSENSUS in this note, not public-header facts. Legal user masks, KERNEL from a user caller, SCRATCH_SRAM legality, USBWLAN/VSH normalization, unknown bits, and priority bounds remain IMPLEMENTATION_DISAGREEMENT or HARDWARE_UNKNOWN.
The public option type is:
typedef struct {
SceSize size;
SceUID stackMpid;
} SceKernelThreadOptParam;
The public constants identify KERNEL=1 and USER=2 partitions. JPCSP treats stackMpid as a partition identifier for allocation. PPSSPP notices the field but gives it no allocation effect. The PSPSDK block-UID wording carries an explicit uncertainty marker, so a genuine block UID is retained only as a competing hypothesis. The final firmware meaning of stackMpid is HARDWARE_UNKNOWN.
PPSSPP and JPCSP expose SceKernelThreadInfo.stack as a low allocation/base address. That is EMULATOR_CONSENSUS, not confirmed PSP semantics. Establish address orientation before any bounded in-stack sample. Do not probe an adjacent byte or read outside the allocation.
The specification marker is CREATE_THREAD_HARDWARE_ORACLE_SPEC_READY followed by HARDWARE_NOT_RUN. The minimum plan has at least 16 records: 13 discriminators and 3 controls, with at least 2 launches selected from lower-risk phases. Lower-risk is only a planning label; no probe is guaranteed harmless.
| Cell | Option input | Purpose |
|---|---|---|
| C01 | NULL | No-option control. |
| C02 | Non-NULL, size=4 | Prefix-sized option. |
| C03 | Non-NULL, size=8, stackMpid=USER (2) | Primary partition-ID hypothesis. |
| C04 | Non-NULL, size=8, invalid partition 7 | Invalid partition discriminator. |
| C05 | Non-NULL, size=8, stackMpid=KERNEL (1) | Kernel partition discriminator. |
| C06 | Non-NULL, size=8, genuine block UID | Competing PSPSDK hypothesis, not the primary interpretation. |
Remaining cells cover declared attributes, one unknown-bit mutation, bounded priority edges, stack-size controls, and malformed option inputs. Each record retains the raw return value, whether a UID was produced, and observable thread-info state.
Constraints:
- Use partition IDs as the primary stackMpid inputs; keep the block-UID hypothesis separate.
- Establish stack orientation before sampling; never use an adjacent/outside-allocation probe.
- Test LOW_STACK with simultaneous paired allocations, not sequential create/delete address reuse.
- For NO_FILLSTACK, collect a bounded in-stack sample or a count/checksum over an explicitly defined region, not a single byte.
- Keep malformed pointers and malformed sizes in a dedicated phase; do not call them safe.
PPSSPP and JPCSP agree that a nonzero argument block is copied to the child stack, with the argument byte count in $a0 and the child-stack copy address in $a1: EMULATOR_CONSENSUS.
They disagree for a non-NULL pointer with argSize=0:
| Input | PPSSPP model | JPCSP model | Class |
|---|---|---|---|
| argSize > 0, valid pointer | $a0 is the byte count and $a1 points to the child-stack copy. | Same broad model. | EMULATOR_CONSENSUS |
| argSize=0, argp != NULL | $a0=0 and $a1=0. | $a0=0 and $a1 is a child-stack address. | IMPLEMENTATION_DISAGREEMENT |
| argSize=0, argp=NULL | Model-specific zero-argument path. | Model-specific zero-argument path. | HARDWARE_UNKNOWN |
The oracle distinguishes NULL, non-NULL, and misaligned pointers and retains raw failure codes. Huge sizes and malformed pointers are deferred until bounded normal cases establish the observation path.
| State | Comparator models | Class and boundary |
|---|---|---|
| Stack placement | Both model a reserved kernel area, aligned argument area, and 0x40-byte frame. | EMULATOR_CONSENSUS for the broad model; exact PSP spacing is HARDWARE_UNKNOWN. |
| Initial SP | Both derive SP from stack base and size with modeled reservation/alignment. | EMULATOR_CONSENSUS; current formula is not firmware truth. |
| Initial GP | PPSSPP derives module metadata; JPCSP uses the creator GP. | IMPLEMENTATION_DISAGREEMENT; cross-module start is a high-value discriminator. |
| Initial RA | PPSSPP uses a stack return stub; JPCSP uses an internal HLE exit handler. | IMPLEMENTATION_DISAGREEMENT; real-PSP RA is HARDWARE_UNKNOWN. |
| Other registers | 0xDEADBEEF and 0x7F800001 are emulator debug/initialization sentinels. | OPEN_FIRMWARE_IMPLEMENTATION; not hardware initial values. |
The models cover these cases, but exact PSP statuses and ordering remain oracle questions:
- A dormant thread can start.
- Starting an active thread returns an error.
- An exited thread can be restarted from its entry point.
- A never-started dormant thread can be deleted in the model.
- Waiting on a never-started dormant thread is modeled.
- An invalid thread ID is rejected.
Both models reschedule immediately when the child has a strictly better priority. Equal-priority and worse-priority ordering differs, and physical ordering remains unknown. The source-owned marker sequence is BEFORE_START, CHILD_ENTRY, AFTER_START, using a monotonic global counter and no sleeps, arbitrary delays, or hardcoded timing.
The planned specification marker is START_THREAD_HARDWARE_ORACLE_SPEC_READY followed by HARDWARE_NOT_RUN. It contains 17 records, including at least 3 lower-risk launches as a planning subset, covering:
- no-argument start;
- copied arguments;
- zero-size with a non-NULL pointer;
- NULL and misaligned pointer controls;
- initial SP, GP, and RA;
- raw registers at child entry;
- starting twice;
- restarting an exited thread;
- delete before start;
- wait before start;
- invalid IDs;
- returns of 0, a positive value, and a negative/error-shaped value;
- priority scheduling markers.
Return values and register captures must preserve raw observations. No current emulator sentinel or Nakagawa implementation detail is a universal PSP requirement.
VFPU attributes and context behavior have emulator models, but hardware consequences are unmeasured here. This page records the boundary and does not expand the separate VFPU work.
At the reviewed source boundary:
- src/rt/hle.c owns guest ABI extraction and routes CreateThread/StartThread into the scheduler.
- src/rt/sched.c owns the current dormant-thread creation, stack allocation, argument-copy, re-seeding, ready-state, and preemption model.
- docs/HARDWARE_ORACLE.md defines the source-owned probe and publication limits.
These are SOURCE_VERIFIED_NAKAGAWA facts, not firmware-equivalence claims. The remaining compatibility debt is attribute legality/normalization, stackMpid allocation meaning, stack orientation, initial SP/GP/RA/registers, zero-size argument handling, lifecycle return codes, priority ordering, and hardware attribute consequences.
- PSPSDK pspthreadman.h for declarations and attributes.
- PSPSDK ThreadMan reference for the generated public API view.
- PPSSPP ThreadMan implementation and JPCSP ThreadManForUser as open comparators.
- Nakagawa runtime HLE and scheduler as implementation references.
- General ThreadMan and Scheduler model for the title-neutral research companion.
Do not publish private provenance paths, retail inputs, traces, run metadata, or claims that the planned oracle has already run.
Home ยท Current Status ยท Getting Started ยท Research site ยท Public repository
Public-source project manual. Users supply their own lawful inputs; no proprietary game content is distributed.
- ๐ Home
- ๐ Current Status
- ๐ Getting Started
โถ๏ธ Build and Run- ๐งญ Repository Tour
- ๐๏ธ Architecture
- ๐ Static Recompiler
- ๐งฉ Runtime and HLE
- ๐ผ๏ธ Graphics and Display
- ๐ Audio and Media
- ๐งช Verification and Testing
- ๐ฉบ Debugging
- ๐ฎ Hardware Research
- ๐ง Development Workflow
- ๐ค Contributing
- ๐ Publication and Provenance
- ๐ Research and Documentation
- โ FAQ
- ๐ Research Home
- ๐๏ธ Knowledge Base
- ๐ Evidence Standard
- ๐ฌ Hardware Replication