Let's drop support for named POSIX semaphores

Started by Tom Laneabout 23 hours ago10 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t254383
psql -h localhost -U postgres

Built from patchset v1 (message #1), October 26, 2026 at 02:32 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t254383_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t254383_1 && git checkout t254383_1

Patchset v1 (message #1) is on t254383_1

Jump to latest
#1Tom Lane
tgl@sss.pgh.pa.us

After fixing a niggling compiler warning (6e06f6281) I started to
wonder why don't we just drop support for named POSIX semaphores.
We originally put that code in for the benefit of macOS, but SysV
semaphores have been the preferred alternative on that platform since
2002, and I don't know of any other platform where named-POSIX style
was ever preferable. Moreover, our current meson configuration logic
doesn't even offer any way to select it.

We did discuss using named POSIX semaphores on OpenBSD [1]/messages/by-id/27582.1546928073@sss.pgh.pa.us, but soon
found that the performance implications were not great [2]/messages/by-id/3010886.1634950831@sss.pgh.pa.us, so that
discussion never went far and is unlikely to. (Munro speculated in
that thread that maybe we could replace all this stuff with futexes,
but that's yet to bubble to the top of anyone's to-do list.) Those
results on OpenBSD pretty much mirror what you'd expect on any
platform given the constraints of the POSIX API, so it's hard to
believe that things would be different for any future platform
that suddenly gained support for this API.

So I think it's time to just drop it, as per attached. Thoughts?

regards, tom lane

[1]: /messages/by-id/27582.1546928073@sss.pgh.pa.us
[2]: /messages/by-id/3010886.1634950831@sss.pgh.pa.us

Attachments:

t254383_1
v1-0001-Drop-support-for-named-POSIX-semaphores-the-sem_o.patchtext/x-diff; charset=us-ascii; name*0=v1-0001-Drop-support-for-named-POSIX-semaphores-the-sem_o.p; name*1=atchDownload+24-243
#2shihao zhong
zhong950419@gmail.com
In reply to: Tom Lane (#1)
Re: Let's drop support for named POSIX semaphores

Hi Tom,

+1. Looks like the only platform that picked it by default was a very old
mac.

Two nits:

IPCProtection in posix_sema.c is now unused,
clang -Wunused-macros points at it. The fcntl.h and sys/stat.h
includes were only there for sem_open() and stat(), so they can go
too.

Also, runtime.sgml still says "POSIX semaphores are used on Linux and
FreeBSD while other platforms use System V."

Thanks,
Shihao

Attachments:

nocfbot-0002-Remove-leftovers-of-named-POSIX-semaphore-support.patchapplication/octet-stream; name=nocfbot-0002-Remove-leftovers-of-named-POSIX-semaphore-support.patchDownload+2-7
#3Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Tom Lane (#1)
Re: Let's drop support for named POSIX semaphores

On 26/10/2026 04:20, Tom Lane wrote:

So I think it's time to just drop it, as per attached. Thoughts?

+1

- Heikki

#4Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#1)
Re: Let's drop support for named POSIX semaphores

On 26.10.26 03:20, Tom Lane wrote:

After fixing a niggling compiler warning (6e06f6281) I started to
wonder why don't we just drop support for named POSIX semaphores.
We originally put that code in for the benefit of macOS, but SysV
semaphores have been the preferred alternative on that platform since
2002,

There were some recent discussions about removing the requirement of
SysV IPC to allow macOS sandboxing mechanisms to be used. These
discussions mainly focus on SysV shared memory, which is currently a
hard requirement, but I would expect that switching to non-SysV
semaphores would be part of such an undertaking. So I think adding
another hard requirement on SysV IPC would not be preferable.

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#4)
Re: Let's drop support for named POSIX semaphores

Peter Eisentraut <peter@eisentraut.org> writes:

There were some recent discussions about removing the requirement of
SysV IPC to allow macOS sandboxing mechanisms to be used. These
discussions mainly focus on SysV shared memory, which is currently a
hard requirement, but I would expect that switching to non-SysV
semaphores would be part of such an undertaking. So I think adding
another hard requirement on SysV IPC would not be preferable.

Named POSIX semaphores are not a credible replacement for SysV
semaphores, because of their performance issues (which are just
as real on macOS as anywhere else). So I think the direction we'd
have to go in to make that happen is to replace all the semaphore
stuff with futexes or some other low-level primitive, as Munro
speculated about in one of the threads I cited.

regards, tom lane

#6Greg Burd
greg@burd.me
In reply to: Peter Eisentraut (#4)
Re: Let's drop support for named POSIX semaphores

+1 on dropping it.

Peter, as to your concern that this adds another hard SysV dependency
and so cuts against the work to let PostgreSQL run without SysV IPC (for
macOS sandboxing): I don't think removing *named* POSIX semaphores costs
that effort anything, because named POSIX semaphores are not the thing
that effort would reach for.

The non-SysV semaphore path we'd actually want is the *unnamed* kind
(sem_init), which posix_sema.c already prefers and which backs the sem_t
structs out of shared memory. The named kind (sem_open) is only the
fallback, and the header comment there spells out why it's a dead end
for this:

With unnamed semaphores, the sem_t structs live in an array in shared
memory [...] Therefore, the named-semaphore code *does not cope with
EXEC_BACKEND*.

So a SysV-free future built on POSIX semaphores runs through the unnamed
path Tom is keeping, not the named path he's removing. Dropping named
POSIX semaphores narrows the matrix to "SysV or unnamed-POSIX".

(+1 as well to Shihao's two nits, the now-unused IPCProtection macro
and the stale runtime.sgml line about which platforms use which.)

best,

-greg

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Greg Burd (#6)
Re: Let's drop support for named POSIX semaphores

Greg Burd <greg@burd.me> writes:

Peter, as to your concern that this adds another hard SysV dependency
and so cuts against the work to let PostgreSQL run without SysV IPC (for
macOS sandboxing): I don't think removing *named* POSIX semaphores costs
that effort anything, because named POSIX semaphores are not the thing
that effort would reach for.

The non-SysV semaphore path we'd actually want is the *unnamed* kind
(sem_init), which posix_sema.c already prefers and which backs the sem_t
structs out of shared memory.

... and which macOS still doesn't support :-(. But moving from SysV
to named POSIX semaphores isn't realistic performance-wise, so we need
some other path altogether if we hope to address the sandboxing
problem.

(+1 as well to Shihao's two nits, the now-unused IPCProtection macro
and the stale runtime.sgml line about which platforms use which.)

Yeah, I noticed a few comments that need updates as well.

regards, tom lane

#8Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#5)
Re: Let's drop support for named POSIX semaphores

Hi,

On 2026-10-26 11:42:56 -0400, Tom Lane wrote:

So I think the direction we'd have to go in to make that happen is to
replace all the semaphore stuff with futexes or some other low-level
primitive, as Munro speculated about in one of the threads I cited.

Agreed, that's the right direction. We really aren't using semaphores in a way
that benefits from them being semaphores. In fact, we have to fix up the
semaphore counters in a bunch of places that would not need such complication
with a better primitive.

FWIW, I recalled Thomas posting patches for macos futexes before. I didn't
immediately find them, but did quickly find the branch that implements futexes
on macos:

https://github.com/macdice/postgres/commits/pg_futex/
https://github.com/macdice/postgres/commit/bf2ceb73fe8a48ece981a82ef103284e5dfc0a54

Given that, as Thomas notes in [1]/messages/by-id/CA+hUKGKAPR=NXxMTCmEomCUpq+mrPLDVyfVa4bKZqfDjwyzD7Q@mail.gmail.com, macos finally documents the futex APIs,
that seems like the obvious way forward.

I also found an older branch of Thomas' that abstracts futexes across a number
of platforms [2]https://github.com/macdice/postgres/commits/pg_futex/ and then implements semaphores on top of those futexes.

It's *really* annoying that window's WaitOnAddress() equivalent explicitly
requires the waiter and waker to be threads in the same process :(.

E.g. lwlocks would be faster *and* the code would be simpler if futexes could
be used everywhere.

Greetings,

Andres

[1]: /messages/by-id/CA+hUKGKAPR=NXxMTCmEomCUpq+mrPLDVyfVa4bKZqfDjwyzD7Q@mail.gmail.com
[2]: https://github.com/macdice/postgres/commits/pg_futex/

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#8)
Re: Let's drop support for named POSIX semaphores

Andres Freund <andres@anarazel.de> writes:

It's *really* annoying that window's WaitOnAddress() equivalent explicitly
requires the waiter and waker to be threads in the same process :(.
E.g. lwlocks would be faster *and* the code would be simpler if futexes could
be used everywhere.

Well, in our hypothetical multithreaded future, that might be fine.
I'm wondering how much change we should try to make in this area now,
rather than after (or as part of) the multithreading work.

regards, tom lane

#10Greg Burd
greg@burd.me
In reply to: Tom Lane (#9)
Re: Let's drop support for named POSIX semaphores

On Monday, October 26th, 2026 at 1:06 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Andres Freund <andres@anarazel.de> writes:

It's *really* annoying that window's WaitOnAddress() equivalent explicitly
requires the waiter and waker to be threads in the same process :(.
E.g. lwlocks would be faster *and* the code would be simpler if futexes could
be used everywhere.

Well, in our hypothetical multithreaded future, that might be fine.
I'm wondering how much change we should try to make in this area now,
rather than after (or as part of) the multithreading work.

regards, tom lane

I don't think Windows has to block this, and I don't think the API
would need to change when threads arrive.

Kernel futexes that work across processes exist on Linux, FreeBSD,
OpenBSD and NetBSD (both key shared waits on the backing VM object,
not the VA), DragonFly, and macOS 14.4+ via os_sync_wait_on_address()
with the SHARED flags, which is what Thomas's pg_futex branch uses
[0]: https://github.com/macdice/postgres/commit/bf2ceb73fe8a48ece981a82ef103284e5dfc0a54
macOS needing a fallback in any case, so the question is what the
fallback looks like rather than whether we need one.

Thomas's pg_futex.h already wraps the value in a struct to leave room
for one. The fallback I'd suggest is to embed a spinlock and a
proclist_head in that struct, and have waiters sleep on their own
PGPROC semaphore: enqueue, recheck the value, release, sleep; the
waker updates the value, dequeues, and posts. That is the same thing
lwlock.c and condition_variable.c already do by hand, done once.
Embedding the queue rather than using a parking lot hashed by address
matters because DSM segments map at different addresses in different
backends; the native kernels don't care, but a userspace hash would.

With that, LWLocks and CVs could be written once against pg_futex,
getting native futexes where the kernel has them and today's
behavior elsewhere, and the semaphore count fixups Andres mentioned
move into one place. In a multithreaded build Windows simply moves
to the native tier via WaitOnAddress(), and the generic fallback can
sit on pg_threads.h mtx/cnd the way Zig's std.Thread.Futex does [1]https://github.com/ziglang/zig/blob/master/lib/std/Thread/Futex.zig.

I'd keep the API to 32-bit wait(expected, timeout), wake_one() and
wake_all(), since macOS and Windows can't wake an arbitrary count and
Linux and FreeBSD only wait on 32-bit words. Latches are out of scope:
a futex can't multiplex with sockets or postmaster death.

The open question for me is performance. Haris's futex-based
LWLockWaitListLock() patch [2]/messages/by-id/DM6PR18MB29081469262A7BBCE85220B3A8112@DM6PR18MB2908.namprd18.prod.outlook.com was a large win on Neoverse V3 but a
small loss on recent x86, so a futex LWLock needs real numbers, not
assumptions.

If there is any agreement on this approach I'd be happy to picked up
the lwlock-futex branch [3]https://github.com/macdice/postgres/commits/lwlock-futex/ and try the embedded-queue fallback on
top of it.

thoughts?

-greg

[0]: https://github.com/macdice/postgres/commit/bf2ceb73fe8a48ece981a82ef103284e5dfc0a54
[1]: https://github.com/ziglang/zig/blob/master/lib/std/Thread/Futex.zig
[2]: /messages/by-id/DM6PR18MB29081469262A7BBCE85220B3A8112@DM6PR18MB2908.namprd18.prod.outlook.com
[3]: https://github.com/macdice/postgres/commits/lwlock-futex/