Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * latch.c
4 : : * Routines for inter-process latches
5 : : *
6 : : * The latch interface is a reliable replacement for the common pattern of
7 : : * using pg_usleep() or select() to wait until a signal arrives, where the
8 : : * signal handler sets a flag variable. See latch.h for more information
9 : : * on how to use them.
10 : : *
11 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
12 : : * Portions Copyright (c) 1994, Regents of the University of California
13 : : *
14 : : * IDENTIFICATION
15 : : * src/backend/storage/ipc/latch.c
16 : : *
17 : : *-------------------------------------------------------------------------
18 : : */
19 : : #include "postgres.h"
20 : :
21 : : #include "miscadmin.h"
22 : : #include "port/atomics.h"
23 : : #include "storage/latch.h"
24 : : #include "storage/waiteventset.h"
25 : : #include "utils/resowner.h"
26 : :
27 : : /* A common WaitEventSet used to implement WaitLatch() */
28 : : static WaitEventSet *LatchWaitSet;
29 : :
30 : : /* The positions of the latch and PM death events in LatchWaitSet */
31 : : #define LatchWaitSetLatchPos 0
32 : : #define LatchWaitSetPostmasterDeathPos 1
33 : :
34 : : void
1864 tmunro@postgresql.or 35 :CBC 19220 : InitializeLatchWaitSet(void)
36 : : {
37 : : int latch_pos PG_USED_FOR_ASSERTS_ONLY;
38 : :
39 [ - + ]: 19220 : Assert(LatchWaitSet == NULL);
40 : :
41 : : /* Set up the WaitEventSet used by WaitLatch(). */
653 heikki.linnakangas@i 42 : 19220 : LatchWaitSet = CreateWaitEventSet(NULL, 2);
1864 tmunro@postgresql.or 43 : 19220 : latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
44 : : MyLatch, NULL);
45 [ - + ]: 19220 : Assert(latch_pos == LatchWaitSetLatchPos);
46 : :
47 : : /*
48 : : * WaitLatch will modify this to WL_EXIT_ON_PM_DEATH or
49 : : * WL_POSTMASTER_DEATH on each call.
50 : : */
184 heikki.linnakangas@i 51 [ + + ]: 19220 : if (IsUnderPostmaster)
52 : : {
53 : 18974 : latch_pos = AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
54 : : PGINVALID_SOCKET, NULL, NULL);
55 [ - + ]: 18974 : Assert(latch_pos == LatchWaitSetPostmasterDeathPos);
56 : : }
1864 tmunro@postgresql.or 57 : 19220 : }
58 : :
59 : : /*
60 : : * Initialize a process-local latch.
61 : : */
62 : : void
2385 peter@eisentraut.org 63 : 20041 : InitLatch(Latch *latch)
64 : : {
5474 heikki.linnakangas@i 65 : 20041 : latch->is_set = false;
1650 tmunro@postgresql.or 66 : 20041 : latch->maybe_sleeping = false;
5474 heikki.linnakangas@i 67 : 20041 : latch->owner_pid = MyProcPid;
68 : 20041 : latch->is_shared = false;
69 : :
70 : : #ifdef WIN32
71 : : latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
72 : : if (latch->event == NULL)
73 : : elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
74 : : #endif /* WIN32 */
75 : 20041 : }
76 : :
77 : : /*
78 : : * Initialize a shared latch that can be set from other processes. The latch
79 : : * is initially owned by no-one; use OwnLatch to associate it with the
80 : : * current process.
81 : : *
82 : : * InitSharedLatch needs to be called in postmaster before forking child
83 : : * processes, usually right after allocating the shared memory block
84 : : * containing the latch with ShmemInitStruct. (The Unix implementation
85 : : * doesn't actually require that, but the Windows one does.) Because of
86 : : * this restriction, we have no concurrency issues to worry about here.
87 : : *
88 : : * Note that other handles created in this module are never marked as
89 : : * inheritable. Thus we do not need to worry about cleaning up child
90 : : * process references to postmaster-private latches or WaitEventSets.
91 : : */
92 : : void
2385 peter@eisentraut.org 93 : 134389 : InitSharedLatch(Latch *latch)
94 : : {
95 : : #ifdef WIN32
96 : : SECURITY_ATTRIBUTES sa;
97 : :
98 : : /*
99 : : * Set up security attributes to specify that the events are inherited.
100 : : */
101 : : ZeroMemory(&sa, sizeof(sa));
102 : : sa.nLength = sizeof(sa);
103 : : sa.bInheritHandle = TRUE;
104 : :
105 : : latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
106 : : if (latch->event == NULL)
107 : : elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
108 : : #endif
109 : :
5474 heikki.linnakangas@i 110 : 134389 : latch->is_set = false;
1650 tmunro@postgresql.or 111 : 134389 : latch->maybe_sleeping = false;
5474 heikki.linnakangas@i 112 : 134389 : latch->owner_pid = 0;
113 : 134389 : latch->is_shared = true;
114 : 134389 : }
115 : :
116 : : /*
117 : : * Associate a shared latch with the current process, allowing it to
118 : : * wait on the latch.
119 : : *
120 : : * Although there is a sanity check for latch-already-owned, we don't do
121 : : * any sort of locking here, meaning that we could fail to detect the error
122 : : * if two processes try to own the same latch at about the same time. If
123 : : * there is any risk of that, caller must provide an interlock to prevent it.
124 : : */
125 : : void
2385 peter@eisentraut.org 126 : 18867 : OwnLatch(Latch *latch)
127 : : {
128 : : int owner_pid;
129 : :
130 : : /* Sanity checks */
3456 andres@anarazel.de 131 [ - + ]: 18867 : Assert(latch->is_shared);
132 : :
1194 tmunro@postgresql.or 133 : 18867 : owner_pid = latch->owner_pid;
134 [ - + ]: 18867 : if (owner_pid != 0)
1194 tmunro@postgresql.or 135 [ # # ]:UBC 0 : elog(PANIC, "latch already owned by PID %d", owner_pid);
136 : :
5474 heikki.linnakangas@i 137 :CBC 18867 : latch->owner_pid = MyProcPid;
138 : 18867 : }
139 : :
140 : : /*
141 : : * Disown a shared latch currently owned by the current process.
142 : : */
143 : : void
2385 peter@eisentraut.org 144 : 18812 : DisownLatch(Latch *latch)
145 : : {
5474 heikki.linnakangas@i 146 [ - + ]: 18812 : Assert(latch->is_shared);
147 [ - + ]: 18812 : Assert(latch->owner_pid == MyProcPid);
148 : :
149 : 18812 : latch->owner_pid = 0;
150 : 18812 : }
151 : :
152 : : /*
153 : : * Wait for a given latch to be set, or for postmaster death, or until timeout
154 : : * is exceeded. 'wakeEvents' is a bitmask that specifies which of those events
155 : : * to wait for. If the latch is already set (and WL_LATCH_SET is given), the
156 : : * function returns immediately.
157 : : *
158 : : * The "timeout" is given in milliseconds. It must be >= 0 if WL_TIMEOUT flag
159 : : * is given. Although it is declared as "long", we don't actually support
160 : : * timeouts longer than INT_MAX milliseconds. Note that some extra overhead
161 : : * is incurred when WL_TIMEOUT is given, so avoid using a timeout if possible.
162 : : *
163 : : * The latch must be owned by the current process, ie. it must be a
164 : : * process-local latch initialized with InitLatch, or a shared latch
165 : : * associated with the current process by calling OwnLatch.
166 : : *
167 : : * Returns bit mask indicating which condition(s) caused the wake-up. Note
168 : : * that if multiple wake-up conditions are true, there is no guarantee that
169 : : * we return all of them in one call, but we will return at least one.
170 : : */
171 : : int
2385 peter@eisentraut.org 172 : 1005828 : WaitLatch(Latch *latch, int wakeEvents, long timeout,
173 : : uint32 wait_event_info)
174 : : {
175 : : WaitEvent event;
176 : :
177 : : /* Postmaster-managed callers must handle postmaster death somehow. */
1864 tmunro@postgresql.or 178 [ + - + + : 1005828 : Assert(!IsUnderPostmaster ||
- + ]
179 : : (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
180 : : (wakeEvents & WL_POSTMASTER_DEATH));
181 : :
182 : : /*
183 : : * Some callers may have a latch other than MyLatch, or no latch at all,
184 : : * or want to handle postmaster death differently. It's cheap to assign
185 : : * those, so just do it every time.
186 : : */
187 [ + + ]: 1005828 : if (!(wakeEvents & WL_LATCH_SET))
188 : 10 : latch = NULL;
189 : 1005828 : ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
190 : :
43 michael@paquier.xyz 191 [ + - ]: 1005828 : if (IsUnderPostmaster)
192 : 1005828 : ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
193 : 1005828 : (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
194 : : NULL);
195 : :
1864 tmunro@postgresql.or 196 [ + + ]: 1005828 : if (WaitEventSetWait(LatchWaitSet,
197 [ + + ]: 1005828 : (wakeEvents & WL_TIMEOUT) ? timeout : -1,
198 : : &event, 1,
199 : : wait_event_info) == 0)
200 : 23902 : return WL_TIMEOUT;
201 : : else
202 : 981902 : return event.events;
203 : : }
204 : :
205 : : /*
206 : : * Like WaitLatch, but with an extra socket argument for WL_SOCKET_*
207 : : * conditions.
208 : : *
209 : : * When waiting on a socket, EOF and error conditions always cause the socket
210 : : * to be reported as readable/writable/connected, so that the caller can deal
211 : : * with the condition.
212 : : *
213 : : * wakeEvents must include either WL_EXIT_ON_PM_DEATH for automatic exit
214 : : * if the postmaster dies or WL_POSTMASTER_DEATH for a flag set in the
215 : : * return value if the postmaster dies. The latter is useful for rare cases
216 : : * where some behavior other than immediate exit is needed.
217 : : *
218 : : * NB: These days this is just a wrapper around the WaitEventSet API. When
219 : : * using a latch very frequently, consider creating a longer living
220 : : * WaitEventSet instead; that's more efficient.
221 : : */
222 : : int
2385 peter@eisentraut.org 223 : 116821 : WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
224 : : long timeout, uint32 wait_event_info)
225 : : {
3456 andres@anarazel.de 226 : 116821 : int ret = 0;
227 : : int rc;
228 : : WaitEvent event;
653 heikki.linnakangas@i 229 : 116821 : WaitEventSet *set = CreateWaitEventSet(CurrentResourceOwner, 3);
230 : :
5174 231 [ + + ]: 116821 : if (wakeEvents & WL_TIMEOUT)
3456 andres@anarazel.de 232 [ - + ]: 101797 : Assert(timeout >= 0);
233 : : else
234 : 15024 : timeout = -1;
235 : :
236 [ + + ]: 116821 : if (wakeEvents & WL_LATCH_SET)
237 : 116428 : AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
238 : : latch, NULL);
239 : :
240 : : /* Postmaster-managed callers must handle postmaster death somehow. */
2479 tmunro@postgresql.or 241 [ + - - + : 116821 : Assert(!IsUnderPostmaster ||
- - ]
242 : : (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
243 : : (wakeEvents & WL_POSTMASTER_DEATH));
244 : :
245 [ - + - - ]: 116821 : if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
3456 andres@anarazel.de 246 :UBC 0 : AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
247 : : NULL, NULL);
248 : :
2479 tmunro@postgresql.or 249 [ + - + - ]:CBC 116821 : if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
250 : 116821 : AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
251 : : NULL, NULL);
252 : :
2944 tgl@sss.pgh.pa.us 253 [ + - ]: 116821 : if (wakeEvents & WL_SOCKET_MASK)
254 : : {
255 : : int ev;
256 : :
257 : 116821 : ev = wakeEvents & WL_SOCKET_MASK;
3456 andres@anarazel.de 258 : 116821 : AddWaitEventToSet(set, ev, sock, NULL, NULL);
259 : : }
260 : :
3259 rhaas@postgresql.org 261 : 116821 : rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
262 : :
3456 andres@anarazel.de 263 [ + + ]: 116821 : if (rc == 0)
264 : 218 : ret |= WL_TIMEOUT;
265 : : else
266 : : {
267 : 116603 : ret |= event.events & (WL_LATCH_SET |
268 : : WL_POSTMASTER_DEATH |
269 : : WL_SOCKET_MASK);
270 : : }
271 : :
272 : 116821 : FreeWaitEventSet(set);
273 : :
274 : 116821 : return ret;
275 : : }
276 : :
277 : : /*
278 : : * Sets a latch and wakes up anyone waiting on it.
279 : : *
280 : : * This is cheap if the latch is already set, otherwise not so much.
281 : : *
282 : : * NB: when calling this in a signal handler, be sure to save and restore
283 : : * errno around it. (That's standard practice in most signal handlers, of
284 : : * course, but we used to omit it in handlers that only set a flag.)
285 : : *
286 : : * NB: this function is called from critical sections and signal handlers so
287 : : * throwing an error is not a good idea.
288 : : */
289 : : void
2385 peter@eisentraut.org 290 : 1340949 : SetLatch(Latch *latch)
291 : : {
292 : : #ifndef WIN32
293 : : pid_t owner_pid;
294 : : #else
295 : : HANDLE handle;
296 : : #endif
297 : :
298 : : /*
299 : : * The memory barrier has to be placed here to ensure that any flag
300 : : * variables possibly changed by this process have been flushed to main
301 : : * memory, before we check/set is_set.
302 : : */
3889 andres@anarazel.de 303 : 1340949 : pg_memory_barrier();
304 : :
305 : : /* Quick exit if already set */
5474 heikki.linnakangas@i 306 [ + + ]: 1340949 : if (latch->is_set)
307 : 207077 : return;
308 : :
309 : 1133872 : latch->is_set = true;
310 : :
1650 tmunro@postgresql.or 311 : 1133872 : pg_memory_barrier();
312 [ + + ]: 1133872 : if (!latch->maybe_sleeping)
313 : 77695 : return;
314 : :
315 : : #ifndef WIN32
316 : :
317 : : /*
318 : : * See if anyone's waiting for the latch. It can be the current process if
319 : : * we're in a signal handler. We use the self-pipe or SIGURG to ourselves
320 : : * to wake up WaitEventSetWaitBlock() without races in that case. If it's
321 : : * another process, send a signal.
322 : : *
323 : : * Fetch owner_pid only once, in case the latch is concurrently getting
324 : : * owned or disowned. XXX: This assumes that pid_t is atomic, which isn't
325 : : * guaranteed to be true! In practice, the effective range of pid_t fits
326 : : * in a 32 bit integer, and so should be atomic. In the worst case, we
327 : : * might end up signaling the wrong process. Even then, you're very
328 : : * unlucky if a process with that bogus pid exists and belongs to
329 : : * Postgres; and PG database processes should handle excess SIGUSR1
330 : : * interrupts without a problem anyhow.
331 : : *
332 : : * Another sort of race condition that's possible here is for a new
333 : : * process to own the latch immediately after we look, so we don't signal
334 : : * it. This is okay so long as all callers of ResetLatch/WaitLatch follow
335 : : * the standard coding convention of waiting at the bottom of their loops,
336 : : * not the top, so that they'll correctly process latch-setting events
337 : : * that happen before they enter the loop.
338 : : */
5474 heikki.linnakangas@i 339 : 1056177 : owner_pid = latch->owner_pid;
340 [ - + ]: 1056177 : if (owner_pid == 0)
5474 heikki.linnakangas@i 341 :UBC 0 : return;
5474 heikki.linnakangas@i 342 [ + + ]:CBC 1056177 : else if (owner_pid == MyProcPid)
184 343 : 34771 : WakeupMyProc();
344 : : else
345 : 1021406 : WakeupOtherProc(owner_pid);
346 : :
347 : : #else
348 : :
349 : : /*
350 : : * See if anyone's waiting for the latch. It can be the current process if
351 : : * we're in a signal handler.
352 : : *
353 : : * Use a local variable here just in case somebody changes the event field
354 : : * concurrently (which really should not happen).
355 : : */
356 : : handle = latch->event;
357 : : if (handle)
358 : : {
359 : : SetEvent(handle);
360 : :
361 : : /*
362 : : * Note that we silently ignore any errors. We might be in a signal
363 : : * handler or other critical path where it's not safe to call elog().
364 : : */
365 : : }
366 : : #endif
367 : : }
368 : :
369 : : /*
370 : : * Clear the latch. Calling WaitLatch after this will sleep, unless
371 : : * the latch is set again before the WaitLatch call.
372 : : */
373 : : void
2385 peter@eisentraut.org 374 : 1785456 : ResetLatch(Latch *latch)
375 : : {
376 : : /* Only the owner should reset the latch */
5474 heikki.linnakangas@i 377 [ - + ]: 1785456 : Assert(latch->owner_pid == MyProcPid);
1650 tmunro@postgresql.or 378 [ - + ]: 1785456 : Assert(latch->maybe_sleeping == false);
379 : :
5474 heikki.linnakangas@i 380 : 1785456 : latch->is_set = false;
381 : :
382 : : /*
383 : : * Ensure that the write to is_set gets flushed to main memory before we
384 : : * examine any flag variables. Otherwise a concurrent SetLatch might
385 : : * falsely conclude that it needn't signal us, even though we have missed
386 : : * seeing some flag updates that SetLatch was supposed to inform us of.
387 : : */
3889 andres@anarazel.de 388 : 1785456 : pg_memory_barrier();
5474 heikki.linnakangas@i 389 : 1785456 : }
|