Add support for user-defined I/O conversion casts.
[PostgreSQL.git] / src / backend / port / win32_sema.c
blob2acb17307a56b0bd85422548c9051ed2a005a172
1 /*-------------------------------------------------------------------------
3 * win32_sema.c
4 * Microsoft Windows Win32 Semaphores Emulation
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 * IDENTIFICATION
9 * $PostgreSQL$
11 *-------------------------------------------------------------------------
14 #include "postgres.h"
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
33 * process exits.
35 void
36 PGReserveSemaphores(int maxSemas, int port)
38 mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
39 if (mySemSet == NULL)
40 elog(PANIC, "out of memory");
41 numSems = 0;
42 maxSems = maxSemas;
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)
52 static void
53 ReleaseSemaphores(int code, Datum arg)
55 int i;
57 for (i = 0; i < numSems; i++)
58 CloseHandle(mySemSet[i]);
59 free(mySemSet);
63 * PGSemaphoreCreate
65 * Initialize a PGSemaphore structure to represent a sema with count 1
67 void
68 PGSemaphoreCreate(PGSemaphore sema)
70 HANDLE cur_handle;
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);
86 if (cur_handle)
88 /* Successfully done */
89 *sema = cur_handle;
90 mySemSet[numSems++] = cur_handle;
92 else
93 ereport(PANIC,
94 (errmsg("could not create semaphore: error code %d", (int) GetLastError())));
98 * PGSemaphoreReset
100 * Reset a previously-initialized PGSemaphore to have count 0
102 void
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));
113 * PGSemaphoreLock
115 * Lock a semaphore (decrement count), blocking if count would be < 0.
116 * Serve the interrupt if interruptOK is true.
118 void
119 PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
121 DWORD ret;
122 HANDLE wh[2];
124 wh[0] = *sema;
125 wh[1] = pgwin32_signal_event;
128 * As in other implementations of PGSemaphoreLock, we need to check
129 * for cancel/die interrupts each time through the loop. But here,
130 * there is no hidden magic about whether the syscall will internally
131 * service a signal --- we do that ourselves.
135 ImmediateInterruptOK = interruptOK;
136 CHECK_FOR_INTERRUPTS();
138 errno = 0;
139 ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
141 if (ret == WAIT_OBJECT_0)
143 /* We got it! */
144 return;
146 else if (ret == WAIT_OBJECT_0 + 1)
148 /* Signal event is set - we have a signal to deliver */
149 pgwin32_dispatch_queued_signals();
150 errno = EINTR;
152 else
153 /* Otherwise we are in trouble */
154 errno = EIDRM;
156 ImmediateInterruptOK = false;
157 } while (errno == EINTR);
159 if (errno != 0)
160 ereport(FATAL,
161 (errmsg("could not lock semaphore: error code %d", (int) GetLastError())));
165 * PGSemaphoreUnlock
167 * Unlock a semaphore (increment count)
169 void
170 PGSemaphoreUnlock(PGSemaphore sema)
172 if (!ReleaseSemaphore(*sema, 1, NULL))
173 ereport(FATAL,
174 (errmsg("could not unlock semaphore: error code %d", (int) GetLastError())));
178 * PGSemaphoreTryLock
180 * Lock a semaphore only if able to do so without blocking
182 bool
183 PGSemaphoreTryLock(PGSemaphore sema)
185 DWORD ret;
187 ret = WaitForSingleObject(*sema, 0);
189 if (ret == WAIT_OBJECT_0)
191 /* We got it! */
192 return true;
194 else if (ret == WAIT_TIMEOUT)
196 /* Can't get it */
197 errno = EAGAIN;
198 return false;
201 /* Otherwise we are in trouble */
202 ereport(FATAL,
203 (errmsg("could not try-lock semaphore: error code %d", (int) GetLastError())));
205 /* keep compiler quiet */
206 return false;