Refactor shared memory allocation for semaphores
authorHeikki Linnakangas <[email protected]>
Thu, 6 Nov 2025 12:45:00 +0000 (14:45 +0200)
committerHeikki Linnakangas <[email protected]>
Thu, 6 Nov 2025 12:45:00 +0000 (14:45 +0200)
Before commit e25626677f, spinlocks were implemented using semaphores
on some platforms (--disable-spinlocks). That made it necessary to
initialize semaphores early, before any spinlocks could be used. Now
that we don't support --disable-spinlocks anymore, we can allocate the
shared memory needed for semaphores the same way as other shared
memory structures. Since the semaphores are used only in the PGPROC
array, move the semaphore shmem size estimation and initialization
calls to ProcGlobalShmemSize() and InitProcGlobal().

Author: Ashutosh Bapat <[email protected]>
Discussion: https://www.postgresql.org/message-id/CAExHW5seSZpPx-znjidVZNzdagGHOk06F+Ds88MpPUbxd1kTaA@mail.gmail.com

src/backend/port/posix_sema.c
src/backend/port/sysv_sema.c
src/backend/storage/ipc/ipci.c
src/backend/storage/ipc/shmem.c
src/backend/storage/lmgr/proc.c
src/include/storage/ipc.h
src/include/storage/shmem.h

index 269c7460817ec74de780cb1f22eddf8ac096ea4d..d7fb0c0c4da0a3c2ac8c789077e6dbd16efd1c50 100644 (file)
@@ -215,12 +215,8 @@ PGReserveSemaphores(int maxSemas)
        elog(PANIC, "out of memory");
 #else
 
-   /*
-    * We must use ShmemAllocUnlocked(), since the spinlock protecting
-    * ShmemAlloc() won't be ready yet.
-    */
    sharedSemas = (PGSemaphore)
-       ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas));
+       ShmemAlloc(PGSemaphoreShmemSize(maxSemas));
 #endif
 
    numSems = 0;
index 6ac83ea1a821ab9cf953d4275c9420014cf23889..9faaeeefc79089febaa99083c08a4bf4fdd75b3c 100644 (file)
@@ -343,12 +343,8 @@ PGReserveSemaphores(int maxSemas)
                 errmsg("could not stat data directory \"%s\": %m",
                        DataDir)));
 
-   /*
-    * We must use ShmemAllocUnlocked(), since the spinlock protecting
-    * ShmemAlloc() won't be ready yet.
-    */
    sharedSemas = (PGSemaphore)
-       ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas));
+       ShmemAlloc(PGSemaphoreShmemSize(maxSemas));
    numSharedSemas = 0;
    maxSharedSemas = maxSemas;
 
index 19f9c77448885de5fcff1a345fee7e7f5c990fb8..b23d0c19360ade87942466412ba410f6216ec110 100644 (file)
@@ -81,23 +81,12 @@ RequestAddinShmemSpace(Size size)
 
 /*
  * CalculateShmemSize
- *     Calculates the amount of shared memory and number of semaphores needed.
- *
- * If num_semaphores is not NULL, it will be set to the number of semaphores
- * required.
+ *     Calculates the amount of shared memory needed.
  */
 Size
-CalculateShmemSize(int *num_semaphores)
+CalculateShmemSize(void)
 {
    Size        size;
-   int         numSemas;
-
-   /* Compute number of semaphores we'll need */
-   numSemas = ProcGlobalSemas();
-
-   /* Return the number of semaphores if requested by the caller */
-   if (num_semaphores)
-       *num_semaphores = numSemas;
 
    /*
     * Size of the Postgres shared-memory block is estimated via moderately-
@@ -109,7 +98,6 @@ CalculateShmemSize(int *num_semaphores)
     * during the actual allocation phase.
     */
    size = 100000;
-   size = add_size(size, PGSemaphoreShmemSize(numSemas));
    size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
                                             sizeof(ShmemIndexEnt)));
    size = add_size(size, dsm_estimate_size());
@@ -204,12 +192,11 @@ CreateSharedMemoryAndSemaphores(void)
    PGShmemHeader *shim;
    PGShmemHeader *seghdr;
    Size        size;
-   int         numSemas;
 
    Assert(!IsUnderPostmaster);
 
    /* Compute the size of the shared-memory block */
