Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rPlkK-00E0Vq-IE for pgsql-hackers@arkaria.postgresql.org; Tue, 16 Jan 2024 15:53:01 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rPlkJ-004n3h-LL for pgsql-hackers@arkaria.postgresql.org; Tue, 16 Jan 2024 15:52:59 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rPlkJ-004n3Z-BC for pgsql-hackers@lists.postgresql.org; Tue, 16 Jan 2024 15:52:59 +0000 Received: from mail-il1-x12f.google.com ([2607:f8b0:4864:20::12f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rPlkG-0028dr-EK for pgsql-hackers@postgresql.org; Tue, 16 Jan 2024 15:52:58 +0000 Received: by mail-il1-x12f.google.com with SMTP id e9e14a558f8ab-3606e211e5cso57816505ab.3 for ; Tue, 16 Jan 2024 07:52:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1705420374; x=1706025174; darn=postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=9LSzREjV5Dx7z/VFrCjrHPtF4F0djA+vHRSenekZAFU=; b=MJjuLEMHBjvpiIBDexxj9JPHM7kFZ1o+IIFGGKNcbTmgHyby2Peoi36/qcrLmWgjLE 5jClrEe+XNJCCAJa51MkOe4SGSUXGtLygf/nqJTChDf2OLVS3F1LIjvffRQXMPErQC1w aRCc9ky1Xv2xCiiBG2gCe6wkw9i72UWOX88JCrDgqrthbsdoghOXahJvtdc/5TyTnDUX nNpU9oPB9rGxVOKtSjgPMfEvX9/baqkYd/MDoo6lkOpP/TyBbsNYGfjhZBly+t28sKHZ TQCfY6ItY81l0SlPz+TH3AMVOpwg/CxqaJylS7FiD9OkS7v2tDMW71vwqEEVHR6gjLqT I07Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705420374; x=1706025174; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=9LSzREjV5Dx7z/VFrCjrHPtF4F0djA+vHRSenekZAFU=; b=DyXadsDnENdUqlVMz19KallmgzzSczLXj3wmd0NNqwfsQFZAqk5o978IBGOnaLs4D0 XBqRZCD1h512n7Jl4EGbln6iS3NPn0PUB4qosKT7AwyNGC38hR6PCpEkhPKg3kp/vRHt B6R1npZh01N3XtG3k+P9pZ56sb0NzJu1tBSKnb9xObbgElyWGOhXSGkmLCVjzImfVtPz n1az4rSm2KUz9tg4bL5IyfdTiWvk2suWSp9u/GWicZJ6rgknGo88+rA/KoUJhe0ANxJ5 uaCCzJcpHXVCobRlJqMifct6kFzYt53A3J/+wJWKcHL/OtONQ+P8utiEXBF48DFGXVA1 DZ2g== X-Gm-Message-State: AOJu0YyMQ7NV+vWcsZhYDOUW6gUCyCepyYzXG+m4ZOtmE73CERL5zgfI 1RRWe+mX5BYKzFV5/fEkhV4= X-Google-Smtp-Source: AGHT+IHeomOY62mev5VzCxRaZn5+t+ThVWYG07xDgvM410BxYXuwPjOb2YtutysMUPem1GUqMLe5Tw== X-Received: by 2002:a92:dc8d:0:b0:35f:dc48:9153 with SMTP id c13-20020a92dc8d000000b0035fdc489153mr6375950iln.57.1705420374326; Tue, 16 Jan 2024 07:52:54 -0800 (PST) Received: from nathanxps13 (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id o5-20020a02c6a5000000b0046e29003e62sm1823734jan.112.2024.01.16.07.52.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Jan 2024 07:52:53 -0800 (PST) Date: Tue, 16 Jan 2024 09:52:52 -0600 From: Nathan Bossart To: Bharath Rupireddy Cc: Aleksander Alekseev , pgsql-hackers@postgresql.org Subject: Re: reorganize "Shared Memory and LWLocks" section of docs Message-ID: <20240116155252.GA100542@nathanxps13> References: <20240112041430.GA3557928@nathanxps13> <20240112154650.GA3565306@nathanxps13> <20240112172350.GB3803561@nathanxps13> <20240113212815.GA4065002@nathanxps13> <20240116142019.GA52506@nathanxps13> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="MGYHOYXEY6WxJCY8" Content-Disposition: inline In-Reply-To: <20240116142019.GA52506@nathanxps13> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --MGYHOYXEY6WxJCY8 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Tue, Jan 16, 2024 at 08:20:19AM -0600, Nathan Bossart wrote: > On Tue, Jan 16, 2024 at 10:02:15AM +0530, Bharath Rupireddy wrote: >> The v3 patch looks good to me except for a nitpick: the input >> parameter for RequestAddinShmemSpace is 'Size' not 'int' >> >> >> void RequestAddinShmemSpace(int size) >> > > Hah, I think this mistake is nearly old enough to vote (e0dece1, 5f78aa5). > Good catch. I fixed this in v4. -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --MGYHOYXEY6WxJCY8 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0001-reorganize-shared-memory-and-lwlocks-documentatio.patch" From 402eaf87776fb6a9d212da66947f47c63bd53f2a Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 11 Jan 2024 21:55:25 -0600 Subject: [PATCH v4 1/1] reorganize shared memory and lwlocks documentation --- doc/src/sgml/xfunc.sgml | 184 +++++++++++++++++++++++++--------------- 1 file changed, 115 insertions(+), 69 deletions(-) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 89116ae74c..ede2a5dea6 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3397,90 +3397,136 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray - Shared Memory and LWLocks + Shared Memory - - Add-ins can reserve LWLocks and an allocation of shared memory on server - startup. The add-in's shared library must be preloaded by specifying - it in - shared_preload_libraries. - The shared library should register a shmem_request_hook - in its _PG_init function. This - shmem_request_hook can reserve LWLocks or shared memory. - Shared memory is reserved by calling: + + Requesting Shared Memory at Startup + + + Add-ins can reserve shared memory on server startup. To do so, the + add-in's shared library must be preloaded by specifying it in + shared_preload_libraries. + The shared library should also register a + shmem_request_hook in its + _PG_init function. This + shmem_request_hook can reserve shared memory by + calling: -void RequestAddinShmemSpace(int size) +void RequestAddinShmemSpace(Size size) - from your shmem_request_hook. - - - LWLocks are reserved by calling: + Each backend should obtain a pointer to the reserved shared memory by + calling: + +void *ShmemInitStruct(const char *name, Size size, bool *foundPtr) + + If this function sets foundPtr to + false, the caller should proceed to initialize the + contents of the reserved shared memory. If foundPtr + is set to true, the shared memory was already + initialized by another backend, and the caller need not initialize + further. + + + + To avoid race conditions, each backend should use the LWLock + AddinShmemInitLock when initializing its allocation + of shared memory, as shown here: + +static mystruct *ptr = NULL; +bool found; + +LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); +ptr = ShmemInitStruct("my struct name", size, &found); +if (!found) +{ + ... initialize contents of shared memory ... + ptr->locks = GetNamedLWLockTranche("my tranche name"); +} +LWLockRelease(AddinShmemInitLock); + + shmem_startup_hook provides a convenient place for the + initialization code, but it is not strictly required that all such code + be placed in this hook. Each backend will execute the registered + shmem_startup_hook shortly after it attaches to shared + memory. Note that add-ins should still acquire + AddinShmemInitLock within this hook, as shown in the + example above. + + + + An example of a shmem_request_hook and + shmem_startup_hook can be found in + contrib/pg_stat_statements/pg_stat_statements.c in + the PostgreSQL source tree. + + + + + + LWLocks + + + Requesting LWLocks at Startup + + + Add-ins can reserve LWLocks on server startup. As with shared memory, + the add-in's shared library must be preloaded by specifying it in + shared_preload_libraries, + and the shared library should register a + shmem_request_hook in its + _PG_init function. This + shmem_request_hook can reserve LWLocks by calling: void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks) - from your shmem_request_hook. This will ensure that an array of - num_lwlocks LWLocks is available under the name - tranche_name. Use GetNamedLWLockTranche - to get a pointer to this array. - - - An example of a shmem_request_hook can be found in - contrib/pg_stat_statements/pg_stat_statements.c in the - PostgreSQL source tree. - - - There is another, more flexible method of obtaining LWLocks. First, - allocate a tranche_id from a shared counter by - calling: + This ensures that an array of num_lwlocks LWLocks is + available under the name tranche_name. A pointer to + this array can be obtained by calling: -int LWLockNewTrancheId(void) +LWLockPadded *GetNamedLWLockTranche(const char *tranche_name) - Next, each individual process using the tranche_id - should associate it with a tranche_name by calling: + + + + + Requesting LWLocks After Startup + + + There is another, more flexible method of obtaining LWLocks that can be + done after server startup and outside a + shmem_request_hook. To do so, first allocate a + tranche_id by calling: -void LWLockRegisterTranche(int tranche_id, const char *tranche_name) +int LWLockNewTrancheId(void) - It is also required to call LWLockInitialize once - per LWLock, passing the tranche_id as argument: + Next, initialize each LWLock, passing the new + tranche_id as an argument: void LWLockInitialize(LWLock *lock, int tranche_id) - A complete usage example of LWLockNewTrancheId, - LWLockInitialize and - LWLockRegisterTranche can be found in - contrib/pg_prewarm/autoprewarm.c in the - PostgreSQL source tree. - - - To avoid possible race-conditions, each backend should use the LWLock - AddinShmemInitLock when connecting to and initializing - its allocation of shared memory, as shown here: - -static mystruct *ptr = NULL; + Similar to shared memory, each backend should ensure that only one + process allocates a new tranche_id and initializes + each new LWLock. One way to do this is to only call these functions in + your shared memory initialization code with the + AddinShmemInitLock held exclusively. + -if (!ptr) -{ - bool found; - - LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); - ptr = ShmemInitStruct("my struct name", size, &found); - if (!found) - { - initialize contents of shmem area; - acquire any requested LWLocks using: - ptr->locks = GetNamedLWLockTranche("my tranche name"); - } - LWLockRelease(AddinShmemInitLock); -} + + Finally, each backend using the tranche_id should + associate it with a tranche_name by calling: + +void LWLockRegisterTranche(int tranche_id, const char *tranche_name) - - - It is convenient to use shmem_startup_hook which allows - placing all the code responsible for initializing shared memory in one - place. When using shmem_startup_hook the extension - still needs to acquire AddinShmemInitLock in order to - work properly on all the supported platforms. - + + + + A complete usage example of LWLockNewTrancheId, + LWLockInitialize, and + LWLockRegisterTranche can be found in + contrib/pg_prewarm/autoprewarm.c in the + PostgreSQL source tree. + + -- 2.25.1 --MGYHOYXEY6WxJCY8--