Add Win32 semaphore implementation, rather than mimicking SysV
semaphores. Qingqing Zhou
This commit is contained in:
parent
291724dfa8
commit
908f317b73
23
configure.in
23
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
|
||||
|
||||
|
||||
|
195
src/backend/port/win32_sema.c
Normal file
195
src/backend/port/win32_sema.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user