# libSceUlt technical debt ### Unknown function info - [Bound condition variables](../../../core/libs/prx/libSceUlt/Export.cpp) use the creation-time mutex, inferred from PPSA28061 callers of `_sceUltConditionVariableCreate`; the wait caller reloads only the condition argument. Error precedence, busy/state errors, FIFO signal selection and unsupported recursive waits have not been measured on PS5 hardware. Non-null options and waits at recursion depth above one throw. A live condition prevents destroying its bound mutex. Finalization follows the existing host mutex lifecycle: it invalidates conditions and wakes queued or reacquiring waiters with a state error. Scheduling priority and build-version validation are not implemented. - [libSceUlt ulthreads](../../../core/libs/prx/libSceUlt/Export.cpp) - Runtime option defaults still omit the native header, stack size, worker affinity and priority fields; affinity depends on unresolved process configuration queries. Host threads do not use the guest context or worker scheduler. Native concurrent-join error values and precedence remain unverified; the host retains running TryJoin `AGAIN` and competing committed-join `STATE` behavior. Guest TLS, cancellation state and cleanup handlers remain host-thread-affine; context migration has no established contract. - [Ulthread completion](../../../core/libs/prx/libSceUlt/Export.cpp) is published before pthread destructors and native teardown finish, so TryJoin can still block in kernel join. ULT releases its join claim on cancellation or exception, but kernel wait allocation can leave native join ownership and wait registration stranded before commitment; exceptions after commitment cannot restore native joinability either. Mocked precommit failures test only ULT rollback. Creation exceptions before handle publication remove the registration; after publication they retain it because a runner may already use its state. These are host lifecycle guarantees, not console measurements. - [libSceUlt queues](../../../core/libs/prx/libSceUlt/Export.cpp) - Queue-data pool destruction and shared slot limits still require comparison with the native node allocator. - [`sceUltConditionVariableCreate` and `sceUltConditionVariableOptParamInitialize`](../../../core/libs/prx/libSceUlt/Export.cpp) (libSceUlt) are absent from the console export list, where only the underscored variants `_sceUltConditionVariableCreate` and `_sceUltConditionVariableOptParamInitialize` appear; their non-underscored signatures are assumed. Condition variable option parameter initialization only zeroes 128 bytes, and its layout without the common header remains unverified on hardware. - [Status query exports](../../../core/libs/prx/libSceUlt/Export.cpp) lack waiter identities, types and wait values. All five synchronization queries throw before writing output when capacity is nonzero and waiters exist; capacity-zero queries still report counts. `sceUltGetUlthreadRuntimeInfo` throws for a non-empty worker array because no worker threads are started. Recovered layouts, waiting records, worker scheduling and priority accounting lack full console validation. - [Mutex and reader-writer status queries](../../../core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp) throw for held recursive mutexes and ulthread-owned mutexes or write locks: recursive counts and ulthread owner encoding remain unverified. [Firmware 13.42 observations](https://github.com/boykopovar/AnyPS5/pull/9975#issuecomment-6417685562), from native x86-64 module runs with stubbed imports rather than PS5 hardware, supply `lockType` 1/2/0 for read/write/free, pthread `owner` from the thread block's first 8 bytes, `ownerType` 1 and default mutex `lockCount` 0 when held once. Both queries reject any supplied waiting record whose `size` is not 64 with `ULT_ERROR_INVALID` before writing output, as observed without waiters. Validation precedence and record-size checks for the other queries remain unverified. - [Ult factory and creation exports](../../../core/libs/prx/libSceUlt/Export.cpp) without a leading underscore are absent from the supplied module; their signatures remain unresolved. Diagnostic signatures and synchronization argument lists are recovered. - [sceUltMutexTryLock, the reader-writer lock and sceUltUlthreadGetSelf, sceUltUlthreadYield and sceUltUlthreadExit](../../../core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp) (libSceUlt) - the signatures follow the PS Vita libult in [RPCS3](https://github.com/RPCS3/rpcs3/blob/13aa88c3c4d66ea8799e987f7d762d90943ab17b/rpcs3/Emu/PSP2/Modules/sceUlt.cpp) (a 256-byte lock and 128-byte option structures), not a PS5 binary. The rules are assumed: readers may take the lock while a writer waits, a thread that holds the write lock gets `ULT_ERROR_STATE` for any further lock instead of waiting on itself, a reader asking for the write lock waits on its own read lock, and the try forms return `ULT_ERROR_BUSY`. Outside an ulthread, `sceUltUlthreadGetSelf`, `sceUltUlthreadYield` and `sceUltUlthreadExit` return `ULT_ERROR_STATE`; inside one they act on the guest thread it runs on, since ulthreads are not scheduled cooperatively here - [_sceUltWaitingQueueResourcePoolOptParamInitialize, _sceUltSemaphoreOptParamInitialize, _sceUltQueueDataResourcePoolOptParamInitialize, _sceUltQueueOptParamInitialize and _sceUltUlthreadOptParamInitialize](../../../core/libs/prx/libSceUlt/Export.cpp) and [_sceUltReaderWriterLockOptParamInitialize and _sceUltReaderWriterLockCreate](../../../core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp) (libSceUlt) forward to the exports without the underscore; that their argument lists match is inferred from the other underscore Ult exports, not measured ### Functional - [sceUltFinalize](../../../core/libs/prx/libSceUlt/Export.cpp) - allocator-failure behavior is unverified on a PS5. The host may throw `std::bad_alloc` while reserving temporary wake lists; guest waiting-pool exhaustion and native finalization errors are not modeled. - [libSceUlt queues](../../../core/libs/prx/libSceUlt/Export.cpp) use preallocated host storage instead of the supplied guest work area; the guest object layouts remain incomplete. Waiting-queue pool thread limits and waiter priority ordering are not implemented. Finalization wakes blocked queue callers with `ULT_ERROR_STATE`. - [sceUltWaitingQueueResourcePoolDestroy](../../../core/libs/prx/libSceUlt/Export.cpp) refuses with `ULT_ERROR_STATE` only when a thread is currently waiting on a pool-backed mutex, semaphore or queue, matching the PS5 libSceUlt disassembly (0x473a in or55417wcDk); bound but idle objects do not block pool destruction. Waiting-queue pool guest work area node accounting is not implemented.