aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2006-04-29 16:34:41 +0000
committerBruce Momjian <bruce@momjian.us>2006-04-29 16:34:41 +0000
commit908f317b73c784b7101463d08d6415ef7fd5cb6c (patch)
treea9893dc6523b874260197a20e07a0f981728cae2 /src
parent291724dfa8809c8103a413cd653c1063336d8790 (diff)
downloadpostgresql-908f317b73c784b7101463d08d6415ef7fd5cb6c.tar.gz
postgresql-908f317b73c784b7101463d08d6415ef7fd5cb6c.zip
Add Win32 semaphore implementation, rather than mimicking SysV
semaphores. Qingqing Zhou
Diffstat (limited to 'src')
-rw-r--r--src/backend/port/win32_sema.c195
-rw-r--r--src/include/storage/pg_sema.h7
2 files changed, 201 insertions, 1 deletions
diff --git a/src/backend/port/win32_sema.c b/src/backend/port/win32_sema.c
new file mode 100644
index 00000000000..bf8ee839f25
--- /dev/null
+++ b/src/backend/port/win32_sema.c
@@ -0,0 +1,195 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_sema.c
+ * Microsoft Windows Win32 Semaphores Emulation
+ *
+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/port/win32_sema.c,v 1.1 2006/04/29 16:34:41 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "miscadmin.h"
+#include "storage/ipc.h"
+#include "storage/pg_sema.h"
+
+static HANDLE *mySemSet; /* IDs of sema sets acquired so far */
+static int numSems; /* number of sema sets acquired so far */
+static int maxSems; /* allocated size of mySemaSet array */
+
+static void ReleaseSemaphores(int code, Datum arg);
+
+/*
+ * PGReserveSemaphores --- initialize semaphore support
+ *
+ * In the Win32 implementation, we acquire semaphores on-demand; the
+ * maxSemas parameter is just used to size the array that keeps track of
+ * acquired semas for subsequent releasing. We use anonymous semaphores
+ * so the semaphores are automatically freed when the last referencing
+ * process exits.
+ */
+void PGReserveSemaphores(int maxSemas, int port)
+{
+ mySemSet = (HANDLE *)malloc(maxSemas * sizeof(HANDLE));
+ if (mySemSet == NULL)
+ elog(PANIC, "out of memory");
+ numSems = 0;
+ maxSems = maxSemas;
+
+ on_shmem_exit(ReleaseSemaphores, 0);
+}
+
+/*
+ * Release semaphores at shutdown or shmem reinitialization
+ *
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+ReleaseSemaphores(int code, Datum arg)
+{
+ int i;
+
+ for (i = 0; i < numSems; i++)
+ CloseHandle(mySemSet[i]);
+ free(mySemSet);
+}
+
+/*
+ * PGSemaphoreCreate
+ *
+ * Initialize a PGSemaphore structure to represent a sema with count 1
+ */
+void PGSemaphoreCreate(PGSemaphore sema)
+{
+ HANDLE cur_handle;
+ SECURITY_ATTRIBUTES sec_attrs;
+
+ /* Can't do this in a backend, because static state is postmaster's */
+ Assert(!IsUnderPostmaster);
+
+ if (numSems >= maxSems)
+ elog(PANIC, "too many semaphores created");
+
+ ZeroMemory(&sec_attrs, sizeof(sec_attrs));
+ sec_attrs.nLength = sizeof(sec_attrs);
+ sec_attrs.lpSecurityDescriptor = NULL;
+ sec_attrs.bInheritHandle = TRUE;
+
+ /* We don't need a named semaphore */
+ cur_handle = CreateSemaphore(&sec_attrs, 1, 1, NULL);
+ if (cur_handle)
+ {
+ /* Successfully done */
+ *sema = cur_handle;
+ mySemSet[numSems++] = cur_handle;
+ }
+ else
+ ereport(PANIC,
+ (errmsg("could not create semaphore: error code %d", (int)GetLastError())));
+}
+
+/*
+ * PGSemaphoreReset
+ *
+ * Reset a previously-initialized PGSemaphore to have count 0
+ */
+void PGSemaphoreReset(PGSemaphore sema)
+{
+ /*
+ * There's no direct API for this in Win32, so we have to ratchet the
+ * semaphore down to 0 with repeated trylock's.
+ */
+ while (PGSemaphoreTryLock(sema));
+}
+
+/*
+ * PGSemaphoreLock
+ *
+ * Lock a semaphore (decrement count), blocking if count would be < 0.
+ * Serve the interrupt if interruptOK is true.
+ */
+void PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
+{
+ DWORD ret;
+ HANDLE wh[2];
+
+ wh[0] = *sema;
+ wh[1] = pgwin32_signal_event;
+
+ do
+ {
+ ImmediateInterruptOK = interruptOK;
+ CHECK_FOR_INTERRUPTS();
+
+ errno = 0;
+ ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
+
+ if (ret == WAIT_OBJECT_0)
+ {
+ /* We got it! */
+ return;
+ }
+ else if (ret == WAIT_OBJECT_0 + 1)
+ {
+ /* Signal event is set - we have a signal to deliver */
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ }
+ else
+ /* Otherwise we are in trouble */
+ errno = EIDRM;
+
+ ImmediateInterruptOK = false;
+ } while (errno == EINTR);
+
+ if (errno != 0)
+ ereport(FATAL,
+ (errmsg("could not lock semaphore: error code %d", (int) GetLastError())));
+}
+
+/*
+ * PGSemaphoreUnlock
+ *
+ * Unlock a semaphore (increment count)
+ */
+void PGSemaphoreUnlock(PGSemaphore sema)
+{
+ if (!ReleaseSemaphore(*sema, 1, NULL))
+ ereport(FATAL,
+ (errmsg("could not unlock semaphore: error code %d", (int) GetLastError())));
+}
+
+/*
+ * PGSemaphoreTryLock
+ *
+ * Lock a semaphore only if able to do so without blocking
+ */
+bool PGSemaphoreTryLock(PGSemaphore sema)
+{
+ DWORD ret;
+
+ ret = WaitForSingleObject(*sema, 0);
+
+ if (ret == WAIT_OBJECT_0)
+ {
+ /* We got it! */
+ return true;
+ }
+ else if (ret == WAIT_TIMEOUT)
+ {
+ /* Can't get it */
+ errno = EAGAIN;
+ return false;
+ }
+
+ /* Otherwise we are in trouble */
+ ereport(FATAL,
+ (errmsg("could not try-lock semaphore: error code %d", (int) GetLastError())));
+
+ /* keep compiler quiet */
+ return false;
+}
diff --git a/src/include/storage/pg_sema.h b/src/include/storage/pg_sema.h
index bacbd7d3f0c..65a482468d3 100644
--- a/src/include/storage/pg_sema.h
+++ b/src/include/storage/pg_sema.h
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/pg_sema.h,v 1.8 2006/03/05 15:58:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/pg_sema.h,v 1.9 2006/04/29 16:34:41 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,6 +54,11 @@ typedef struct PGSemaphoreData
} PGSemaphoreData;
#endif
+#ifdef USE_WIN32_SEMAPHORES
+
+typedef HANDLE PGSemaphoreData;
+#endif
+
typedef PGSemaphoreData *PGSemaphore;