Skip to content

feat(libkernel): implement the sigset functions - #1641

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
SleglJan:feat/libkernel-sigset
Oct 9, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
SleglJan:feat/libkernel-sigset

Conversation

@SleglJan

@SleglJan SleglJan commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds the five POSIX signal-set functions to libkernel: sigemptyset, sigfillset, sigaddset, sigdelset and sigismember, with the semantics of FreeBSD 11's lib/libc/gen/sigsetops.c and sys/sys/_sigset.h:

  • The set is four 32-bit words, the same GuestSignalSet layout as Signals.cpp (defined again in the new file, with a static_assert on its size); signal n lives in word (n − 1) >> 5 at bit (n − 1) & 31.
  • Valid signals are 1 to 128 (_SIG_MAXSIG). sigaddset, sigdelset and sigismember return -1 with errno 22 for any other value and leave the set untouched; sigismember returns 1 or 0.
  • sigfillset writes all ones to every word, as FreeBSD does; sigemptyset writes zeros. Neither fails.
  • A null set throws (std::invalid_argument); the console would fault.

shadPS4 implements the same five the same way (src/core/libraries/kernel/threads/exception.cpp).

The functions go in a new System/src/SignalSets.cpp rather than Signals.cpp. Dispatch in Signals.cpp on main tests the blocked mask at bit n, so a set built with these functions would block the wrong signal; #1652 corrects that to bit n − 1 and this PR lists it under Depends on. #1431 described moving the mask to a per-thread bit n − 1 layout, but its current head does not touch Signals.cpp. The only file shared with #1431 is libkernel/CMakeLists.txt.

Overlap: the pr-overlap report lists #1482, #1613, #1616 and #1627 for __error_nid_postfix. That is the shared extern "C" declaration of the errno accessor each of them adds to reach the guest errno, not an export; none of them touches the same files or lines.

In the Linux audit of the homebrew catalog (#1578), sigemptyset, sigfillset and sigdelset were each absent for 19 to 20 of the 34 relinked titles, sigaddset for 10.

Tested

  • Linux (CachyOS, kernel 7.2.9, GCC 16.2.1), full build with BUILD_TESTING=ON and ANYPS5_ENABLE_SPIRV_TOOLS=ON on main 4b005b2: ctest --repeat until-fail:3 467/467; tools/check_test_registration.py and tools/check_conventions.py --base upstream/main pass.
  • New guest_signal_sets test: empty; fill, then membership of all 128 signals; add at the word boundaries 1, 32, 33, 65, 96 and 128 and delete at 1, 32, 33, 96 and 128, with every other word checked; idempotent add; delete of an absent signal; errno 22 and an unchanged set for 0, -1, 129, 1000, INT_MIN and INT_MAX, against a nearly empty and a full set; errno untouched by every successful call. Written before the implementation; it failed on the five unresolved exports and passes with them.
  • The patched libkernel.prx exports the five NIDs (+F7C-hdk7+E, VkTAsrZDcJ0, JUimFtKe0Kc, Nd-u09VFSCA, JnNl8Xr-z4Y).
  • tools/import_audit.py on catalog titles, absent imports before → after: PPSA69420 ScreenTester5 9 → 7, PPSA17641 SymphonyStation5 35 → 33, PPSA99007 Yamagi Quake II 23 → 19, PPSA99420 PS5MC 121 → 116. None of them loads yet; the remaining imports are listed in Four open-source homebrew titles stop at start-up on unresolved imports (sysctl, pthread_set_name_np, isatty, mkstemp, signal sets, Opus decoders) #1578.
  • Windows: the same Build workflow run on this commit in the fork's Actions (merged onto main 6b56175), run 37822072979: guest_signal_sets passes its three repeats, full suite 474/474. The first attempt timed out in guest_raise_exception, the hang described in sceKernelRaiseException on Windows can stop a thread inside emulator code that holds a host lock #1488, and passed on the rerun.

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: fix(libkernel): block guest signals by FreeBSD's bit n - 1 #1652
  • AI-assisted: yes

🤖 Generated with Claude Code

@klosixgaming-arch klosixgaming-arch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean implementation of the five POSIX signal-set functions following FreeBSD semantics. The bit manipulation is correct, validation is thorough (signal range 1-128), and error handling properly sets errno to EINVAL for invalid signals. Test coverage is excellent - covers all operations, word boundaries, idempotent add, and invalid signal cases with errno verification. Good separation into a dedicated SignalSets.cpp file to avoid conflicts with the Signals.cpp rewrite in #1431.

@github-actions

github-actions Bot commented Oct 8, 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
#1675 __error_nid_postfix
#1729 __error_nid_postfix
#1772 __error_nid_postfix
#1841 __error_nid_postfix
#1860 __error_nid_postfix

Add sigemptyset, sigfillset, sigaddset, sigdelset and sigismember with
FreeBSD 11 semantics (lib/libc/gen/sigsetops.c): a 128-bit set of four
32-bit words, signal n at bit n - 1, signals 1 to 128 valid. sigfillset
sets every bit. An invalid signal returns -1 with errno EINVAL and leaves
the set untouched; sigismember returns 1 or 0. A null set throws.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@SleglJan
SleglJan force-pushed the feat/libkernel-sigset branch from 2c5beb7 to e6a9b50 Compare October 8, 2026 15:46
@SleglJan

SleglJan commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Amended after the approval; the exports and their semantics are unchanged. What changed:

  • Dispatch on main tests the blocked mask at bit n, so a set built with these functions blocked the wrong signal. That is fixed separately in fix(libkernel): block guest signals by FreeBSD's bit n - 1 #1652 (one expression plus a test), and this PR now lists it under Depends on. The earlier text said feat(libkernel): deliver sceKernelRaiseException on Linux #1431 would move the mask to bit n − 1; its current head does not touch Signals.cpp, so the description no longer relies on it.
  • static_assert(sizeof(GuestSignalSet) == 16); the index arithmetic lives in one WordIndex helper; the errno helper is RejectSignal; the null check takes a typed pointer.
  • Test additions: INT_MIN and INT_MAX, signals 65 and 96 (word 2), membership of all 128 signals after sigfillset, errno untouched by successful calls, the invalid-signal loop against a full set as well.
  • The pr-overlap table above is the shared extern "C" declaration of __error_nid_postfix, not an export; see the description.

Re-run on this revision: full ctest --repeat until-fail:3 467/467, conventions and test-registration checks pass.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

Progress report (4b005b2 → e6a9b50)

📈 System libraries: 84.78% (+0.02%, +5 implemented functions)

✅ 5 implemented
Library Name
libkernel sigaddset_nid_postfix
libkernel sigdelset_nid_postfix
libkernel sigemptyset_nid_postfix
libkernel sigfillset_nid_postfix
libkernel sigismember_nid_postfix

@popcoder565

Copy link
Copy Markdown
Contributor

First Windows run, since the description says it wasn't tested on Windows.

Setup: Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Merged onto main b7218b3 together with nine other small libc/libkernel PRs: #1975, #1976, #1977, #1859, #1685, #1676, #1675, #1656, #1807.

  • guest_signal_sets passes.
  • Full ctest: 510/510 (one GPU test skipped for a device limit).

🤖 Addressed by Claude Code

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the five exports against shadPS4 (exception.cpp) and SharpProspero (CompatEmitter.cs): range 1..128, bit n - 1, EINVAL on anything else. Full build and ctest green (guest_signal_sets passes, and the test cannot link without SignalSets.cpp); CI green on this head, Windows included. Merging.

@adriadam10
adriadam10 merged commit 4c36741 into boykopovar:main Oct 9, 2026
7 of 9 checks passed
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