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+
104107 int nevents ; /* number of registered events */
105108 int 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 ,
196199 WaitEvent * 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)
323351 Assert (LatchWaitSet == NULL );
324352
325353 /* Set up the WaitEventSet used by WaitLatch(). */
326- LatchWaitSet = CreateWaitEventSet (TopMemoryContext , 2 );
354+ LatchWaitSet = CreateWaitEventSet (NULL , 2 );
327355 latch_pos = AddWaitEventToSet (LatchWaitSet , WL_LATCH_SET , PGINVALID_SOCKET ,
328356 MyLatch , NULL );
329357 if (IsUnderPostmaster )
@@ -541,7 +569,7 @@ WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
541569 int ret = 0 ;
542570 int rc ;
543571 WaitEvent event ;
544- WaitEventSet * set = CreateWaitEventSet (CurrentMemoryContext , 3 );
572+ WaitEventSet * set = CreateWaitEventSet (CurrentResourceOwner , 3 );
545573
546574 if (wakeEvents & WL_TIMEOUT )
547575 Assert (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{
723754 WaitEventSet * set ;
724755 char * data ;
@@ -744,7 +775,10 @@ CreateWaitEventSet(MemoryContext context, int nevents)
744775 sz += 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
749783 set = (WaitEventSet * ) data ;
750784 data += MAXALIGN (sizeof (WaitEventSet ));
@@ -770,6 +804,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
770804 set -> nevents_space = nevents ;
771805 set -> 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 )
774814 if (!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 )
838884 close (set -> epoll_fd );
839885 ReleaseExternalFD ();
840886#elif defined(WAIT_USE_KQUEUE )
841887 close (set -> kqueue_fd );
842888 ReleaseExternalFD ();
843889#elif defined(WAIT_USE_WIN32 )
844- WaitEvent * cur_event ;
845-
846- for (cur_event = set -> events ;
890+ for (WaitEvent * cur_event = set -> events ;
847891 cur_event < (set -> events + set -> nevents );
848892 cur_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+ }
0 commit comments