Thread

  1. [PATCH v4 3/3] Better express platform requirements in s_lock.h.

    Nathan Bossart <nathan@postgresql.org> — 2026-05-07T20:32:50Z

    ---
     src/include/storage/s_lock.h | 56 ++++++++++++++++++++----------------
     1 file changed, 32 insertions(+), 24 deletions(-)
    
    diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
    index fb872edd2f0..c4369ee4ff6 100644
    --- a/src/include/storage/s_lock.h
    +++ b/src/include/storage/s_lock.h
    @@ -44,23 +44,16 @@
      *		atomic test-and-set only when it appears free.
      *
      *	TAS() and TAS_SPIN() are NOT part of the API, and should never be called
    - *	directly.
    - *
    - *	CAUTION: on some platforms TAS() and/or TAS_SPIN() may sometimes report
    - *	failure to acquire a lock even when the lock is not locked.  For example,
    - *	on Alpha TAS() will "fail" if interrupted.  Therefore a retry loop must
    - *	always be used, even if you are certain the lock is free.
    + *	directly.  If a platform-specific TAS() is defined, the platform must
    + *	_not_ define its own S_LOCK().  Conversely, if a platform-specific
    + *	S_LOCK() is defined, the platform must _not_ define its own TAS(), but
    + *	it does need to define its own TAS_SPIN().  Currently, all supported
    + *	platforms define TAS() and use the default S_LOCK() implementation, so
    + *	that is probably a good place to start if adding a new one.
      *
      *	It is the responsibility of these macros to make sure that the compiler
      *	does not re-order accesses to shared memory to precede the actual lock
    - *	acquisition, or follow the lock release.  Prior to PostgreSQL 9.5, this
    - *	was the caller's responsibility, which meant that callers had to use
    - *	volatile-qualified pointers to refer to both the spinlock itself and the
    - *	shared data being accessed within the spinlocked critical section.  This
    - *	was notationally awkward, easy to forget (and thus error-prone), and
    - *	prevented some useful compiler optimizations.  For these reasons, we
    - *	now require that the macros themselves prevent compiler re-ordering,
    - *	so that the caller doesn't need to take special precautions.
    + *	acquisition, or follow the lock release.
      *
      *	On platforms with weak memory ordering, the TAS(), TAS_SPIN(), and
      *	S_UNLOCK() macros must further include hardware-level memory fence
    @@ -72,7 +65,7 @@
      *
      *	On most supported platforms, TAS() uses a tas() function written
      *	in assembly language to execute a hardware atomic-test-and-set
    - *	instruction.  Equivalent OS-supplied mutex routines could be used too.
    + *	instruction.  Equivalent compiler intrinsics are another popular option.
      *
      *
      * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
    @@ -642,20 +635,25 @@ spin_delay(void)
     #endif	/* !defined(TAS) */
     
     
    -/* Blow up if we didn't have any way to do spinlocks */
    -#ifndef TAS
    -#error PostgreSQL does not have spinlock support on this platform.  Please report this to pgsql-bugs@lists.postgresql.org.
    -#endif
    -
    -
     /*
      * Default Definitions - override these above as needed.
      */
     
    -#if !defined(S_LOCK)
    +/*
    + * Make sure S_LOCK is defined, either explicitly for the platform or via a TAS
    + * macro for the platform.  Exactly one of either S_LOCK or TAS should be
    + * defined for a supported platform at this point in the file.
    + */
    +#if defined(S_LOCK)
    +#if defined(TAS)
    +#error Both TAS and S_LOCK defined on this platform.  Please report this to pgsql-bugs@lists.postgresql.org.
    +#endif
    +#elif defined(TAS)
     #define S_LOCK(lock) \
     	(TAS(lock) ? s_lock((lock), __FILE__, __LINE__, __func__) : 0)
    -#endif	 /* S_LOCK */
    +#else
    +#error Neither TAS nor S_LOCK defined on this platform.  Please report this to pgsql-bugs@lists.postgresql.org.
    +#endif
     
     #if !defined(S_UNLOCK)
     /*
    @@ -687,9 +685,19 @@ extern void s_unlock(volatile slock_t *lock);
     #define SPIN_DELAY()	((void) 0)
     #endif	 /* SPIN_DELAY */
     
    +/*
    + * We can only define TAS_SPIN if TAS was defined.  Otherwise, the platform
    + * defined its own S_LOCK without TAS, and therefore is responsible for
    + * defining its own TAS_SPIN as well.  (Note that we currently do not have any
    + * platforms that don't define TAS.)
    + */
     #if !defined(TAS_SPIN)
    +#if defined(TAS)
     #define TAS_SPIN(lock)	TAS(lock)
    -#endif	 /* TAS_SPIN */
    +#else
    +#error Neither TAS nor TAS_SPIN defined on this platform.  Please report this to pgsql-bugs@lists.postgresql.org.
    +#endif	 /* TAS */
    +#endif	 /* ! TAS_SPIN */
     
     
     /*
    -- 
    2.50.1 (Apple Git-155)
    
    
    --JmXY/Yn6swRVDyih--