Coverage Report

Created: 2026-11-12 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}