On Wed, Jul 23, 2025, at 09:42, Joel Jacobson wrote:
> Great work in this thread. I'll try to help, definitively benchmarking,
> but will also try to load the new design into my brain, to get the
> correct mental model of it, so I can hopefully help with code review as
> well.

First, my apologies for joining this long-running discussion late.

Following up on my email in the "Optimize LISTEN/NOTIFY" thread [1], I
wanted to elaborate on the architectural pattern my patches demonstrate,
as I believe it's highly complementary to the work being done here.

The fundamental distinction is between decoupled vs. combined state
management. The v7 patch set creates a new Interrupt system where the
wakeup mechanism and the 'pending' state for all subsystems are combined
into a single, centralized atomic bitmask.

My work explores an alternative: decoupling the two. The insight is that
many of our legacy subsystems were designed to be stateless because they
lacked the atomics and WaitEventSet abstractions we have today. The
signal was a workaround for this state management limitation.

This suggests a powerful, three-step migration pattern:

Step 1: Decouple state management with a lock-free atomic FSM.

Each subsystem should be empowered to manage its own state. My first
patch for async.c [1] demonstrates this by introducing a lock-free,
atomic finite state machine (FSM). Using a subsystem-specific atomic
integer and CAS operations, async.c now robustly manages its own IDLE,
SIGNALLED, PROCESSING states without any locks. This solves the state
synchronization problem directly and eliminates the vast majority of
redundant wakeups.

Step 2: Trivialize the wake-up with a generic poke.

Once state is managed reliably, the expensive kill(pid, SIGUSR1) syscall
can be trivially replaced with a direct SetLatch, as shown in my second
patch [1]. This is a simple and effective intermediate step that leverages
the existing WaitEventSet infrastructure to make the wakeup much
cheaper.

Step 3: Decouple event dispatch with specific interrupts.

The final goal is to replace the generic poke with SendInterrupt using a
specific reason (e.g., INTERRUPT_ASYNC_NOTIFY). This lets the event loop
wait on a bitmask of interrupt reasons and, on wakeup, dispatch only to
the relevant subsystem handler—fully decoupling event handling from
subsystem details.

This three-step, vertical migration strategy (subsystem by subsystem)
seems to offer a powerful alternative to a horizontal, layer-by-layer
replacement. It allows each subsystem's logic to be self-contained and
avoids constraints on a single global interrupt mask. The core
WaitEventSet is kept simple: its only job is to provide the efficient,
multiplexed wait.

I believe the ideal architecture uses your unified Interrupt system as
the low-level primitive, while encouraging key subsystems to adopt these
decoupled FSMs to determine *when* to call SendInterrupt.

I'm happy to help with this effort in any way I can.

/Joel

[1] 
https://www.postgresql.org/message-id/0b4d402a-9ac2-4aa8-acf8-8231dbe579ea%40app.fastmail.com


Reply via email to