Repository navigation
fix(libkernel): give Linux guest threads the stack size they request - #1988
adriadam10 merged 2 commits into
Conversation
|
I reviewed the complete four-file diff. The Linux |
|
Windows build check, since the description says Windows wasn't built. Setup: Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Merged onto It builds, and 🤖 Addressed by Claude Code |
|
This conflicts with main after today's merges; could you rebase? It passed testing and is otherwise ready. |
scePthreadCreate on Linux started guest threads with std::thread, so every thread got the host default stack (RLIMIT_STACK, usually 8 MiB) whatever the title asked for. A thread that asks for more than that and uses it crashes with SIGSEGV. Once the thread ran, scePthreadAttrGet also reported the host size instead of the requested one. Create the thread with pthread_create and a stack of the requested size plus what glibc keeps at its top (static TLS, the thread control block and the start_thread frame). That reserve is measured once with a probe thread. The thread reports [top - reserve - size, top - reserve) as its stack, as Windows reports [top - size, top), and the creator waits until the range is set, as on Windows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…coverage Co-Authored-By: Claude <noreply@anthropic.com>
|
Rebased on current
Checked: build and the guest pthread/mutex/cond/semaphore tests pass 10 times in a row; |
aee35dd to
f455b42
Compare
…x-thread-stack-size fix(libkernel): give Linux guest threads the stack size they request
What
On Linux,
scePthreadCreateignored the requested stack size. Guest threads were started withstd::thread, so every thread got the host default stack (RLIMIT_STACK, 8 MiB on most systems) whatever the title passed toscePthreadAttrSetstacksize/pthread_attr_setstacksize. Windows already honours it (_beginthreadexwith the requested size).main.RunThread→SetStackFromHostreplacedstackSize/stackAddresswith the host range.scePthreadAttrGetthen reported 8 MiB for every thread.guest_pthread_attronly passes because it usually reads the attributes before the new thread gets that far. Pinned to one CPU (taskset -c 0) it fails 2 times in 1000 onmain.ulimit -s.Change (Linux only,
Pthread/src/Thread.cpp):pthread_createandpthread_attr_setstacksize.PthreadPrivate::_thr(std::thread) becomespthread_t hostThread. Join and detach usepthread_join/pthread_detach.EINVAL(a 16 KiB stack with 512 KiB of TLS). The host stack is thereforerequested + reserve, rounded up to the page size. The reserve is everything glibc keeps above the start routine's frame. It is measured once with a probe thread, because it is constant within a process.[top - reserve - size, top - reserve)as its guest stack, as Windows records[top - size, top). The creator waits until the range is set beforescePthreadCreatereturns, as on Windows.NativeThreadArgsis now shared by both platforms.scePthreadAttrGetandsceKernelIsStackreport the requested size, and the race above is gone.DEFAULT_STACK_SIZE(1 MiB) on Linux, as on Windows, instead of the host default.Not changed: an address passed with
scePthreadAttrSetstack/scePthreadAttrSetstackaddris still ignored on both platforms. The thread runs on a host-allocated stack of that size. This could be a follow-up.Tested
Linux: WSL2, Ubuntu 22.04, glibc 2.35, GCC 13.4, Release,
ulimit -s8192. No title run.guest_pthread_stack:thread_localdata. Each thread checks thatscePthreadAttrGetreports the requested size and that its frame is inside the reported range. It then recurses through the range down to 8 KiB above its start.main: it aborts at the first thread, where a 16 KiB thread reports 8 MiB. A variant without the size checks (16 MiB only) dies with SIGSEGV.requested - 616bytes for all four sizes.Creating guest thread: Invalid argumenton the 16 KiB thread.guest_pthread_attrpinned to one CPU: 2/1000 failures onmain, 0/3000 with this change.ctest:agc_driver*/agc_write_trackingpass.--repeat until-fail:20.agc_driver_emulated_color_compareandagc_driver_shader_clockfail andagc_driver_flat_storeandagc_driver_global_vcc_basetime out, with or without this change.tools/check_conventions.py --base origin/mainandtools/check_test_registration.py buildpass.#ifdefaroundNativeThreadArgsmoved. A MinGW GCC 10 syntax check ofThread.cppgives the same errors asmain(all from that toolchain's old headers).Overlap:
tools/pr_overlap.pyneedsgit merge-tree --write-tree(git 2.38+), so I checked the open PRs that touchThread.cpp/Pthread.hppby hand withgit merge-tree. No open PR changes the Linux stack size.std::threadblock inscePthreadCreate, so whichever lands second needs a rebase. The conflicts are mechanical: their code moves intoStartNativeThread/ aroundpthread_create.pthread_t hostThreadnext to_thrforpthread_kill. This PR uses that name for the thread handle, so their uses keep working.SetStackFromHostto report the requested size, but it still runs threads on the host default stack.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code