beentry = MyBEEntry;
    do
    {
-       beentry->st_changecount++;
+       pgstat_increment_changecount_before(beentry);
    } while ((beentry->st_changecount & 1) == 0);
 
    beentry->st_procpid = MyProcPid;
    beentry->st_appname[NAMEDATALEN - 1] = '\0';
    beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0';
 
-   beentry->st_changecount++;
-   Assert((beentry->st_changecount & 1) == 0);
+   pgstat_increment_changecount_after(beentry);
 
    /* Update app name to current GUC setting */
    if (application_name)
     * before and after.  We use a volatile pointer here to ensure the
     * compiler doesn't try to get cute.
     */
-   beentry->st_changecount++;
+   pgstat_increment_changecount_before(beentry);
 
    beentry->st_procpid = 0;    /* mark invalid */
 
-   beentry->st_changecount++;
-   Assert((beentry->st_changecount & 1) == 0);
+   pgstat_increment_changecount_after(beentry);
 }
 
 
             * non-disabled state.  As our final update, change the state and
             * clear fields we will not be updating anymore.
             */
-           beentry->st_changecount++;
+           pgstat_increment_changecount_before(beentry);
            beentry->st_state = STATE_DISABLED;
            beentry->st_state_start_timestamp = 0;
            beentry->st_activity[0] = '\0';
            /* st_xact_start_timestamp and st_waiting are also disabled */
            beentry->st_xact_start_timestamp = 0;
            beentry->st_waiting = false;
-           beentry->st_changecount++;
-           Assert((beentry->st_changecount & 1) == 0);
+           pgstat_increment_changecount_after(beentry);
        }
        return;
    }
    /*
     * Now update the status entry
     */
-   beentry->st_changecount++;
+   pgstat_increment_changecount_before(beentry);
 
    beentry->st_state = state;
    beentry->st_state_start_timestamp = current_timestamp;
        beentry->st_activity_start_timestamp = start_timestamp;
    }
 
-   beentry->st_changecount++;
-   Assert((beentry->st_changecount & 1) == 0);
+   pgstat_increment_changecount_after(beentry);
 }
 
 /* ----------
     * st_changecount before and after.  We use a volatile pointer here to
     * ensure the compiler doesn't try to get cute.
     */
-   beentry->st_changecount++;
+   pgstat_increment_changecount_before(beentry);
 
    memcpy((char *) beentry->st_appname, appname, len);
    beentry->st_appname[len] = '\0';
 
-   beentry->st_changecount++;
-   Assert((beentry->st_changecount & 1) == 0);
+   pgstat_increment_changecount_after(beentry);
 }
 
 /*
     * st_changecount before and after.  We use a volatile pointer here to
     * ensure the compiler doesn't try to get cute.
     */
-   beentry->st_changecount++;
+   pgstat_increment_changecount_before(beentry);
    beentry->st_xact_start_timestamp = tstamp;
-   beentry->st_changecount++;
-   Assert((beentry->st_changecount & 1) == 0);
+   pgstat_increment_changecount_after(beentry);
 }
 
 /* ----------
         */
        for (;;)
        {
-           int         save_changecount = beentry->st_changecount;
+           int         before_changecount;
+           int         after_changecount;
+
+           pgstat_save_changecount_before(beentry, before_changecount);
 
            localentry->backendStatus.st_procpid = beentry->st_procpid;
            if (localentry->backendStatus.st_procpid > 0)
                localentry->backendStatus.st_activity = localactivity;
            }
 
-           if (save_changecount == beentry->st_changecount &&
-               (save_changecount & 1) == 0)
+           pgstat_save_changecount_after(beentry, after_changecount);
+           if (before_changecount == after_changecount &&
+               (before_changecount & 1) == 0)
                break;
 
            /* Make sure we can break out of loop if stuck... */
 
        for (;;)
        {
-           int         save_changecount = vbeentry->st_changecount;
+           int         before_changecount;
+           int         after_changecount;
+
+           pgstat_save_changecount_before(vbeentry, before_changecount);
 
            found = (vbeentry->st_procpid == pid);
 
-           if (save_changecount == vbeentry->st_changecount &&
-               (save_changecount & 1) == 0)
+           pgstat_save_changecount_after(vbeentry, after_changecount);
+
+           if (before_changecount == after_changecount &&
+               (before_changecount & 1) == 0)
                break;
 
            /* Make sure we can break out of loop if stuck... */
 
 #include "libpq/pqcomm.h"
 #include "portability/instr_time.h"
 #include "postmaster/pgarch.h"
+#include "storage/barrier.h"
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
 
     * st_changecount again.  If the value hasn't changed, and if it's even,
     * the copy is valid; otherwise start over.  This makes updates cheap
     * while reads are potentially expensive, but that's the tradeoff we want.
+    *
+    * The above protocol needs the memory barriers to ensure that
+    * the apparent order of execution is as it desires. Otherwise,
+    * for example, the CPU might rearrange the code so that st_changecount
+    * is incremented twice before the modification on a machine with
+    * weak memory ordering. This surprising result can lead to bugs.
     */
    int         st_changecount;
 
    char       *st_activity;
 } PgBackendStatus;
 
+/*
+ * Macros to load and store st_changecount with the memory barriers.
+ *
+ * pgstat_increment_changecount_before() and
+ * pgstat_increment_changecount_after() need to be called before and after
+ * PgBackendStatus entries are modified, respectively. This makes sure that
+ * st_changecount is incremented around the modification.
+ *
+ * Also pgstat_save_changecount_before() and pgstat_save_changecount_after()
+ * need to be called before and after PgBackendStatus entries are copied into
+ * private memory, respectively.
+ */
+#define pgstat_increment_changecount_before(beentry)   \
+   do {    \
+       beentry->st_changecount++;  \
+       pg_write_barrier(); \
+   } while (0)
+
+#define pgstat_increment_changecount_after(beentry)    \
+   do {    \
+       pg_write_barrier(); \
+       beentry->st_changecount++;  \
+       Assert((beentry->st_changecount & 1) == 0); \
+   } while (0)
+
+#define pgstat_save_changecount_before(beentry, save_changecount)  \
+   do {    \
+       save_changecount = beentry->st_changecount; \
+       pg_read_barrier();  \
+   } while (0)
+
+#define pgstat_save_changecount_after(beentry, save_changecount)   \
+   do {    \
+       pg_read_barrier();  \
+       save_changecount = beentry->st_changecount; \
+   } while (0)
+
 /* ----------
  * LocalPgBackendStatus
  *