Skip to content

feat(libkernel): implement thread cancellation - #1141

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
nicolasabosch:feat/kernel-pthread-cancel
Oct 10, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
nicolasabosch:feat/kernel-pthread-cancel

Conversation

@nicolasabosch

Copy link
Copy Markdown
Contributor

What

scePthreadCancel and pthread_cancel threw, scePthreadTestcancel did nothing and the cleanup handler exports did not exist (recorded in TechnicalDebt as "Thread cancellation is not modelled"). This implements deferred cancellation after FreeBSD libthr (thr_cancel.c, thr_clean.c, thr_exit.c).

  • scePthreadCancel / pthread_cancel record the request on the thread and wake it when it is blocked in a cancellable wait. A null thread returns ESRCH.
  • A request is acted on at scePthreadTestcancel, the condition variable waits, the scePthreadSem and sem waits, scePthreadJoin and the sleeps, and under their POSIX names. A condition wait takes its mutex back before the thread exits, and a cancelled join leaves the target joinable.
  • The thread exits with PTHREAD_CANCELED (1) through scePthreadExit, which now runs the handlers of the new __pthread_cleanup_push_imp and __pthread_cleanup_pop_imp exports, newest first. The handler node uses the guest's _pthread_cleanup_info like libthr's struct pthread_cleanup.
  • scePthreadSetcancelstate and scePthreadSetcanceltype return EINVAL for unknown values and, like libthr, test for a pending request when the type is asynchronous. pthread_setcanceltype is added.
  • pthread_cancel moves from Unimplemented.cpp to Pthread/Posix/Thread.cpp with its real signature.

Limits, recorded in TechnicalDebt: a sleep is not interrupted (the thread exits when it ends, so the sceKernelUsleep path keeps its timing), file and socket calls are not cancellation points, and the asynchronous type acts like the deferred one except at the two set calls. The constants and the node layout are FreeBSD's, not measured on the console; the NIDs of the two cleanup exports come from their names and I have not seen a title import them.

#760 adds three lines to Pthread.hpp and Thread.cpp in other places; this does not depend on it.

Tested

Windows 11, WinLibs GCC 15.2.0: full build, libs target and ctest (387 passed; agc_driver_sdwa_float_selectors, shader_clock, vop1_float_unary, vop3_mad_i64 and vopc_compare excluded, they fail on this machine's Intel Arc GPU without this change). New guest_pthread_cancel test cancels threads blocked in a condition wait (while the canceller holds the mutex), scePthreadSemWait, sem_wait, scePthreadJoin and a sceKernelUsleep loop, checks the disabled state, the asynchronous type, the handler order and the error codes; it passed 40 runs in a row, and 15 with APS5_COARSE_TIMED_WAITS=1. Not tested on Linux and not tested with a title.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Progress report (948a526 → ef9d0dd)

📈 System libraries: 84.51% (+0.07%, +5 implemented functions)

✅ 5 implemented
Library Name
libkernel __pthread_cleanup_pop_imp_nid_postfix
libkernel __pthread_cleanup_push_imp_nid_postfix
libkernel pthread_cancel_nid_postfix
libkernel pthread_setcanceltype_nid_postfix
libkernel scePthreadCancel

@tv7

tv7 commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Data point: PPSA03306 (Silt, Unity) imports __pthread_cleanup_push_imp (1xvtUVx1-Sg). On main (cea1ef13), startup stops at FAIL: unresolved ELF import 1xvtUVx1-Sg from libkernel.prx. With this PR merged locally, the import resolves and startup continues to the next missing import (hypotf, which #1196 adds). Windows 11, GCC 15.2.0, RTX 3070. I only checked startup, not whether the cleanup handlers run.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

One thing before this can go in: please drop the // Canonical lib is libScePosix ... comment at Pthread/Posix/Thread.cpp:87-89; code comments are only allowed as technical-debt markers.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Conflicts with main in Pthread/src/Cond.cpp (the recursive-mutex cond wait change, 7406c97) and docs/dev/TechnicalDebt.md; please rebase.

Sanjaysrinivas added a commit to Sanjaysrinivas/AnyPS5 that referenced this pull request Oct 9, 2026
Refs boykopovar#1668. Complements boykopovar#1141 with resource ownership and lifecycle regressions.
@adriadam10 adriadam10 mentioned this pull request Oct 9, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased onto current main as @oneandonlydean asked (conflicts in Pthread/src/Cond.cpp, Pthread/src/Thread.cpp and docs/dev/TechnicalDebt.md); the pthread_cancel comment was already dropped.

  • Cond.cpp: the recursive-mutex wait keeps main's unlock/relock of the extra levels around ThreadCancel::Wait.
  • Thread.cpp: the cancel state, cancel type, exiting flag and cleanup handler stack now live in GuestThreadState (main moved the thread state to WindowsThreadLocal) instead of separate thread_locals.
  • TechnicalDebt.md: the "Thread cancellation" line replaces the old one; the neighbouring lines are main's.

Rebuilt and ran the libkernel/libs tests on Linux: all green, guest_pthread_cancel passes 30 runs in a row.

@adriadam10
adriadam10 force-pushed the feat/kernel-pthread-cancel branch from 6d38053 to 91ab3f7 Compare October 10, 2026 09:27
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 10, 2026
scePthreadCancel and pthread_cancel threw, scePthreadTestcancel did
nothing and the cleanup handler exports did not exist.

A cancel request is now recorded on the thread and acted on at
scePthreadTestcancel, the condition variable waits, scePthreadSem and
sem waits, scePthreadJoin and the sleeps, and under their POSIX names.
A thread blocked in one of the waits is woken; a condition wait takes
its mutex back before the thread exits. The thread exits with
PTHREAD_CANCELED through scePthreadExit, which now runs the handlers
of __pthread_cleanup_push_imp and __pthread_cleanup_pop_imp.
scePthreadSetcancelstate and scePthreadSetcanceltype reject unknown
values, and pthread_setcanceltype is added.

Constants, the handler node layout and the order of events follow
FreeBSD libthr. A sleep is not interrupted, file and socket calls are
not cancellation points and the asynchronous type acts like the
deferred one except at the two set calls (TechnicalDebt). New test:
guest_pthread_cancel.
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased again onto current main (@oneandonlydean asked for a rebase): the only conflict was Unimplemented.cpp, where the old pthread_cancel stub and its comment are now removed since the real export lives in Pthread/Posix/Thread.cpp.

Rebuilt and ran the libkernel/libs tests on Linux: all green.

@adriadam10
adriadam10 force-pushed the feat/kernel-pthread-cancel branch from 91ab3f7 to ef9d0dd Compare October 10, 2026 09:33
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 10, 2026
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#2478 docs/dev/TechnicalDebt.md L325

@github-actions github-actions Bot mentioned this pull request Oct 10, 2026
6 tasks done
@adriadam10
adriadam10 merged commit be40308 into boykopovar:main Oct 10, 2026
14 checks passed
Sanjaysrinivas added a commit to Sanjaysrinivas/AnyPS5 that referenced this pull request Oct 10, 2026
Refs boykopovar#1668. Complements boykopovar#1141 with resource ownership and lifecycle regressions.
Sanjaysrinivas added a commit to Sanjaysrinivas/AnyPS5 that referenced this pull request Oct 10, 2026
Refs boykopovar#1668. Complements boykopovar#1141 with resource ownership and lifecycle regressions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants