mirror of https://github.com/postgres/postgres
semaphores. Qingqing ZhouREL8_2_STABLE
parent
291724dfa8
commit
908f317b73
@ -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; |
||||||
|
} |
||||||
Loading…
Reference in new issue