commit c26f82a01c68b578a498b721191bb23cd3e51556
Author: Alexander Korotkov <akorotkov@postgresql.org>
Date:   Fri Feb 21 23:35:34 2020 +0300

    Add pg_shmem_init_time() function returning shmem initialization time
    
    When server crashes, postmaster typically stays alive, but reinitializes shared
    memory and restarts peers.  So, calculation of uptime requires parsing of log
    files.  New pg_shmem_init_time() function returns last shmem (re)initialization
    time.  So, one can easily calculate the server uptime in SQL.
    
    Discussion: https://postgr.es/m/flat/b3a85c5d-56a8-677b-5578-86d94654eb5c%40postgrespro.ru
    Author: Anastasia Lubennikova
    Reviewed-by: Tomas Vondra, Peter Eisentraut, Justin Pryzby, Tom Lane, Robert Haas, Alexander Korotkov

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index ceda48e0fc3..887da61445a 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16948,6 +16948,12 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n);
        <entry>configuration load time</entry>
       </row>
 
+      <row>
+       <entry><literal><function>pg_shmem_init_time()</function></literal></entry>
+       <entry><type>timestamp with time zone</type></entry>
+       <entry>shared memory initialization time</entry>
+      </row>
+
       <row>
        <entry><literal><function>pg_current_logfile(<optional><type>text</type></optional>)</function></literal></entry>
        <entry><type>text</type></entry>
@@ -17199,6 +17205,19 @@ SET search_path TO <replaceable>schema</replaceable> <optional>, <replaceable>sc
     the time when the postmaster process re-read the configuration files.)
    </para>
 
+   <indexterm>
+    <primary>pg_shmem_init_time</primary>
+   </indexterm>
+
+   <para>
+    <function>pg_shmem_init_time</function> returns the
+    <type>timestamp with time zone</type> when the server shared memory was
+    initialized or reinitialized the last time.  When server crashes, postmaster
+    typically stays alive, but reinitializes shared memory and restarts peers.
+    <function>pg_shmem_init_time</function> lets one calculate real server
+    uptime.
+   </para>
+
    <indexterm>
     <primary>pg_current_logfile</primary>
    </indexterm>
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index b86281acd86..bda0bff70ce 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -506,6 +506,7 @@ typedef struct
 	pid_t		PostmasterPid;
 	TimestampTz PgStartTime;
 	TimestampTz PgReloadTime;
+	TimestampTz PgShmemInitTime;
 	pg_time_t	first_syslogger_file_time;
 	bool		redirection_done;
 	bool		IsBinaryUpgrade;
@@ -2633,6 +2634,8 @@ reset_shared(void)
 	 * clean up dead IPC objects if the postmaster crashes and is restarted.
 	 */
 	CreateSharedMemoryAndSemaphores();
+
+	PgShmemInitTime = GetCurrentTimestamp();
 }
 
 
@@ -6179,6 +6182,7 @@ save_backend_variables(BackendParameters *param, Port *port,
 	param->PostmasterPid = PostmasterPid;
 	param->PgStartTime = PgStartTime;
 	param->PgReloadTime = PgReloadTime;
+	param->PgShmemInitTime = PgShmemInitTime;
 	param->first_syslogger_file_time = first_syslogger_file_time;
 
 	param->redirection_done = redirection_done;
@@ -6414,6 +6418,7 @@ restore_backend_variables(BackendParameters *param, Port *port)
 	PostmasterPid = param->PostmasterPid;
 	PgStartTime = param->PgStartTime;
 	PgReloadTime = param->PgReloadTime;
+	PgShmemInitTime = param->PgShmemInitTime;
 	first_syslogger_file_time = param->first_syslogger_file_time;
 
 	redirection_done = param->redirection_done;
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 0b6c9d5ea8e..e9c444380ef 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -51,6 +51,9 @@ TimestampTz PgStartTime;
 /* Set at configuration reload */
 TimestampTz PgReloadTime;
 
+/* Set at shared memory (re)initialization */
+TimestampTz PgShmemInitTime;
+
 typedef struct
 {
 	Timestamp	current;
@@ -1573,6 +1576,12 @@ pg_conf_load_time(PG_FUNCTION_ARGS)
 	PG_RETURN_TIMESTAMPTZ(PgReloadTime);
 }
 
+Datum
+pg_shmem_init_time(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_TIMESTAMPTZ(PgShmemInitTime);
+}
+
 /*
  * GetCurrentTimestamp -- get the current operating system time
  *
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index eb3c1a88d14..3ac0ccd2f2c 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -7839,6 +7839,12 @@
   prorettype => 'timestamptz', proargtypes => '',
   prosrc => 'pg_conf_load_time' },
 
+# shared memory (re)init time function
+{ oid => '4035', descr => 'shared memory (re)init time',
+  proname => 'pg_shmem_init_time', provolatile => 's', proparallel => 'r',
+  prorettype => 'timestamptz', proargtypes => '',
+  prosrc => 'pg_shmem_init_time' },
+
 # new functions for Y-direction rtree opclasses
 { oid => '2562',
   proname => 'box_below', prorettype => 'bool', proargtypes => 'box box',
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index 03a1de569f0..6e67e45c78b 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -62,6 +62,8 @@ extern TimestampTz PgStartTime;
 /* Set at configuration reload */
 extern TimestampTz PgReloadTime;
 
+/* Set at shared memory (re)initialization */
+extern TimestampTz PgShmemInitTime;
 
 /* Internal routines (not fmgr-callable) */
 
