/*-------------------------------------------------------------------------
*
* win32_sema . c
* Microsoft Windows Win32 Semaphores Emulation
*
* Portions Copyright ( c ) 1996 - 2025 , PostgreSQL Global Development Group
*
* IDENTIFICATION
* src / backend / port / win32_sema . c
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#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);
/*
* Report amount of shared memory needed for semaphores
*/
Size
PGSemaphoreShmemSize(int maxSemas)
{
/* No shared memory needed on Windows */
return 0 ;
}
/*
* 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)
{
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
*
* Allocate a PGSemaphore structure with initial count 1
*/
PGSemaphore
PGSemaphoreCreate(void )
{
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 , 32767 , NULL);
if (cur_handle)
{
/* Successfully done */
mySemSet[numSems++] = cur_handle;
}
else
ereport(PANIC,
(errmsg("could not create semaphore: error code %lu" ,
GetLastError())));
return (PGSemaphore) cur_handle;
}
/*
* 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))
/* loop */ ;
}
/*
* PGSemaphoreLock
*
* Lock a semaphore ( decrement count ) , blocking if count would be < 0 .
*/
void
PGSemaphoreLock(PGSemaphore sema)
{
HANDLE wh[2 ];
bool done = false ;
/*
* Note : pgwin32_signal_event should be first to ensure that it will be
* reported when multiple events are set . We want to guarantee that
* pending signals are serviced .
*/
wh[0 ] = pgwin32_signal_event;
wh[1 ] = sema;
/*
* As in other implementations of PGSemaphoreLock , we need to check for
* cancel / die interrupts each time through the loop . But here , there is
* no hidden magic about whether the syscall will internally service a
* signal - - - we do that ourselves .
*/
while (!done)
{
DWORD rc;
CHECK_FOR_INTERRUPTS();
rc = WaitForMultipleObjectsEx(2 , wh, FALSE , INFINITE, TRUE );
switch (rc)
{
case WAIT_OBJECT_0:
/* Signal event is set - we have a signal to deliver */
pgwin32_dispatch_queued_signals();
break ;
case WAIT_OBJECT_0 + 1 :
/* We got it! */
done = true ;
break ;
case WAIT_IO_COMPLETION:
/*
* The system interrupted the wait to execute an I / O
* completion routine or asynchronous procedure call in this
* thread . PostgreSQL does not provoke either of these , but
* atypical loaded DLLs or even other processes might do so .
* Now , resume waiting .
*/
break ;
case WAIT_FAILED:
ereport(FATAL,
(errmsg("could not lock semaphore: error code %lu" ,
GetLastError())));
break ;
default :
elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu" , rc);
break ;
}
}
}
/*
* PGSemaphoreUnlock
*
* Unlock a semaphore ( increment count )
*/
void
PGSemaphoreUnlock(PGSemaphore sema)
{
if (!ReleaseSemaphore(sema, 1 , NULL))
ereport(FATAL,
(errmsg("could not unlock semaphore: error code %lu" ,
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 %lu" ,
GetLastError())));
/* keep compiler quiet */
return false ;
}
Messung V0.5 in Prozent C=90 H=90 G=90
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland