PostgreSQL Source Code git master
Loading...
Searching...
No Matches
win32_sema.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * win32_sema.c
4 * Microsoft Windows Win32 Semaphores Emulation
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/backend/port/win32_sema.c
10 *
11 *-------------------------------------------------------------------------
12 */
13
14#include "postgres.h"
15
16#include "miscadmin.h"
17#include "storage/ipc.h"
18#include "storage/pg_sema.h"
19
20static HANDLE *mySemSet; /* IDs of sema sets acquired so far */
21static int numSems; /* number of sema sets acquired so far */
22static int maxSems; /* allocated size of mySemaSet array */
23
24static void ReleaseSemaphores(int code, Datum arg);
25
26
27/*
28 * Report amount of shared memory needed for semaphores
29 */
30Size
32{
33 /* No shared memory needed on Windows */
34 return 0;
35}
36
37/*
38 * PGReserveSemaphores --- initialize semaphore support
39 *
40 * In the Win32 implementation, we acquire semaphores on-demand; the
41 * maxSemas parameter is just used to size the array that keeps track of
42 * acquired semas for subsequent releasing. We use anonymous semaphores
43 * so the semaphores are automatically freed when the last referencing
44 * process exits.
45 */
46void
48{
49 mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
50 if (mySemSet == NULL)
51 elog(PANIC, "out of memory");
52 numSems = 0;
54
56}
57
58/*
59 * Release semaphores at shutdown or shmem reinitialization
60 *
61 * (called as an on_shmem_exit callback, hence funny argument list)
62 */
63static void
65{
66 int i;
67
68 for (i = 0; i < numSems; i++)
71}
72
73/*
74 * PGSemaphoreCreate
75 *
76 * Allocate a PGSemaphore structure with initial count 1
77 */
80{
83
84 /* Can't do this in a backend, because static state is postmaster's */
86
87 if (numSems >= maxSems)
88 elog(PANIC, "too many semaphores created");
89
91 sec_attrs.nLength = sizeof(sec_attrs);
92 sec_attrs.lpSecurityDescriptor = NULL;
93 sec_attrs.bInheritHandle = TRUE;
94
95 /* We don't need a named semaphore */
97 if (cur_handle)
98 {
99 /* Successfully done */
101 }
102 else
104 (errmsg("could not create semaphore: error code %lu",
105 GetLastError())));
106
107 return (PGSemaphore) cur_handle;
108}
109
110/*
111 * PGSemaphoreReset
112 *
113 * Reset a previously-initialized PGSemaphore to have count 0
114 */
115void
117{
118 /*
119 * There's no direct API for this in Win32, so we have to ratchet the
120 * semaphore down to 0 with repeated trylock's.
121 */
122 while (PGSemaphoreTryLock(sema))
123 /* loop */ ;
124}
125
126/*
127 * PGSemaphoreLock
128 *
129 * Lock a semaphore (decrement count), blocking if count would be < 0.
130 */
131void
133{
134 HANDLE wh[2];
135 bool done = false;
136
137 /*
138 * Note: pgwin32_signal_event should be first to ensure that it will be
139 * reported when multiple events are set. We want to guarantee that
140 * pending signals are serviced.
141 */
143 wh[1] = sema;
144
145 /*
146 * As in other implementations of PGSemaphoreLock, we need to check for
147 * cancel/die interrupts each time through the loop. But here, there is
148 * no hidden magic about whether the syscall will internally service a
149 * signal --- we do that ourselves.
150 */
151 while (!done)
152 {
153 DWORD rc;
154
156
158 switch (rc)
159 {
160 case WAIT_OBJECT_0:
161 /* Signal event is set - we have a signal to deliver */
163 break;
164 case WAIT_OBJECT_0 + 1:
165 /* We got it! */
166 done = true;
167 break;
169
170 /*
171 * The system interrupted the wait to execute an I/O
172 * completion routine or asynchronous procedure call in this
173 * thread. PostgreSQL does not provoke either of these, but
174 * atypical loaded DLLs or even other processes might do so.
175 * Now, resume waiting.
176 */
177 break;
178 case WAIT_FAILED:
180 (errmsg("could not lock semaphore: error code %lu",
181 GetLastError())));
182 break;
183 default:
184 elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu", rc);
185 break;
186 }
187 }
188}
189
190/*
191 * PGSemaphoreUnlock
192 *
193 * Unlock a semaphore (increment count)
194 */
195void
197{
198 if (!ReleaseSemaphore(sema, 1, NULL))
200 (errmsg("could not unlock semaphore: error code %lu",
201 GetLastError())));
202}
203
204/*
205 * PGSemaphoreTryLock
206 *
207 * Lock a semaphore only if able to do so without blocking
208 */
209bool
211{
212 DWORD ret;
213
214 ret = WaitForSingleObject(sema, 0);
215
216 if (ret == WAIT_OBJECT_0)
217 {
218 /* We got it! */
219 return true;
220 }
221 else if (ret == WAIT_TIMEOUT)
222 {
223 /* Can't get it */
224 errno = EAGAIN;
225 return false;
226 }
227
228 /* Otherwise we are in trouble */
230 (errmsg("could not try-lock semaphore: error code %lu",
231 GetLastError())));
232
233 /* keep compiler quiet */
234 return false;
235}
#define Assert(condition)
Definition c.h:873
size_t Size
Definition c.h:619
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define FATAL
Definition elog.h:41
#define PANIC
Definition elog.h:42
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
bool IsUnderPostmaster
Definition globals.c:120
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
int i
Definition isn.c:77
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
void * arg
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
void pgwin32_dispatch_queued_signals(void)
Definition signal.c:120
HANDLE pgwin32_signal_event
Definition signal.c:27
#define free(a)
#define malloc(a)
#define EAGAIN
Definition win32_port.h:359
Size PGSemaphoreShmemSize(int maxSemas)
Definition win32_sema.c:31
void PGSemaphoreUnlock(PGSemaphore sema)
Definition win32_sema.c:196
static int maxSems
Definition win32_sema.c:22
void PGReserveSemaphores(int maxSemas)
Definition win32_sema.c:47
void PGSemaphoreReset(PGSemaphore sema)
Definition win32_sema.c:116
void PGSemaphoreLock(PGSemaphore sema)
Definition win32_sema.c:132
static int numSems
Definition win32_sema.c:21
bool PGSemaphoreTryLock(PGSemaphore sema)
Definition win32_sema.c:210
static HANDLE * mySemSet
Definition win32_sema.c:20
PGSemaphore PGSemaphoreCreate(void)
Definition win32_sema.c:79
static void ReleaseSemaphores(int code, Datum arg)
Definition win32_sema.c:64