1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Semaphores Emulation
6 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
9 * src/backend/port/win32_sema.c
11 *-------------------------------------------------------------------------
16 #include "miscadmin.h"
17 #include "storage/ipc.h"
18 #include "storage/pg_sema.h"
20 static HANDLE *mySemSet; /* IDs of sema sets acquired so far */
21 static int numSems; /* number of sema sets acquired so far */
22 static int maxSems; /* allocated size of mySemaSet array */
24 static void ReleaseSemaphores(int code, Datum arg);
27 * PGReserveSemaphores --- initialize semaphore support
29 * In the Win32 implementation, we acquire semaphores on-demand; the
30 * maxSemas parameter is just used to size the array that keeps track of
31 * acquired semas for subsequent releasing. We use anonymous semaphores
32 * so the semaphores are automatically freed when the last referencing
36 PGReserveSemaphores(int maxSemas, int port)
38 mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
40 elog(PANIC, "out of memory");
44 on_shmem_exit(ReleaseSemaphores, 0);
48 * Release semaphores at shutdown or shmem reinitialization
50 * (called as an on_shmem_exit callback, hence funny argument list)
53 ReleaseSemaphores(int code, Datum arg)
57 for (i = 0; i < numSems; i++)
58 CloseHandle(mySemSet[i]);
65 * Initialize a PGSemaphore structure to represent a sema with count 1
68 PGSemaphoreCreate(PGSemaphore sema)
71 SECURITY_ATTRIBUTES sec_attrs;
73 /* Can't do this in a backend, because static state is postmaster's */
74 Assert(!IsUnderPostmaster);
76 if (numSems >= maxSems)
77 elog(PANIC, "too many semaphores created");
79 ZeroMemory(&sec_attrs, sizeof(sec_attrs));
80 sec_attrs.nLength = sizeof(sec_attrs);
81 sec_attrs.lpSecurityDescriptor = NULL;
82 sec_attrs.bInheritHandle = TRUE;
84 /* We don't need a named semaphore */
85 cur_handle = CreateSemaphore(&sec_attrs, 1, 32767, NULL);
88 /* Successfully done */
90 mySemSet[numSems++] = cur_handle;
94 (errmsg("could not create semaphore: error code %lu", GetLastError())));
100 * Reset a previously-initialized PGSemaphore to have count 0
103 PGSemaphoreReset(PGSemaphore sema)
106 * There's no direct API for this in Win32, so we have to ratchet the
107 * semaphore down to 0 with repeated trylock's.
109 while (PGSemaphoreTryLock(sema));
115 * Lock a semaphore (decrement count), blocking if count would be < 0.
116 * Serve the interrupt if interruptOK is true.
119 PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
125 * Note: pgwin32_signal_event should be first to ensure that it will be
126 * reported when multiple events are set. We want to guarantee that
127 * pending signals are serviced.
129 wh[0] = pgwin32_signal_event;
133 * As in other implementations of PGSemaphoreLock, we need to check for
134 * cancel/die interrupts each time through the loop. But here, there is
135 * no hidden magic about whether the syscall will internally service a
136 * signal --- we do that ourselves.
140 ImmediateInterruptOK = interruptOK;
141 CHECK_FOR_INTERRUPTS();
143 ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
145 if (ret == WAIT_OBJECT_0)
147 /* Signal event is set - we have a signal to deliver */
148 pgwin32_dispatch_queued_signals();
151 else if (ret == WAIT_OBJECT_0 + 1)
157 /* Otherwise we are in trouble */
160 ImmediateInterruptOK = false;
161 } while (errno == EINTR);
165 (errmsg("could not lock semaphore: error code %lu", GetLastError())));
171 * Unlock a semaphore (increment count)
174 PGSemaphoreUnlock(PGSemaphore sema)
176 if (!ReleaseSemaphore(*sema, 1, NULL))
178 (errmsg("could not unlock semaphore: error code %lu", GetLastError())));
184 * Lock a semaphore only if able to do so without blocking
187 PGSemaphoreTryLock(PGSemaphore sema)
191 ret = WaitForSingleObject(*sema, 0);
193 if (ret == WAIT_OBJECT_0)
198 else if (ret == WAIT_TIMEOUT)
205 /* Otherwise we are in trouble */
207 (errmsg("could not try-lock semaphore: error code %lu", GetLastError())));
209 /* keep compiler quiet */