/src/postgres/src/backend/storage/ipc/ipci.c
Line | Count | Source |
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 | | RequestAddinShmemSpace(Size size) |
46 | 0 | { |
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 | | CalculateShmemSize(void) |
58 | 0 | { |
59 | 0 | 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 | 0 | size = 100000; |
71 | 0 | size = add_size(size, ShmemGetRequestedSize()); |
72 | | |
73 | | /* include additional requested shmem from preload libraries */ |
74 | 0 | size = add_size(size, total_addin_request); |
75 | | |
76 | | /* might as well round it off to a multiple of a typical page size */ |
77 | 0 | size = add_size(size, 8192 - (size % 8192)); |
78 | |
|
79 | 0 | return size; |
80 | 0 | } |
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 | | CreateSharedMemoryAndSemaphores(void) |
121 | 0 | { |
122 | 0 | PGShmemHeader *shim; |
123 | 0 | PGShmemHeader *seghdr; |
124 | 0 | Size size; |
125 | |
|
126 | 0 | Assert(!IsUnderPostmaster); |
127 | | |
128 | | /* Compute the size of the shared-memory block */ |
129 | 0 | size = CalculateShmemSize(); |
130 | 0 | elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size); |
131 | | |
132 | | /* |
133 | | * Create the shmem segment |
134 | | */ |
135 | 0 | 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 | 0 | Assert(strcmp("unknown", |
142 | 0 | GetConfigOption("huge_pages_status", false, false)) != 0); |
143 | | |
144 | | /* |
145 | | * Set up shared memory allocation mechanism |
146 | | */ |
147 | 0 | InitShmemAllocator(seghdr); |
148 | | |
149 | | /* Initialize all shmem areas */ |
150 | 0 | ShmemInitRequested(); |
151 | | |
152 | | /* Initialize dynamic shared memory facilities. */ |
153 | 0 | dsm_postmaster_startup(shim); |
154 | | |
155 | | /* |
156 | | * Now give loadable modules a chance to set up their shmem allocations |
157 | | */ |
158 | 0 | if (shmem_startup_hook) |
159 | 0 | shmem_startup_hook(); |
160 | 0 | } |
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 | | RegisterBuiltinShmemCallbacks(void) |
169 | 0 | { |
170 | | /* |
171 | | * Call RegisterShmemCallbacks(...) on each subsystem listed in |
172 | | * subsystemlist.h |
173 | | */ |
174 | 0 | #define PG_SHMEM_SUBSYSTEM(subsystem_callbacks) \ |
175 | 0 | RegisterShmemCallbacks(&(subsystem_callbacks)); |
176 | |
|
177 | 0 | #include "storage/subsystemlist.h" |
178 | |
|
179 | 0 | #undef PG_SHMEM_SUBSYSTEM |
180 | 0 | } |
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 | | InitializeShmemGUCs(void) |
190 | 0 | { |
191 | 0 | char buf[64]; |
192 | 0 | Size size_b; |
193 | 0 | Size size_mb; |
194 | 0 | Size hp_size; |
195 | | |
196 | | /* |
197 | | * Calculate the shared memory size and round up to the nearest megabyte. |
198 | | */ |
199 | 0 | size_b = CalculateShmemSize(); |
200 | 0 | size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024); |
201 | 0 | sprintf(buf, "%zu", size_mb); |
202 | 0 | SetConfigOption("shared_memory_size", buf, |
203 | 0 | PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); |
204 | | |
205 | | /* |
206 | | * Calculate the number of huge pages required. |
207 | | */ |
208 | 0 | GetHugePageSize(&hp_size, NULL); |
209 | 0 | if (hp_size != 0) |
210 | 0 | { |
211 | 0 | Size hp_required; |
212 | |
|
213 | 0 | hp_required = size_b / hp_size; |
214 | 0 | if (size_b % hp_size != 0) |
215 | 0 | hp_required = add_size(hp_required, 1); |
216 | 0 | sprintf(buf, "%zu", hp_required); |
217 | 0 | SetConfigOption("shared_memory_size_in_huge_pages", buf, |
218 | 0 | PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); |
219 | 0 | } |
220 | |
|
221 | 0 | sprintf(buf, "%d", ProcGlobalSemas()); |
222 | 0 | SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); |
223 | 0 | } |