Skip to content

feat(libkernel): implement read and write events for guest sockets - #1091

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
kjhq:feat/libkernel-socket-events
Oct 11, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
kjhq:feat/libkernel-socket-events

Conversation

@kjhq

@kjhq kjhq commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

What

Implements sceKernelAddReadEvent, sceKernelDeleteReadEvent, sceKernelAddWriteEvent and sceKernelDeleteWriteEvent for guest sockets (EVFILT_READ -1, EVFILT_WRITE -2).

  • KernelFilter gets an optional pollFunc. GetTriggeredEvents and WaitForEvents call it for every event that has one and set triggered from the result.
  • GuestSockets::Ready checks the host socket (poll / WSAPoll) with a zero timeout. A read event reports the readable byte count (FIONREAD) in data and a write event the send buffer size (SO_SNDBUF). EV_EOF is set on POLLHUP/POLLERR, and for a read event also once the peer has shut down its sending side (POLLRDHUP on Linux). Events are level-triggered, as in kqueue without EV_CLEAR.
  • When nothing is ready, the wait is event-driven, not polled:
    • The thread blocks in ppoll / WSAPoll on the sockets of the queue's descriptor events plus a per-thread loopback UDP wake socket.
    • Adding, triggering or deleting an event and closing the queue write one byte to the wake socket of each thread blocked on that queue. Each thread registers its wake socket under the queue lock before unlocking, so no wake-up is lost.
    • Timeouts and timer deadlines bound the ppoll/WSAPoll timeout. WSAPoll counts in milliseconds, so on Windows the last sub-millisecond before a deadline is waited on the queue's condition variable.
  • Closing a guest socket removes its read and write events from every queue, as close does on FreeBSD.
  • A descriptor that is not a guest socket and a low watermark above 1 throw; a closed socket is EBADF.
  • TechnicalDebt (Functional) notes that a write event's data is the send buffer size, not the free space in it.

WaitForEvents changes next to the lines #1081 touches (the blocking wait with no timeout); the two do not overlap in behaviour, but whichever merges second needs a small rebase.

New test guest_socket_events (TCP over loopback) checks:

  • no event before a connection
  • the listener becomes readable on connect, with the given user data
  • a connected socket is writable with data > 0
  • the accepted socket reports the sent byte count, then nothing once read, then readable with data == 0 and EV_EOF after the peer closes
  • a wait with no timeout returns when data arrives from another thread 50 ms later
  • a thread blocked with no timeout is woken when another thread adds a write event
  • closing a socket removes its event (a later delete is ENOENT)
  • deleting twice is ENOENT, a closed socket is EBADF, and a non-socket descriptor and a large low watermark throw

With the wake on AddEvent removed, the test hangs.

Title

PPSA17221 (Minecraft) needs #716 to load the modules in its app root, so every run below is current main + #716 + the PRs of this set (#1088, #1090–#1096), plus local changes outside it: dialog, NpAuth and TextToSpeech2 stubs that open PRs cover (#560, #925, #301) and a GPU end-of-pipe change that is not submitted. With all of them the title loads a world. The line below is from a run with only this PR left out, Windows 11, WinLibs GCC, normal user session.

Without it startup stops at load:

FAIL: unresolved ELF import JxJ4tfgKlXA from libkernel.prx

JxJ4tfgKlXA is sceKernelDeleteReadEvent; the eboot also imports sceKernelAddReadEvent (VHCS3rCd0PM), sceKernelAddWriteEvent (R-tyYMpYaxY) and sceKernelDeleteWriteEvent (cBGTk8S92XM).

Tested

Debian 13 (WSL2), GCC 14.2.0, Release: full ctest, 0 of 391 failed (151 AGC driver tests report Skipped on this machine), including guest_socket_events and guest_equeue_events.

