62
62
#include "storage/pmsignal.h"
63
63
#include "storage/shmem.h"
64
64
#include "utils/memutils.h"
65
+ #include "utils/resowner.h"
65
66
66
67
/*
67
68
* Select the fd readiness primitive to use. Normally the "most modern"
101
102
/* typedef in latch.h */
102
103
struct WaitEventSet
103
104
{
105
+ ResourceOwner owner ;
106
+
104
107
int nevents ;/* number of registered events */
105
108
int nevents_space ;/* maximum number of events in this set */
106
109
@@ -195,6 +198,31 @@ static void WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event);
195
198
static inline int WaitEventSetWaitBlock (WaitEventSet * set ,int cur_timeout ,
196
199
WaitEvent * occurred_events ,int nevents );
197
200
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
+
198
226
/*
199
227
* Initialize the process-local latch infrastructure.
200
228
*
@@ -323,7 +351,7 @@ InitializeLatchWaitSet(void)
323
351
Assert (LatchWaitSet == NULL );
324
352
325
353
/* Set up the WaitEventSet used by WaitLatch(). */
326
- LatchWaitSet = CreateWaitEventSet (TopMemoryContext ,2 );
354
+ LatchWaitSet = CreateWaitEventSet (NULL ,2 );
327
355
latch_pos = AddWaitEventToSet (LatchWaitSet ,WL_LATCH_SET ,PGINVALID_SOCKET ,
328
356
MyLatch ,NULL );
329
357
if (IsUnderPostmaster )
@@ -541,7 +569,7 @@ WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
541
569
int ret = 0 ;
542
570
int rc ;
543
571
WaitEvent event ;
544
- WaitEventSet * set = CreateWaitEventSet (CurrentMemoryContext ,3 );
572
+ WaitEventSet * set = CreateWaitEventSet (CurrentResourceOwner ,3 );
545
573
546
574
if (wakeEvents & WL_TIMEOUT )
547
575
Assert (timeout >=0 );
@@ -716,9 +744,12 @@ ResetLatch(Latch *latch)
716
744
*
717
745
* These events can then be efficiently waited upon together, using
718
746
* WaitEventSetWait().
747
+ *
748
+ * The WaitEventSet is tracked by the given 'resowner'. Use NULL for session
749
+ * lifetime.
719
750
*/
720
751
WaitEventSet *
721
- CreateWaitEventSet (MemoryContext context ,int nevents )
752
+ CreateWaitEventSet (ResourceOwner resowner ,int nevents )
722
753
{
723
754
WaitEventSet * set ;
724
755
char * data ;
@@ -744,7 +775,10 @@ CreateWaitEventSet(MemoryContext context, int nevents)
744
775
sz += MAXALIGN (sizeof (HANDLE )* (nevents + 1 ));
745
776
#endif
746
777
747
- data = (char * )MemoryContextAllocZero (context ,sz );
778
+ if (resowner != NULL )
779
+ ResourceOwnerEnlarge (resowner );
780
+
781
+ data = (char * )MemoryContextAllocZero (TopMemoryContext ,sz );
748
782
749
783
set = (WaitEventSet * )data ;
750
784
data += MAXALIGN (sizeof (WaitEventSet ));
@@ -770,6 +804,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
770
804
set -> nevents_space = nevents ;
771
805
set -> exit_on_postmaster_death = false;
772
806
807
+ if (resowner != NULL )
808
+ {
809
+ ResourceOwnerRememberWaitEventSet (resowner ,set );
810
+ set -> owner = resowner ;
811
+ }
812
+
773
813
#if defined(WAIT_USE_EPOLL )
774
814
if (!AcquireExternalFD ())
775
815
{
@@ -834,16 +874,20 @@ CreateWaitEventSet(MemoryContext context, int nevents)
834
874
void
835
875
FreeWaitEventSet (WaitEventSet * set )
836
876
{
877
+ if (set -> owner )
878
+ {
879
+ ResourceOwnerForgetWaitEventSet (set -> owner ,set );
880
+ set -> owner = NULL ;
881
+ }
882
+
837
883
#if defined(WAIT_USE_EPOLL )
838
884
close (set -> epoll_fd );
839
885
ReleaseExternalFD ();
840
886
#elif defined(WAIT_USE_KQUEUE )
841
887
close (set -> kqueue_fd );
842
888
ReleaseExternalFD ();
843
889
#elif defined(WAIT_USE_WIN32 )
844
- WaitEvent * cur_event ;
845
-
846
- for (cur_event = set -> events ;
890
+ for (WaitEvent * cur_event = set -> events ;
847
891
cur_event < (set -> events + set -> nevents );
848
892
cur_event ++ )
849
893
{
@@ -2300,3 +2344,13 @@ drain(void)
2300
2344
}
2301
2345
2302
2346
#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
+ }