OSDN Git Service

Add Win32 semaphore implementation, rather than mimicking SysV
authorBruce Momjian <bruce@momjian.us>
Sat, 29 Apr 2006 16:34:41 +0000 (16:34 +0000)
committerBruce Momjian <bruce@momjian.us>
Sat, 29 Apr 2006 16:34:41 +0000 (16:34 +0000)
semaphores.

Qingqing Zhou

configure.in
src/backend/port/win32_sema.c [new file with mode: 0644]
src/include/storage/pg_sema.h

index f35cdd6..83a2906 100644 (file)
@@ -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 (file)
index 0000000..bf8ee83
--- /dev/null
@@ -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;
+}
index bacbd7d..65a4824 100644 (file)
@@ -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;