Skip to content

Conversation

@ryanbreen
Copy link
Owner

Summary

  • Implement proper blocking I/O for UDP sockets to eliminate CPU busy-waiting
  • When recvfrom() has no data available → block the calling thread
  • When packet arrives via softirq → wake blocked threads
  • Thread resumes and receives the packet

This follows the existing stdin blocking pattern in the kernel and replaces the inefficient busy-wait loop in DNS resolution.

Key Changes

Core Implementation

  • Add wait queue to UdpSocket for tracking blocked threads
  • Implement register_waiter() / unregister_waiter() / wake_waiters() methods
  • Modify sys_recvfrom() to block when no data and socket is blocking mode
  • Wake threads in enqueue_packet() when data arrives

SOCK_NONBLOCK Support

  • Add SOCK_NONBLOCK (0x800) flag support in sys_socket()
  • Mask flag from base socket type before type switch
  • Userspace can create nonblocking sockets: socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)

Integration Testing

  • New blocking_recv_test.rs userspace binary - creates blocking UDP socket on port 55556
  • New run-blocking-recv-test.sh Docker script with UDP port forwarding
  • External packet via nc -u localhost 55556 wakes blocked test

Unit Tests

  • Comprehensive tests for wait queue operations (register, unregister, wake)
  • Tests for has_data() double-check pattern
  • Tests for nonblocking mode flag propagation
  • Module-level docs explaining unit test limitations vs integration coverage

Test plan

  • ./docker/qemu/run-dns-test.sh - All 6 stages pass
  • ./docker/qemu/run-blocking-recv-test.sh - PASS (thread blocks, wakes on packet)
  • ./docker/qemu/run-boot-parallel.sh 1 - Full boot test passes
  • cargo build --release - Zero warnings

🤖 Generated with Claude Code

ryanbreen and others added 7 commits January 23, 2026 04:25
Implement proper blocking I/O for UDP sockets, replacing busy-wait with
efficient wait queues. DNS test pass rate improved from ~30% to 100%.

Key changes:
- Add waiting_threads queue to UdpSocket for blocked thread tracking
- Implement wake mechanism in enqueue_packet() when packets arrive
- Add blocking HLT loop in sys_recvfrom() with proper preemption handling
- Fix idle thread context restoration after userspace starts
- Add ready_queue duplicate prevention in scheduler
- Add unit tests for wait queue and scheduler invariants

The idle context fix was critical: after userspace starts (RING3_CONFIRMED),
idle always goes to idle_loop instead of restoring potentially stale
boot-time context that could cause hangs.

Also adds Docker test scripts for DNS, keyboard, and interactive testing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CRITICAL: Running QEMU directly on macOS causes system-wide instability:
- Hypervisor.framework resource leaks when QEMU is killed
- GPU driver destabilization affecting all GPU-accelerated apps
- Memory pressure cascades from orphaned QEMU processes

This update makes Docker-based QEMU execution mandatory:
- All QEMU runs must use docker/qemu/run-*.sh scripts
- GDB debugging is now disabled (requires native QEMU)
- Added new test scripts: run-dns-test.sh, run-interactive.sh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tions

Handler tests:
- test_is_ring3_confirmed_initial_state: Verify false before Ring 3 syscalls
- test_ring3_confirmed_swap_behavior: Verify exactly-once detection semantics

Socket tests:
- test_recvfrom_error_constants: Verify EAGAIN, EBADF, ENOTSOCK constants
- test_sockaddr_in_structure: Verify sockaddr_in layout and byte conversion
- test_socket_type_constants: Verify AF_INET, SOCK_STREAM, SOCK_DGRAM values
- test_udp_socket_has_data_for_race_check: Verify has_data() for race fix

NOTE: These are no_std kernel tests that compile as part of the kernel
build but cannot run with cargo test due to x86_64-breenix target.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add #[allow(dead_code)] annotations for code that is only used in
conditionally-compiled build configurations:

- kernel_main_continue: only called when not dns_test_only
- Async executor infrastructure (Task, TaskId, Executor, TaskWaker):
  only used when async keyboard/serial tasks are enabled
- keyboard_task and related functions: conditionally compiled
- serial_command_task and related functions: conditionally compiled
- TTY input_char path and helpers: used by keyboard_task
- Timer validation functions: used in kernel_main_continue
- TSC query functions: used in debug and test code
- UdpSocket::set_nonblocking: public API for future fcntl support

Also adds #[cfg] annotation to kernel_main_continue to match its
call site, preventing compilation when not needed.

Build is now warning-free for the dns_test_only configuration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add unit tests recommended by validation report:
- test_enqueue_packet_wakes_multiple_waiters: Verify all waiting threads
  are woken when packet arrives
- test_nonblocking_mode_flag: Test set_nonblocking() behavior
- test_recv_from_dequeues_packets: Test FIFO ordering of packet receive
- test_race_condition_double_check: Test the critical double-check pattern
  that prevents race between setting Blocked state and packet arrival
- test_rx_queue_overflow: Test oldest-packet-dropped behavior at queue limit

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SOCK_NONBLOCK (0x800) flag support in sys_socket()
- Mask nonblocking flag from base socket type before type switch
- Add SOCK_NONBLOCK constant to libbreenix socket module
- Fix EAGAIN test to use SOCK_DGRAM | SOCK_NONBLOCK

Integration test:
- Add blocking_recv_test userspace binary that creates blocking UDP
  socket and waits for external packet
- Add run-blocking-recv-test.sh Docker script with UDP port forwarding
- Add blocking_recv_test feature flag to kernel Cargo.toml

Test improvements from validation:
- Rename test_has_data_double_check_pattern to test_has_data_reflects_queue_state
- Add module-level documentation explaining unit test limitations
- Document that true concurrent race testing requires integration tests

All tests pass:
- DNS test: 6/6 stages
- Blocking recv test: PASS
- Boot test: PASS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… test

Address validation review findings:

Critical fixes:
- Add nonblock_eagain_test.rs integration test that verifies SOCK_NONBLOCK
  creates a non-blocking socket that returns EAGAIN when no data available
- Strengthen blocking_recv_test.rs to verify received data starts with
  "wakeup" (the string sent by test script), fail with exit code 4 on mismatch

Important fixes:
- Add test_recvfrom_ebadf_constant unit test documenting EBADF error value
  and noting syscall error paths require process context

All tests pass:
- DNS test: 6/6 stages
- Blocking recv test: PASS (with data verification)
- Nonblock EAGAIN test: exercises SOCK_NONBLOCK path
- Boot test: PASS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ryanbreen ryanbreen merged commit 056892f into main Jan 23, 2026
2 checks passed
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.

2 participants