Re: Interrupts vs signals
Joel Jacobson <joel@compiler.org>
From: "Joel Jacobson" <joel@compiler.org>
To: "Heikki Linnakangas" <hlinnaka@iki.fi>,
"Andres Freund" <andres@anarazel.de>, "Thomas Munro" <thomas.munro@gmail.com>
Cc: "Michael Paquier" <michael@paquier.xyz>,
"Robert Haas" <robertmhaas@gmail.com>, "Fujii Masao" <masao.fujii@gmail.com>,
pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2025-07-24T22:04:31Z
Lists: pgsql-hackers
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
Commits
-
Ignore SIGINT in walwriter and walsummarizer
- a92b809f9da1 19 (unreleased) landed
-
Split WaitEventSet functions to separate source file
- 393e0d231405 18.0 landed
-
Use ModifyWaitEvent to update exit_on_postmaster_death
- 84e5b2f07a5e 18.0 landed
-
Remove unused ShutdownLatchSupport() function
- a98e4dee63ce 18.0 landed
-
Rename two functions that wake up other processes
- 368d8270c838 18.0 landed
-
Use ProcNumbers instead of direct Latch pointers to address other procs
- a9c546a5a378 18.0 landed
-
Clean up WaitLatch calls that passed latch without WL_LATCH_SET
- f9ecb57a506a 18.0 landed
-
Remove unneeded #include
- 094ae071605d 18.0 landed
-
Remove unused latch
- 6c0c49f7d37d 18.0 landed
-
Remove support for background workers without BGWORKER_SHMEM_ACCESS.
- 80a8f95b3bca 15.0 cited