diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 24 | ||||
-rw-r--r-- | src/backend/utils/activity/wait_event.c | 41 | ||||
-rw-r--r-- | src/include/utils/wait_event.h | 42 |
3 files changed, 69 insertions, 38 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee272..692f21ef6a8 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -448,6 +448,9 @@ InitProcess(void) OwnLatch(&MyProc->procLatch); SwitchToSharedLatch(); + /* now that we have a proc, report wait events to shared memory */ + pgstat_set_wait_event_storage(&MyProc->wait_event_info); + /* * We might be reusing a semaphore that belonged to a failed process. So * be careful and reinitialize its value here. (This is not strictly @@ -601,6 +604,9 @@ InitAuxiliaryProcess(void) OwnLatch(&MyProc->procLatch); SwitchToSharedLatch(); + /* now that we have a proc, report wait events to shared memory */ + pgstat_set_wait_event_storage(&MyProc->wait_event_info); + /* Check that group locking fields are in a proper initial state. */ Assert(MyProc->lockGroupLeader == NULL); Assert(dlist_is_empty(&MyProc->lockGroupMembers)); @@ -884,10 +890,15 @@ ProcKill(int code, Datum arg) /* * Reset MyLatch to the process local one. This is so that signal * handlers et al can continue using the latch after the shared latch - * isn't ours anymore. After that clear MyProc and disown the shared - * latch. + * isn't ours anymore. + * + * Similarly, stop reporting wait events to MyProc->wait_event_info. + * + * After that clear MyProc and disown the shared latch. */ SwitchBackToLocalLatch(); + pgstat_reset_wait_event_storage(); + proc = MyProc; MyProc = NULL; DisownLatch(&proc->procLatch); @@ -952,13 +963,10 @@ AuxiliaryProcKill(int code, Datum arg) /* Cancel any pending condition variable sleep, too */ ConditionVariableCancelSleep(); - /* - * Reset MyLatch to the process local one. This is so that signal - * handlers et al can continue using the latch after the shared latch - * isn't ours anymore. After that clear MyProc and disown the shared - * latch. - */ + /* look at the equivalent ProcKill() code for comments */ SwitchBackToLocalLatch(); + pgstat_reset_wait_event_storage(); + proc = MyProc; MyProc = NULL; DisownLatch(&proc->procLatch); diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c index 840ebef92ab..accc1eb5776 100644 --- a/src/backend/utils/activity/wait_event.c +++ b/src/backend/utils/activity/wait_event.c @@ -7,6 +7,17 @@ * * IDENTIFICATION * src/backend/postmaster/wait_event.c + * + * NOTES + * + * To make pgstat_report_wait_start() and pgstat_report_wait_end() as + * lightweight as possible, they do not check if shared memory (MyProc + * specifically, where the wait event is stored) is already available. Instead + * we initially set my_wait_event_info to a process local variable, which then + * is redirected to shared memory using pgstat_set_wait_event_storage(). For + * the same reason pgstat_track_activities is not checked - the check adds + * more work than it saves. + * * ---------- */ #include "postgres.h" @@ -23,6 +34,36 @@ static const char *pgstat_get_wait_timeout(WaitEventTimeout w); static const char *pgstat_get_wait_io(WaitEventIO w); +static uint32 local_my_wait_event_info; +uint32 *my_wait_event_info = &local_my_wait_event_info; + + +/* + * Configure wait event reporting to report wait events to *wait_event_info. + * *wait_event_info needs to be valid until pgstat_reset_wait_event_storage() + * is called. + * + * Expected to be called during backend startup, to point my_wait_event_info + * into shared memory. + */ +void +pgstat_set_wait_event_storage(uint32 *wait_event_info) +{ + my_wait_event_info = wait_event_info; +} + +/* + * Reset wait event storage location. + * + * Expected to be called during backend shutdown, before the location set up + * pgstat_set_wait_event_storage() becomes invalid. + */ +void +pgstat_reset_wait_event_storage(void) +{ + my_wait_event_info = &local_my_wait_event_info; +} + /* ---------- * pgstat_get_wait_event_type() - * diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h index 2c883467f34..44448b48ec0 100644 --- a/src/include/utils/wait_event.h +++ b/src/include/utils/wait_event.h @@ -11,9 +11,6 @@ #define WAIT_EVENT_H -#include "storage/proc.h" /* for MyProc */ - - /* ---------- * Wait Classes * ---------- @@ -234,13 +231,10 @@ extern const char *pgstat_get_wait_event(uint32 wait_event_info); extern const char *pgstat_get_wait_event_type(uint32 wait_event_info); static inline void pgstat_report_wait_start(uint32 wait_event_info); static inline void pgstat_report_wait_end(void); +extern void pgstat_set_wait_event_storage(uint32 *wait_event_info); +extern void pgstat_reset_wait_event_storage(void); - -/* - * Repeated here for the inline functions because it is declared in pgstat.h, - * which includes this header. - */ -extern PGDLLIMPORT bool pgstat_track_activities; +extern PGDLLIMPORT uint32 *my_wait_event_info; /* ---------- @@ -254,47 +248,35 @@ extern PGDLLIMPORT bool pgstat_track_activities; * for wait event which is sufficient for current usage, 1-byte is * reserved for future usage. * - * NB: this *must* be able to survive being called before MyProc has been - * initialized. + * Historically we used to make this reporting conditional on + * pgstat_track_activities, but the check for that seems to add more cost + * than it saves. + * + * my_wait_event_info initially points to local memory, making it safe to + * call this before MyProc has been initialized. * ---------- */ static inline void pgstat_report_wait_start(uint32 wait_event_info) { - volatile PGPROC *proc = MyProc; - - if (!pgstat_track_activities || !proc) - return; - /* * Since this is a four-byte field which is always read and written as * four-bytes, updates are atomic. */ - proc->wait_event_info = wait_event_info; + *(volatile uint32 *) my_wait_event_info = wait_event_info; } /* ---------- * pgstat_report_wait_end() - * * Called to report end of a wait. - * - * NB: this *must* be able to survive being called before MyProc has been - * initialized. * ---------- */ static inline void pgstat_report_wait_end(void) { - volatile PGPROC *proc = MyProc; - - if (!pgstat_track_activities || !proc) - return; - - /* - * Since this is a four-byte field which is always read and written as - * four-bytes, updates are atomic. - */ - proc->wait_event_info = 0; + /* see pgstat_report_wait_start() */ + *(volatile uint32 *) my_wait_event_info = 0; } |