Skip to content

vita: exit through newlib and let pte own its per-thread slot behind a switch - #24

Open
frangarcj wants to merge 3 commits into
masterfrom
next-native-tls
Open

vita: exit through newlib and let pte own its per-thread slot behind a switch#24
frangarcj wants to merge 3 commits into
masterfrom
next-native-tls

Conversation

@frangarcj

Copy link
Copy Markdown

What does this change?

Three changes on the Vita OSAL. Threads exit through newlib's vita_exit_thread/vita_exit_delete_thread instead of calling sceKernelExitThread/sceKernelExitDeleteThread directly, so newlib can reclaim the thread's own buffers before its TLS block disappears. The per-thread slot pthread-embedded uses can be owned by pthread-embedded itself instead of newlib, behind the __VITA_NEWLIB_THREAD_SLOT__ switch newlib exports in <sys/vita_thread.h>; at the default value everything behaves as today. The last commit follows newlib's rename of that switch.

Why is this change needed?

Phase A of vitasdk/.github#3. With struct _reent in native TLS, a thread's newlib buffers die with its TLS block, and the only place that can reclaim them is the exiting thread itself; routing the exit through newlib's entry points is what makes that possible. The switch lets pthread-embedded stop depending on newlib's 256-entry slot table once newlib no longer owns it, without changing behaviour before then.

Testing

  • Real PlayStation Vita hardware (3.60, 2026-08-30): newlib-tests built against the native-TLS newlib with this pthread-embedded, 88 tests, 82 pass, 0 failures, 6 skips; the TLS group includes pthread churn with heap bounds, errno isolation between pthreads, and C++ thread_local construction/destruction on pthread return.
  • Vita3K: same suite, with a fix for the emulator's thread END handler.
  • Default value of the switch (newlib keeps the slot): no behavioural change; the existing thread tests pass unchanged.

Compatibility

No API change. At the default switch value, no ABI or behaviour change. Requires the newlib that declares vita_exit_thread/vita_exit_delete_thread (vitasdk/newlib#115); older newlib does not declare them and the link fails loudly rather than silently. Part of RFC vitasdk/.github#3.

Third-party material

None.

AI assistance

  • Claude Opus 5

Additional context

RFC: vitasdk/.github#3. Companion: vitasdk/newlib#115, vitasdk/vita-toolchain#294.

With struct _reent in native TLS a thread's newlib buffers die with its TLS
block, so exiting through vita_exit_thread/vita_exit_delete_thread is the
only way to reclaim them.

Assisted-by: Claude Opus 5
Newlib's kernel-TLS slot table exists to host struct _reent. With the reent
in native TLS the table is a directory of pointers to memory pte already
mallocs itself, so pte can hold the kernel slot directly and newlib can drop
the table, the mutex and the slot along with it.

The key list moves into pspThreadData, collapsing the two slots pte used
into one. The slot stays a kernel TLS slot rather than a TPIDRURO-relative
block because pte_osThreadCancel, pte_osThreadDelete and
pte_osThreadWaitForEnd reach another thread's data through its thid.

__VITA_NEWLIB_THREAD_SLOT__ selects between the two, defaulting to the
newlib slot, so this builds and behaves exactly as before against every
newlib that still provides it.

Assisted-by: Claude Opus 5
__VITA_NEWLIB_THREAD_SLOT__ -> __VITA_NEWLIB_OWNS_THREAD_SLOT__.

Assisted-by: Claude Opus 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant