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 * Request shared memory needed for semaphores
29 */
30void
32{
33 /* No shared memory needed on Windows */
34}
35
36/*
37 * PGSemaphoreInit --- initialize semaphore support
38 *
39 * In the Win32 implementation, we acquire semaphores on-demand; the
40 * maxSemas parameter is just used to size the array that keeps track of
41 * acquired semas for subsequent releasing. We use anonymous semaphores
42 * so the semaphores are automatically freed when the last referencing
43 * process exits.
44 */
45void
47{
48 mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
49 if (mySemSet == NULL)
50 elog(PANIC, "out of memory");
51 numSems = 0;
53
55}
56
57/*
58 * Release semaphores at shutdown or shmem reinitialization
59 *
60 * (called as an on_shmem_exit callback, hence funny argument list)
61 */
62static void
64{
65 int i;
66
67 for (i = 0; i < numSems; i++)
70}
71
72/*
73 * PGSemaphoreCreate
74 *
75 * Allocate a PGSemaphore structure with initial count 1
76 */
79{
82
83 /* Can't do this in a backend, because static state is postmaster's */
85
86 if (numSems >= maxSems)
87 elog(PANIC, "too many semaphores created");
88
90 sec_attrs.nLength = sizeof(sec_attrs);
91 sec_attrs.lpSecurityDescriptor = NULL;
92 sec_attrs.bInheritHandle = TRUE;
93
94 /* We don't need a named semaphore */
96 if (cur_handle)
97 {
98 /* Successfully done */
100 }
101 else
103 (errmsg("could not create semaphore: error code %lu",
104 GetLastError())));
105
106 return (PGSemaphore) cur_handle;
107}
108
109/*
110 * PGSemaphoreReset
111 *
112 * Reset a previously-initialized PGSemaphore to have count 0
113 */
114void
116{
117 /*
118 * There's no direct API for this in Win32, so we have to ratchet the
119 * semaphore down to 0 with repeated trylock's.
120 */
121 while (PGSemaphoreTryLock(sema))
122 /* loop */ ;
123}
124
125/*
126 * PGSemaphoreLock
127 *
128 * Lock a semaphore (decrement count), blocking if count would be < 0.
129 */
130void
132{
133 HANDLE wh[2];
134 bool done = false;
135
136 /*
137 * Note: pgwin32_signal_event should be first to ensure that it will be
138 * reported when multiple events are set. We want to guarantee that
139 * pending signals are serviced.
140 */
142 wh[1] = sema;
143
144 /*
145 * As in other implementations of PGSemaphoreLock, we need to check for
146 * cancel/die interrupts each time through the loop. But here, there is
147 * no hidden magic about whether the syscall will internally service a
148 * signal --- we do that ourselves.
149 */
150 while (!done)
151 {
152 DWORD rc;
153
155
157 switch (rc)
158 {
159 case WAIT_OBJECT_0:
160 /* Signal event is set - we have a signal to deliver */
162 break;
163 case WAIT_OBJECT_0 + 1:
164 /* We got it! */
165 done = true;
166 break;
168
169 /*
170 * The system interrupted the wait to execute an I/O
171 * completion routine or asynchronous procedure call in this
172 * thread. PostgreSQL does not provoke either of these, but
173 * atypical loaded DLLs or even other processes might do so.
174 * Now, resume waiting.
175 */
176 break;
177 case WAIT_FAILED:
179 (errmsg("could not lock semaphore: error code %lu",
180 GetLastError())));
181 break;
182 default:
183 elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu", rc);
184 break;
185 }
186 }
187}
188
189/*
190 * PGSemaphoreUnlock
191 *
192 * Unlock a semaphore (increment count)
193 */
194void
196{
197 if (!ReleaseSemaphore(sema, 1, NULL))
199 (errmsg("could not unlock semaphore: error code %lu",
200 GetLastError())));
201}
202
203/*
204 * PGSemaphoreTryLock
205 *
206 * Lock a semaphore only if able to do so without blocking
207 */
208bool
210{
211 DWORD ret;
212
213 ret = WaitForSingleObject(sema, 0);
214
215 if (ret == WAIT_OBJECT_0)
216 {
217 /* We got it! */
218 return true;
219 }
220 else if (ret == WAIT_TIMEOUT)
221 {
222 /* Can't get it */
223 errno = EAGAIN;
224 return false;
225 }
226
227 /* Otherwise we are in trouble */
229 (errmsg("could not try-lock semaphore: error code %lu",
230 GetLastError())));
231
232 /* keep compiler quiet */
233 return false;
234}
#define Assert(condition)
Definition c.h:943
Datum arg
Definition elog.c:1322
#define FATAL
Definition elog.h:42
#define PANIC
Definition elog.h:44
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
bool IsUnderPostmaster
Definition globals.c:122
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:125
static char * errmsg
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
void PGSemaphoreUnlock(PGSemaphore sema)
Definition win32_sema.c:195
static int maxSems
Definition win32_sema.c:22
void PGSemaphoreShmemRequest(int maxSemas)
Definition win32_sema.c:31
void PGSemaphoreReset(PGSemaphore sema)
Definition win32_sema.c:115
void PGSemaphoreLock(PGSemaphore sema)
Definition win32_sema.c:131
void PGSemaphoreInit(int maxSemas)
Definition win32_sema.c:46
static int numSems
Definition win32_sema.c:21
bool PGSemaphoreTryLock(PGSemaphore sema)
Definition win32_sema.c:209
static HANDLE * mySemSet
Definition win32_sema.c:20
PGSemaphore PGSemaphoreCreate(void)
Definition win32_sema.c:78
static void ReleaseSemaphores(int code, Datum arg)
Definition win32_sema.c:63