aboutsummaryrefslogtreecommitdiff
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
parent291724dfa8809c8103a413cd653c1063336d8790 (diff)
downloadpostgresql-908f317b73c784b7101463d08d6415ef7fd5cb6c.tar.gz
postgresql-908f317b73c784b7101463d08d6415ef7fd5cb6c.zip
Add Win32 semaphore implementation, rather than mimicking SysV
semaphores. Qingqing Zhou
-rw-r--r--configure.in23
-rw-r--r--src/backend/port/win32_sema.c195
-rw-r--r--src/include/storage/pg_sema.h7
3 files changed, 215 insertions, 10 deletions
diff --git a/configure.in b/configure.in
index f35cdd6b7e5..83a29062593 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.462 2006/04/29 00:51:41 momjian Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.463 2006/04/29 16:34:41 momjian Exp $
dnl
dnl Developers, please strive to achieve this order:
dnl
@@ -1269,17 +1269,22 @@ AC_FUNC_MEMCMP
# Select semaphore implementation type.
-if test x"$USE_NAMED_POSIX_SEMAPHORES" = x"1" ; then
- AC_DEFINE(USE_NAMED_POSIX_SEMAPHORES, 1, [Define to select named POSIX semaphores.])
- SEMA_IMPLEMENTATION="src/backend/port/posix_sema.c"
-else
- if test x"$USE_UNNAMED_POSIX_SEMAPHORES" = x"1" ; then
- AC_DEFINE(USE_UNNAMED_POSIX_SEMAPHORES, 1, [Define to select unnamed POSIX semaphores.])
+if test "$PORTNAME" != "win32"; then
+ if test x"$USE_NAMED_POSIX_SEMAPHORES" = x"1" ; then
+ AC_DEFINE(USE_NAMED_POSIX_SEMAPHORES, 1, [Define to select named POSIX semaphores.])
SEMA_IMPLEMENTATION="src/backend/port/posix_sema.c"
else
- AC_DEFINE(USE_SYSV_SEMAPHORES, 1, [Define to select SysV-style semaphores.])
- SEMA_IMPLEMENTATION="src/backend/port/sysv_sema.c"
+ if test x"$USE_UNNAMED_POSIX_SEMAPHORES" = x"1" ; then
+ AC_DEFINE(USE_UNNAMED_POSIX_SEMAPHORES, 1, [Define to select unnamed POSIX semaphores.])
+ SEMA_IMPLEMENTATION="src/backend/port/posix_sema.c"
+ else
+ AC_DEFINE(USE_SYSV_SEMAPHORES, 1, [Define to select SysV-style semaphores.])
+ SEMA_IMPLEMENTATION="src/backend/port/sysv_sema.c"
+ fi
fi
+else
+ AC_DEFINE(USE_WIN32_SEMAPHORES, 1, [Define to select Win32-style semaphores.])
+ SEMA_IMPLEMENTATION="src/backend/port/win32_sema.c"
fi
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;