1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Semaphores Emulation
6 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
9 * $PostgreSQL: pgsql/src/backend/port/win32_sema.c,v 1.5 2007/04/24 12:25:18 mha Exp $
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 %d", (int) 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 wh[1] = pgwin32_signal_event;
129 ImmediateInterruptOK = interruptOK;
130 CHECK_FOR_INTERRUPTS();
133 ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
135 if (ret == WAIT_OBJECT_0)
140 else if (ret == WAIT_OBJECT_0 + 1)
142 /* Signal event is set - we have a signal to deliver */
143 pgwin32_dispatch_queued_signals();
147 /* Otherwise we are in trouble */
150 ImmediateInterruptOK = false;
151 } while (errno == EINTR);
155 (errmsg("could not lock semaphore: error code %d", (int) GetLastError())));
161 * Unlock a semaphore (increment count)
164 PGSemaphoreUnlock(PGSemaphore sema)
166 if (!ReleaseSemaphore(*sema, 1, NULL))
168 (errmsg("could not unlock semaphore: error code %d", (int) GetLastError())));
174 * Lock a semaphore only if able to do so without blocking
177 PGSemaphoreTryLock(PGSemaphore sema)
181 ret = WaitForSingleObject(*sema, 0);
183 if (ret == WAIT_OBJECT_0)
188 else if (ret == WAIT_TIMEOUT)
195 /* Otherwise we are in trouble */
197 (errmsg("could not try-lock semaphore: error code %d", (int) GetLastError())));
199 /* keep compiler quiet */