@ -62,6 +62,7 @@
# include "storage/pmsignal.h"
# include "storage/pmsignal.h"
# include "storage/shmem.h"
# include "storage/shmem.h"
# include "utils/memutils.h"
# include "utils/memutils.h"
# include "utils/resowner.h"
/*
/*
* Select the fd readiness primitive to use . Normally the " most modern "
* Select the fd readiness primitive to use . Normally the " most modern "
@ -101,6 +102,8 @@
/* typedef in latch.h */
/* typedef in latch.h */
struct WaitEventSet
struct WaitEventSet
{
{
ResourceOwner owner ;
int nevents ; /* number of registered events */
int nevents ; /* number of registered events */
int nevents_space ; /* maximum number of events in this set */
int nevents_space ; /* maximum number of events in this set */
@ -195,6 +198,31 @@ static void WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event);
static inline int WaitEventSetWaitBlock ( WaitEventSet * set , int cur_timeout ,
static inline int WaitEventSetWaitBlock ( WaitEventSet * set , int cur_timeout ,
WaitEvent * occurred_events , int nevents ) ;
WaitEvent * occurred_events , int nevents ) ;
/* ResourceOwner support to hold WaitEventSets */
static void ResOwnerReleaseWaitEventSet ( Datum res ) ;
static const ResourceOwnerDesc wait_event_set_resowner_desc =
{
. name = " WaitEventSet " ,
. release_phase = RESOURCE_RELEASE_AFTER_LOCKS ,
. release_priority = RELEASE_PRIO_WAITEVENTSETS ,
. ReleaseResource = ResOwnerReleaseWaitEventSet ,
. DebugPrint = NULL
} ;
/* Convenience wrappers over ResourceOwnerRemember/Forget */
static inline void
ResourceOwnerRememberWaitEventSet ( ResourceOwner owner , WaitEventSet * set )
{
ResourceOwnerRemember ( owner , PointerGetDatum ( set ) , & wait_event_set_resowner_desc ) ;
}
static inline void
ResourceOwnerForgetWaitEventSet ( ResourceOwner owner , WaitEventSet * set )
{
ResourceOwnerForget ( owner , PointerGetDatum ( set ) , & wait_event_set_resowner_desc ) ;
}
/*
/*
* Initialize the process - local latch infrastructure .
* Initialize the process - local latch infrastructure .
*
*
@ -323,7 +351,7 @@ InitializeLatchWaitSet(void)
Assert ( LatchWaitSet = = NULL ) ;
Assert ( LatchWaitSet = = NULL ) ;
/* Set up the WaitEventSet used by WaitLatch(). */
/* Set up the WaitEventSet used by WaitLatch(). */
LatchWaitSet = CreateWaitEventSet ( TopMemoryContext , 2 ) ;
LatchWaitSet = CreateWaitEventSet ( NULL , 2 ) ;
latch_pos = AddWaitEventToSet ( LatchWaitSet , WL_LATCH_SET , PGINVALID_SOCKET ,
latch_pos = AddWaitEventToSet ( LatchWaitSet , WL_LATCH_SET , PGINVALID_SOCKET ,
MyLatch , NULL ) ;
MyLatch , NULL ) ;
if ( IsUnderPostmaster )
if ( IsUnderPostmaster )
@ -541,7 +569,7 @@ WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
int ret = 0 ;
int ret = 0 ;
int rc ;
int rc ;
WaitEvent event ;
WaitEvent event ;
WaitEventSet * set = CreateWaitEventSet ( CurrentMemoryContext , 3 ) ;
WaitEventSet * set = CreateWaitEventSet ( CurrentResourceOwner , 3 ) ;
if ( wakeEvents & WL_TIMEOUT )
if ( wakeEvents & WL_TIMEOUT )
Assert ( timeout > = 0 ) ;
Assert ( timeout > = 0 ) ;
@ -716,9 +744,12 @@ ResetLatch(Latch *latch)
*
*
* These events can then be efficiently waited upon together , using
* These events can then be efficiently waited upon together , using
* WaitEventSetWait ( ) .
* WaitEventSetWait ( ) .
*
* The WaitEventSet is tracked by the given ' resowner ' . Use NULL for session
* lifetime .
*/
*/
WaitEventSet *
WaitEventSet *
CreateWaitEventSet ( MemoryContext context , int nevents )
CreateWaitEventSet ( ResourceOwner resowner , int nevents )
{
{
WaitEventSet * set ;
WaitEventSet * set ;
char * data ;
char * data ;
@ -744,7 +775,10 @@ CreateWaitEventSet(MemoryContext context, int nevents)
sz + = MAXALIGN ( sizeof ( HANDLE ) * ( nevents + 1 ) ) ;
sz + = MAXALIGN ( sizeof ( HANDLE ) * ( nevents + 1 ) ) ;
# endif
# endif
data = ( char * ) MemoryContextAllocZero ( context , sz ) ;
if ( resowner ! = NULL )
ResourceOwnerEnlarge ( resowner ) ;
data = ( char * ) MemoryContextAllocZero ( TopMemoryContext , sz ) ;
set = ( WaitEventSet * ) data ;
set = ( WaitEventSet * ) data ;
data + = MAXALIGN ( sizeof ( WaitEventSet ) ) ;
data + = MAXALIGN ( sizeof ( WaitEventSet ) ) ;
@ -770,6 +804,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
set - > nevents_space = nevents ;
set - > nevents_space = nevents ;
set - > exit_on_postmaster_death = false ;
set - > exit_on_postmaster_death = false ;
if ( resowner ! = NULL )
{
ResourceOwnerRememberWaitEventSet ( resowner , set ) ;
set - > owner = resowner ;
}
# if defined(WAIT_USE_EPOLL)
# if defined(WAIT_USE_EPOLL)
if ( ! AcquireExternalFD ( ) )
if ( ! AcquireExternalFD ( ) )
{
{
@ -834,6 +874,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
void
void
FreeWaitEventSet ( WaitEventSet * set )
FreeWaitEventSet ( WaitEventSet * set )
{
{
if ( set - > owner )
{
ResourceOwnerForgetWaitEventSet ( set - > owner , set ) ;
set - > owner = NULL ;
}
# if defined(WAIT_USE_EPOLL)
# if defined(WAIT_USE_EPOLL)
close ( set - > epoll_fd ) ;
close ( set - > epoll_fd ) ;
ReleaseExternalFD ( ) ;
ReleaseExternalFD ( ) ;
@ -841,9 +887,7 @@ FreeWaitEventSet(WaitEventSet *set)
close ( set - > kqueue_fd ) ;
close ( set - > kqueue_fd ) ;
ReleaseExternalFD ( ) ;
ReleaseExternalFD ( ) ;
# elif defined(WAIT_USE_WIN32)
# elif defined(WAIT_USE_WIN32)
WaitEvent * cur_event ;
for ( WaitEvent * cur_event = set - > events ;
for ( cur_event = set - > events ;
cur_event < ( set - > events + set - > nevents ) ;
cur_event < ( set - > events + set - > nevents ) ;
cur_event + + )
cur_event + + )
{
{
@ -2300,3 +2344,13 @@ drain(void)
}
}
# endif
# endif
static void
ResOwnerReleaseWaitEventSet ( Datum res )
{
WaitEventSet * set = ( WaitEventSet * ) DatumGetPointer ( res ) ;
Assert ( set - > owner ! = NULL ) ;
set - > owner = NULL ;
FreeWaitEventSet ( set ) ;
}