Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * ipci.c
4 : * POSTGRES inter-process communication initialization code.
5 : *
6 : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/storage/ipc/ipci.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "miscadmin.h"
18 : #include "pgstat.h"
19 : #include "storage/dsm.h"
20 : #include "storage/ipc.h"
21 : #include "storage/lock.h"
22 : #include "storage/pg_shmem.h"
23 : #include "storage/proc.h"
24 : #include "storage/shmem_internal.h"
25 : #include "storage/subsystems.h"
26 : #include "utils/guc.h"
27 :
28 : /* GUCs */
29 : int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
30 :
31 : shmem_startup_hook_type shmem_startup_hook = NULL;
32 :
33 : static Size total_addin_request = 0;
34 :
35 : /*
36 : * RequestAddinShmemSpace
37 : * Request that extra shmem space be allocated for use by
38 : * a loadable module.
39 : *
40 : * This may only be called via the shmem_request_hook of a library that is
41 : * loaded into the postmaster via shared_preload_libraries. Calls from
42 : * elsewhere will fail.
43 : */
44 : void
45 0 : RequestAddinShmemSpace(Size size)
46 : {
47 0 : if (!process_shmem_requests_in_progress)
48 0 : elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
49 0 : total_addin_request = add_size(total_addin_request, size);
50 0 : }
51 :
52 : /*
53 : * CalculateShmemSize
54 : * Calculates the amount of shared memory needed.
55 : */
56 : Size
57 2291 : CalculateShmemSize(void)
58 : {
59 : Size size;
60 :
61 : /*
62 : * Size of the Postgres shared-memory block is estimated via moderately-
63 : * accurate estimates for the big hogs, plus 100K for the stuff that's too
64 : * small to bother with estimating.
65 : *
66 : * We take some care to ensure that the total size request doesn't
67 : * overflow size_t. If this gets through, we don't need to be so careful
68 : * during the actual allocation phase.
69 : */
70 2291 : size = 100000;
71 2291 : size = add_size(size, ShmemGetRequestedSize());
72 :
73 : /* include additional requested shmem from preload libraries */
74 2291 : size = add_size(size, total_addin_request);
75 :
76 : /* might as well round it off to a multiple of a typical page size */
77 2291 : size = add_size(size, 8192 - (size % 8192));
78 :
79 2291 : return size;
80 : }
81 :
82 : #ifdef EXEC_BACKEND
83 : /*
84 : * AttachSharedMemoryStructs
85 : * Initialize a postmaster child process's access to shared memory
86 : * structures.
87 : *
88 : * In !EXEC_BACKEND mode, we inherit everything through the fork, and this
89 : * isn't needed.
90 : */
91 : void
92 : AttachSharedMemoryStructs(void)
93 : {
94 : /* InitProcess must've been called already */
95 : Assert(MyProc != NULL);
96 : Assert(IsUnderPostmaster);
97 :
98 : /*
99 : * In EXEC_BACKEND mode, backends don't inherit the number of fast-path
100 : * groups we calculated before setting the shmem up, so recalculate it.
101 : */
102 : InitializeFastPathLocks();
103 :
104 : /* Establish pointers to all shared memory areas in this backend */
105 : ShmemAttachRequested();
106 :
107 : /*
108 : * Now give loadable modules a chance to set up their shmem allocations
109 : */
110 : if (shmem_startup_hook)
111 : shmem_startup_hook();
112 : }
113 : #endif
114 :
115 : /*
116 : * CreateSharedMemoryAndSemaphores
117 : * Creates and initializes shared memory and semaphores.
118 : */
119 : void
120 1233 : CreateSharedMemoryAndSemaphores(void)
121 : {
122 : PGShmemHeader *shim;
123 : PGShmemHeader *seghdr;
124 : Size size;
125 :
126 : Assert(!IsUnderPostmaster);
127 :
128 : /* Compute the size of the shared-memory block */
129 1233 : size = CalculateShmemSize();
130 1233 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
131 :
132 : /*
133 : * Create the shmem segment
134 : */
135 1233 : seghdr = PGSharedMemoryCreate(size, &shim);
136 :
137 : /*
138 : * Make sure that huge pages are never reported as "unknown" while the
139 : * server is running.
140 : */
141 : Assert(strcmp("unknown",
142 : GetConfigOption("huge_pages_status", false, false)) != 0);
143 :
144 : /*
145 : * Set up shared memory allocation mechanism
146 : */
147 1231 : InitShmemAllocator(seghdr);
148 :
149 : /* Initialize all shmem areas */
150 1231 : ShmemInitRequested();
151 :
152 : /* Initialize dynamic shared memory facilities. */
153 1231 : dsm_postmaster_startup(shim);
154 :
155 : /*
156 : * Now give loadable modules a chance to set up their shmem allocations
157 : */
158 1231 : if (shmem_startup_hook)
159 0 : shmem_startup_hook();
160 1231 : }
161 :
162 : /*
163 : * Early initialization of various subsystems, giving them a chance to
164 : * register their shared memory needs before the shared memory segment is
165 : * allocated.
166 : */
167 : void
168 1242 : RegisterBuiltinShmemCallbacks(void)
169 : {
170 : /*
171 : * Call RegisterShmemCallbacks(...) on each subsystem listed in
172 : * subsystemslist.h
173 : */
174 : #define PG_SHMEM_SUBSYSTEM(subsystem_callbacks) \
175 : RegisterShmemCallbacks(&(subsystem_callbacks));
176 :
177 : #include "storage/subsystemlist.h"
178 :
179 : #undef PG_SHMEM_SUBSYSTEM
180 1242 : }
181 :
182 : /*
183 : * InitializeShmemGUCs
184 : *
185 : * This function initializes runtime-computed GUCs related to the amount of
186 : * shared memory required for the current configuration.
187 : */
188 : void
189 1058 : InitializeShmemGUCs(void)
190 : {
191 : char buf[64];
192 : Size size_b;
193 : Size size_mb;
194 : Size hp_size;
195 :
196 : /*
197 : * Calculate the shared memory size and round up to the nearest megabyte.
198 : */
199 1058 : size_b = CalculateShmemSize();
200 1058 : size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
201 1058 : sprintf(buf, "%zu", size_mb);
202 1058 : SetConfigOption("shared_memory_size", buf,
203 : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
204 :
205 : /*
206 : * Calculate the number of huge pages required.
207 : */
208 1058 : GetHugePageSize(&hp_size, NULL);
209 1058 : if (hp_size != 0)
210 : {
211 : Size hp_required;
212 :
213 1058 : hp_required = size_b / hp_size;
214 1058 : if (size_b % hp_size != 0)
215 1056 : hp_required = add_size(hp_required, 1);
216 1058 : sprintf(buf, "%zu", hp_required);
217 1058 : SetConfigOption("shared_memory_size_in_huge_pages", buf,
218 : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
219 : }
220 :
221 1058 : sprintf(buf, "%d", ProcGlobalSemas());
222 1058 : SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
223 1058 : }
|