1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Semaphores Emulation
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
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
;
128 * As in other implementations of PGSemaphoreLock, we need to check for
129 * cancel/die interrupts each time through the loop. But here, there is
130 * no hidden magic about whether the syscall will internally service a
131 * signal --- we do that ourselves.
135 ImmediateInterruptOK
= interruptOK
;
136 CHECK_FOR_INTERRUPTS();
139 ret
= WaitForMultipleObjectsEx(2, wh
, FALSE
, INFINITE
, TRUE
);
141 if (ret
== WAIT_OBJECT_0
)
146 else if (ret
== WAIT_OBJECT_0
+ 1)
148 /* Signal event is set - we have a signal to deliver */
149 pgwin32_dispatch_queued_signals();
153 /* Otherwise we are in trouble */
156 ImmediateInterruptOK
= false;
157 } while (errno
== EINTR
);
161 (errmsg("could not lock semaphore: error code %d", (int) GetLastError())));
167 * Unlock a semaphore (increment count)
170 PGSemaphoreUnlock(PGSemaphore sema
)
172 if (!ReleaseSemaphore(*sema
, 1, NULL
))
174 (errmsg("could not unlock semaphore: error code %d", (int) GetLastError())));
180 * Lock a semaphore only if able to do so without blocking
183 PGSemaphoreTryLock(PGSemaphore sema
)
187 ret
= WaitForSingleObject(*sema
, 0);
189 if (ret
== WAIT_OBJECT_0
)
194 else if (ret
== WAIT_TIMEOUT
)
201 /* Otherwise we are in trouble */
203 (errmsg("could not try-lock semaphore: error code %d", (int) GetLastError())));
205 /* keep compiler quiet */