-   size = CalculateShmemSize(&numSemas);
+   size = CalculateShmemSize();
    elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
 
    /*
@@ -226,13 +213,6 @@ CreateSharedMemoryAndSemaphores(void)
 
    InitShmemAccess(seghdr);
 
-   /*
-    * Create semaphores.  (This is done here for historical reasons.  We used
-    * to support emulating spinlocks with semaphores, which required
-    * initializing semaphores early.)
-    */
-   PGReserveSemaphores(numSemas);
-
    /*
     * Set up shared memory allocation mechanism
     */
@@ -363,12 +343,11 @@ InitializeShmemGUCs(void)
    Size        size_b;
    Size        size_mb;
    Size        hp_size;
-   int         num_semas;
 
    /*
     * Calculate the shared memory size and round up to the nearest megabyte.
     */
-   size_b = CalculateShmemSize(&num_semas);
+   size_b = CalculateShmemSize();
    size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
    sprintf(buf, "%zu", size_mb);
    SetConfigOption("shared_memory_size", buf,
@@ -388,6 +367,6 @@ InitializeShmemGUCs(void)
                        PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
    }
 
-   sprintf(buf, "%d", num_semas);
+   sprintf(buf, "%d", ProcGlobalSemas());
    SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
 }
index b3d0a10792dc7fb0c756aca07b914eb835ccb90f..0f18beb6ad4af76d1a612bc8cb91e3f37439a7a0 100644 (file)
@@ -76,6 +76,7 @@
 #include "utils/builtins.h"
 
 static void *ShmemAllocRaw(Size size, Size *allocated_size);
+static void *ShmemAllocUnlocked(Size size);
 
 /* shared memory global variables */
 
@@ -234,7 +235,7 @@ ShmemAllocRaw(Size size, Size *allocated_size)
  *
  * We consider maxalign, rather than cachealign, sufficient here.
  */
-void *
+static void *
 ShmemAllocUnlocked(Size size)
 {
    Size        newStart;
index 26b201eadb856155c100108821e7a47b5342d5ad..1504fafe6d889dc43cc9dabb1d3fa981ba567c02 100644 (file)
@@ -145,6 +145,7 @@ ProcGlobalShmemSize(void)
    size = add_size(size, sizeof(PROC_HDR));
    size = add_size(size, sizeof(slock_t));
 
+   size = add_size(size, PGSemaphoreShmemSize(ProcGlobalSemas()));
    size = add_size(size, PGProcShmemSize());
    size = add_size(size, FastPathLockShmemSize());
 
@@ -287,6 +288,9 @@ InitProcGlobal(void)
    /* For asserts checking we did not overflow. */
    fpEndPtr = fpPtr + requestSize;
 
+   /* Reserve space for semaphores. */
+   PGReserveSemaphores(ProcGlobalSemas());
+
    for (i = 0; i < TotalProcs; i++)
    {
        PGPROC     *proc = &procs[i];
index 3baf418b3d1ed999b3a87666c20e04576a124fef..2a8a8f0eabdbcab8e3ad57f2df577fb290d81782 100644 (file)
@@ -77,7 +77,7 @@ extern void check_on_shmem_exit_lists_are_empty(void);
 /* ipci.c */
 extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook;
 
-extern Size CalculateShmemSize(int *num_semaphores);
+extern Size CalculateShmemSize(void);
 extern void CreateSharedMemoryAndSemaphores(void);
 #ifdef EXEC_BACKEND
 extern void AttachSharedMemoryStructs(void);
index cd683a9d2d93d09f26a3189a4c2ffd0d22a170cc..70a5b8b172c6159eb1a4ddb7b6448a332d6a78b7 100644 (file)
@@ -33,7 +33,6 @@ extern void InitShmemAccess(PGShmemHeader *seghdr);
 extern void InitShmemAllocation(void);
 extern void *ShmemAlloc(Size size);
 extern void *ShmemAllocNoError(Size size);
-extern void *ShmemAllocUnlocked(Size size);
 extern bool ShmemAddrIsValid(const void *addr);
 extern void InitShmemIndex(void);
 extern HTAB *ShmemInitHash(const char *name, int64 init_size, int64 max_size,