6262#include "storage/pmsignal.h"
6363#include "storage/shmem.h"
6464#include "utils/memutils.h"
65+ #include "utils/resowner.h"
6566
6667/*
6768 * Select the fd readiness primitive to use. Normally the "most modern"
101102/* typedef in latch.h */
102103struct WaitEventSet
103104{
105+ ResourceOwner owner ;
106+
104107int nevents ;/* number of registered events */
105108int nevents_space ;/* maximum number of events in this set */
106109
@@ -195,6 +198,31 @@ static void WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event);
195198static inline int WaitEventSetWaitBlock (WaitEventSet * set ,int cur_timeout ,
196199WaitEvent * occurred_events ,int nevents );
197200
201+ /* ResourceOwner support to hold WaitEventSets */
202+ static void ResOwnerReleaseWaitEventSet (Datum res );
203+
204+ static const ResourceOwnerDesc wait_event_set_resowner_desc =
205+ {
206+ .name = "WaitEventSet" ,
207+ .release_phase = RESOURCE_RELEASE_AFTER_LOCKS ,
208+ .release_priority = RELEASE_PRIO_WAITEVENTSETS ,
209+ .ReleaseResource = ResOwnerReleaseWaitEventSet ,
210+ .DebugPrint = NULL
211+ };
212+
213+ /* Convenience wrappers over ResourceOwnerRemember/Forget */
214+ static inline void
215+ ResourceOwnerRememberWaitEventSet (ResourceOwner owner ,WaitEventSet * set )
216+ {
217+ ResourceOwnerRemember (owner ,PointerGetDatum (set ),& wait_event_set_resowner_desc );
218+ }
219+ static inline void
220+ ResourceOwnerForgetWaitEventSet (ResourceOwner owner ,WaitEventSet * set )
221+ {
222+ ResourceOwnerForget (owner ,PointerGetDatum (set ),& wait_event_set_resowner_desc );
223+ }
224+
225+
198226/*
199227 * Initialize the process-local latch infrastructure.
200228 *
@@ -323,7 +351,7 @@ InitializeLatchWaitSet(void)
323351Assert (LatchWaitSet == NULL );
324352
325353/* Set up the WaitEventSet used by WaitLatch(). */
326- LatchWaitSet = CreateWaitEventSet (TopMemoryContext ,2 );
354+ LatchWaitSet = CreateWaitEventSet (NULL ,2 );
327355latch_pos = AddWaitEventToSet (LatchWaitSet ,WL_LATCH_SET ,PGINVALID_SOCKET ,
328356MyLatch ,NULL );
329357if (IsUnderPostmaster )
@@ -541,7 +569,7 @@ WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
541569int ret = 0 ;
542570int rc ;
543571WaitEvent event ;
544- WaitEventSet * set = CreateWaitEventSet (CurrentMemoryContext ,3 );
572+ WaitEventSet * set = CreateWaitEventSet (CurrentResourceOwner ,3 );
545573
546574if (wakeEvents & WL_TIMEOUT )
547575Assert (timeout >=0 );
@@ -716,9 +744,12 @@ ResetLatch(Latch *latch)
716744 *
717745 * These events can then be efficiently waited upon together, using
718746 * WaitEventSetWait().
747+ *
748+ * The WaitEventSet is tracked by the given 'resowner'. Use NULL for session
749+ * lifetime.
719750 */
720751WaitEventSet *
721- CreateWaitEventSet (MemoryContext context ,int nevents )
752+ CreateWaitEventSet (ResourceOwner resowner ,int nevents )
722753{
723754WaitEventSet * set ;
724755char * data ;
@@ -744,7 +775,10 @@ CreateWaitEventSet(MemoryContext context, int nevents)
744775sz += MAXALIGN (sizeof (HANDLE )* (nevents + 1 ));
745776#endif
746777
747- data = (char * )MemoryContextAllocZero (context ,sz );
778+ if (resowner != NULL )
779+ ResourceOwnerEnlarge (resowner );
780+
781+ data = (char * )MemoryContextAllocZero (TopMemoryContext ,sz );
748782
749783set = (WaitEventSet * )data ;
750784data += MAXALIGN (sizeof (WaitEventSet ));
@@ -770,6 +804,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
770804set -> nevents_space = nevents ;
771805set -> exit_on_postmaster_death = false;
772806
807+ if (resowner != NULL )
808+ {
809+ ResourceOwnerRememberWaitEventSet (resowner ,set );
810+ set -> owner = resowner ;
811+ }
812+
773813#if defined(WAIT_USE_EPOLL )
774814if (!AcquireExternalFD ())
775815{
@@ -834,16 +874,20 @@ CreateWaitEventSet(MemoryContext context, int nevents)
834874void
835875FreeWaitEventSet (WaitEventSet * set )
836876{
877+ if (set -> owner )
878+ {
879+ ResourceOwnerForgetWaitEventSet (set -> owner ,set );
880+ set -> owner = NULL ;
881+ }
882+
837883#if defined(WAIT_USE_EPOLL )
838884close (set -> epoll_fd );
839885ReleaseExternalFD ();
840886#elif defined(WAIT_USE_KQUEUE )
841887close (set -> kqueue_fd );
842888ReleaseExternalFD ();
843889#elif defined(WAIT_USE_WIN32 )
844- WaitEvent * cur_event ;
845-
846- for (cur_event = set -> events ;
890+ for (WaitEvent * cur_event = set -> events ;
847891cur_event < (set -> events + set -> nevents );
848892cur_event ++ )
849893{
@@ -2300,3 +2344,13 @@ drain(void)
23002344}
23012345
23022346#endif
2347+
2348+ static void
2349+ ResOwnerReleaseWaitEventSet (Datum res )
2350+ {
2351+ WaitEventSet * set = (WaitEventSet * )DatumGetPointer (res );
2352+
2353+ Assert (set -> owner != NULL );
2354+ set -> owner = NULL ;
2355+ FreeWaitEventSet (set );
2356+ }