@ -56,6 +56,7 @@
# include "storage/latch.h"
# include "storage/pmsignal.h"
# include "storage/shmem.h"
# include "utils/memutils.h"
/*
* Select the fd readiness primitive to use . Normally the " most modern "
@ -129,6 +130,12 @@ struct WaitEventSet
# endif
} ;
/* A common WaitEventSet used to implement WatchLatch() */
static WaitEventSet * LatchWaitSet ;
/* The position of the latch in LatchWaitSet. */
# define LatchWaitSetLatchPos 0
# ifndef WIN32
/* Are we currently in WaitLatch? The signal handler would like to know. */
static volatile sig_atomic_t waiting = false ;
@ -242,6 +249,24 @@ InitializeLatchSupport(void)
# endif
}
void
InitializeLatchWaitSet ( void )
{
int latch_pos PG_USED_FOR_ASSERTS_ONLY ;
Assert ( LatchWaitSet = = NULL ) ;
/* Set up the WaitEventSet used by WaitLatch(). */
LatchWaitSet = CreateWaitEventSet ( TopMemoryContext , 2 ) ;
latch_pos = AddWaitEventToSet ( LatchWaitSet , WL_LATCH_SET , PGINVALID_SOCKET ,
MyLatch , NULL ) ;
if ( IsUnderPostmaster )
AddWaitEventToSet ( LatchWaitSet , WL_EXIT_ON_PM_DEATH ,
PGINVALID_SOCKET , NULL , NULL ) ;
Assert ( latch_pos = = LatchWaitSetLatchPos ) ;
}
/*
* Initialize a process - local latch .
*/
@ -365,8 +390,31 @@ int
WaitLatch ( Latch * latch , int wakeEvents , long timeout ,
uint32 wait_event_info )
{
return WaitLatchOrSocket ( latch , wakeEvents , PGINVALID_SOCKET , timeout ,
wait_event_info ) ;
WaitEvent event ;
/* Postmaster-managed callers must handle postmaster death somehow. */
Assert ( ! IsUnderPostmaster | |
( wakeEvents & WL_EXIT_ON_PM_DEATH ) | |
( wakeEvents & WL_POSTMASTER_DEATH ) ) ;
/*
* Some callers may have a latch other than MyLatch , or no latch at all ,
* or want to handle postmaster death differently . It ' s cheap to assign
* those , so just do it every time .
*/
if ( ! ( wakeEvents & WL_LATCH_SET ) )
latch = NULL ;
ModifyWaitEvent ( LatchWaitSet , LatchWaitSetLatchPos , WL_LATCH_SET , latch ) ;
LatchWaitSet - > exit_on_postmaster_death =
( ( wakeEvents & WL_EXIT_ON_PM_DEATH ) ! = 0 ) ;
if ( WaitEventSetWait ( LatchWaitSet ,
( wakeEvents & WL_TIMEOUT ) ? timeout : - 1 ,
& event , 1 ,
wait_event_info ) = = 0 )
return WL_TIMEOUT ;
else
return event . events ;
}
/*
@ -830,7 +878,8 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch,
/*
* Change the event mask and , in the WL_LATCH_SET case , the latch associated
* with the WaitEvent .
* with the WaitEvent . The latch may be changed to NULL to disable the latch
* temporarily , and then set back to a latch later .
*
* ' pos ' is the id returned by AddWaitEventToSet .
*/
@ -862,7 +911,6 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
if ( event - > events & WL_LATCH_SET & &
events ! = event - > events )
{
/* we could allow to disable latch events for a while */
elog ( ERROR , " cannot modify latch event " ) ;
}