Windows 11, WinLibs GCC:

  • guest_socket_events and guest_tcp pass.
  • guest_udp passes once the SO_LINGER checks are removed. Those checks come from the closed feat(libkernel): support SO_LINGER and IPV6_V6ONLY in setsockopt #1090, which is still in the local integration tree, and Windows rejects SO_LINGER on UDP sockets.
  • PPSA17221 with this PR and the rest of the set loads a world.

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

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Conflicts with main in Equeue.cpp and Equeue.hpp (the micros == 0 branch changed in #807); please rebase.

@kjhq
kjhq force-pushed the feat/libkernel-socket-events branch from 9dc3924 to 7f5f456 Compare October 8, 2026 08:25
@kjhq

kjhq commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on main (e705d43). In WaitForEvents, an infinite wait now takes the timer deadline from #807 and, while socket events are registered, waits in WaitForDescriptors until that deadline. Linux: guest_socket_events, guest_equeue_events and guest_udp pass. The full ctest has one failure, tls_function_coverage (alu-exec-xor-3 exits with SIGSEGV), which fails the same way on main.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Progress report (e28fbc2 → 0abe0b8)

📉 System libraries: 85.62% (-0.04%, +2 implemented, +2 declared functions)

✅ 2 implemented
Library Name
libkernel sceKernelDeleteReadEvent
libkernel sceKernelDeleteWriteEvent
🆕 2 declared as stubs
Library Name
libkernel sceKernelAddReadEvent
libkernel sceKernelAddWriteEvent

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Conflicts with main again, in Socket/src/Udp.cpp and docs/dev/TechnicalDebt.md; please rebase.

@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased onto current main (conflicts with the socketpair and poll work in Udp.cpp, libkernel/CMakeLists.txt and TechnicalDebt.md; adjacency only, no logic changes). The two commits are kept, no merge commits.

Checked on Linux after the rebase: full build and ctest green (523/523), guest_socket_events does not link without the change. Windows paths (WSAPoll, waker socket) are covered only by the author's Windows 11 run; merging on green CI.

@adriadam10
adriadam10 force-pushed the feat/libkernel-socket-events branch from 7f5f456 to 96eb4ad Compare October 9, 2026 21:29
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 9, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Conflicts with main again in Socket/include/SocketRuntime.hpp (#1738); please rebase.

kjhq added 2 commits October 11, 2026 01:54
sceKernelAddReadEvent/DeleteReadEvent and sceKernelAddWriteEvent/
DeleteWriteEvent register EVFILT_READ and EVFILT_WRITE events on guest
sockets. The equeue polls the host socket for readiness on each wait
and reports the readable byte count or the send buffer size in data,
with EV_EOF on hang-up or error.
A wait on an equeue that holds socket events now blocks in poll/WSAPoll on
those sockets plus a per-thread loopback wake socket, instead of rechecking
every millisecond. Adding, triggering or deleting an event and closing the
equeue wake the blocked waiters. Closing a socket removes its read and write
events, as on FreeBSD. A read event also reports EV_EOF once the peer has
shut down its sending side.
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased onto current main (conflicts in libkernel/CMakeLists.txt, SocketRuntime.hpp and TechnicalDebt.md: kept main's guest_dup, Duplicate/Family/Read/Write and shm_open line next to this PR's guest_socket_events, Ready and TechnicalDebt line). No logic changes, both commits kept, no merge commits. Rebuilt on Linux: scoped ctest 92/92 passes, including guest_socket_events, guest_socket_pair, guest_socket_read_write, guest_equeue_events, guest_udp and guest_tcp. Windows paths (WSAPoll, waker socket) are covered only by the author's Windows 11 run; merging on green CI.

@adriadam10
adriadam10 force-pushed the feat/libkernel-socket-events branch from 96eb4ad to 0abe0b8 Compare October 10, 2026 23:56
@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
#3150 core/libs/prx/libkernel/Socket/include/SocketRuntime.hpp L12

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 11, 2026
@adriadam10
adriadam10 merged commit e8d6de4 into boykopovar:main Oct 11, 2026
14 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.

3 participants