Hello.
In the attached patch I've made a refactoring for tranches.
The prefix for them was extended, and I've did a split of LWLockAssign to two
functions (one with tranche and second for user defined LWLocks).

--
Ildus Kurbangaliev
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 0eb991c..e75ca4d 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -480,7 +480,7 @@ pgss_shmem_startup(void)
 	if (!found)
 	{
 		/* First time through ... */
-		pgss->lock = LWLockAssign();
+		pgss->lock = LWLockUserAssign();
 		pgss->cur_median_usage = ASSUMED_MEDIAN_INIT;
 		pgss->mean_query_len = ASSUMED_LENGTH_INIT;
 		SpinLockInit(&pgss->mutex);
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 9c15950..b365565 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3356,7 +3356,7 @@ if (!ptr)
         {
                 initialize contents of shmem area;
                 acquire any requested LWLocks using:
-                ptr->mylockid = LWLockAssign();
+                ptr->mylockid = LWLockUserAssign();
         }
         LWLockRelease(AddinShmemInitLock);
 }
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 3a58f1e..3a55511 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -457,7 +457,7 @@ CLOGShmemInit(void)
 {
 	ClogCtl->PagePrecedes = CLOGPagePrecedes;
 	SimpleLruInit(ClogCtl, "CLOG Ctl", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE,
-				  CLogControlLock, "pg_clog");
+				  CLogControlLock, "pg_clog", LW_TRANCHE_CLOG_BUFFERS);
 }
 
 /*
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 5ad35c0..2571203 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -466,7 +466,8 @@ CommitTsShmemInit(void)
 
 	CommitTsCtl->PagePrecedes = CommitTsPagePrecedes;
 	SimpleLruInit(CommitTsCtl, "CommitTs Ctl", CommitTsShmemBuffers(), 0,
-				  CommitTsControlLock, "pg_commit_ts");
+				  CommitTsControlLock, "pg_commit_ts",
+				  LW_TRANCHE_COMMITTS_BUFFERS);
 
 	commitTsShared = ShmemInitStruct("CommitTs shared",
 									 sizeof(CommitTimestampShared),
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 1933a87..e8d2474 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1842,10 +1842,12 @@ MultiXactShmemInit(void)
 
 	SimpleLruInit(MultiXactOffsetCtl,
 				  "MultiXactOffset Ctl", NUM_MXACTOFFSET_BUFFERS, 0,
-				  MultiXactOffsetControlLock, "pg_multixact/offsets");
+				  MultiXactOffsetControlLock, "pg_multixact/offsets",
+				  LW_TRANCHE_MULTIXACT_BUFFERS);
 	SimpleLruInit(MultiXactMemberCtl,
 				  "MultiXactMember Ctl", NUM_MXACTMEMBER_BUFFERS, 0,
-				  MultiXactMemberControlLock, "pg_multixact/members");
+				  MultiXactMemberControlLock, "pg_multixact/members",
+				  LW_TRANCHE_MULTIXACT_BUFFERS);
 
 	/* Initialize our shared state struct */
 	MultiXactState = ShmemInitStruct("Shared MultiXact State",
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 5fcea11..7709f6d 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -161,7 +161,7 @@ SimpleLruShmemSize(int nslots, int nlsns)
 
 void
 SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
-			  LWLock *ctllock, const char *subdir)
+			  LWLock *ctllock, const char *subdir, int lwlocktranche)
 {
 	SlruShared	shared;
 	bool		found;
@@ -218,7 +218,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 			shared->page_status[slotno] = SLRU_PAGE_EMPTY;
 			shared->page_dirty[slotno] = false;
 			shared->page_lru_count[slotno] = 0;
-			shared->buffer_locks[slotno] = LWLockAssign();
+			shared->buffer_locks[slotno] = LWLockAssign(lwlocktranche);
 			ptr += BLCKSZ;
 		}
 	}
diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c
index 6b70982..80690bc 100644
--- a/src/backend/access/transam/subtrans.c
+++ b/src/backend/access/transam/subtrans.c
@@ -179,7 +179,8 @@ SUBTRANSShmemInit(void)
 {
 	SubTransCtl->PagePrecedes = SubTransPagePrecedes;
 	SimpleLruInit(SubTransCtl, "SUBTRANS Ctl", NUM_SUBTRANS_BUFFERS, 0,
-				  SubtransControlLock, "pg_subtrans");
+				  SubtransControlLock, "pg_subtrans",
+				  LW_TRANCHE_SUBTRANS_BUFFERS);
 	/* Override default assumption that writes should be fsync'd */
 	SubTransCtl->do_fsync = false;
 }
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index e82a53a..fd04258 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -621,6 +621,7 @@ CREATE VIEW pg_stat_activity AS
             S.query_start,
             S.state_change,
             S.waiting,
+            S.wait_event,
             S.state,
             S.backend_xid,
             s.backend_xmin,
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 3b71174..4325f12 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -469,7 +469,7 @@ AsyncShmemInit(void)
 	 */
 	AsyncCtl->PagePrecedes = asyncQueuePagePrecedes;
 	SimpleLruInit(AsyncCtl, "Async Ctl", NUM_ASYNC_BUFFERS, 0,
-				  AsyncCtlLock, "pg_notify");
+				  AsyncCtlLock, "pg_notify", LW_TRANCHE_ASYNC_BUFFERS);
 	/* Override default assumption that writes should be fsync'd */
 	AsyncCtl->do_fsync = false;
 
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index 4a650cc..e5c023f 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -36,6 +36,7 @@
 #include "tcop/tcopprot.h"
 #include "utils/memutils.h"
 #include "storage/proc.h"
+#include "pgstat.h"
 
 
 char	   *ssl_cert_file;
@@ -129,6 +130,8 @@ secure_read(Port *port, void *ptr, size_t len)
 	ssize_t		n;
 	int			waitfor;
 
+	pgstat_report_wait_start(WAIT_NETWORK, WAIT_NETWORK_READ);
+
 retry:
 #ifdef USE_SSL
 	waitfor = 0;
@@ -175,6 +178,7 @@ retry:
 	 * interrupts from being processed.
 	 */
 	ProcessClientReadInterrupt(false);
+	pgstat_report_wait_end();
 
 	return n;
 }
@@ -209,6 +213,8 @@ secure_write(Port *port, void *ptr, size_t len)
 	ssize_t		n;
 	int			waitfor;
 
+	pgstat_report_wait_start(WAIT_NETWORK, WAIT_NETWORK_WRITE);
+
 retry:
 	waitfor = 0;
 #ifdef USE_SSL
@@ -254,6 +260,7 @@ retry:
 	 * interrupts from being processed.
 	 */
 	ProcessClientWriteInterrupt(false);
+	pgstat_report_wait_end();
 
 	return n;
 }
diff --git a/src/backend/port/unix_latch.c b/src/backend/port/unix_latch.c
index 90ec4f8..dcebfe4 100644
--- a/src/backend/port/unix_latch.c
+++ b/src/backend/port/unix_latch.c
@@ -55,6 +55,7 @@
 #include "storage/latch.h"
 #include "storage/pmsignal.h"
 #include "storage/shmem.h"
+#include "pgstat.h"
 
 /* Are we currently in WaitLatch? The signal handler would like to know. */
 static volatile sig_atomic_t waiting = false;
@@ -262,6 +263,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 #endif
 	}
 
+	pgstat_report_wait_start(WAIT_LATCH, 0);
+
 	waiting = true;
 	do
 	{
@@ -500,6 +503,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 		}
 	} while (result == 0);
 	waiting = false;
+	pgstat_report_wait_end();
 
 	return result;
 }
diff --git a/src/backend/port/win32_latch.c b/src/backend/port/win32_latch.c
index 0e3aaee..92bb5a0 100644
--- a/src/backend/port/win32_latch.c
+++ b/src/backend/port/win32_latch.c
@@ -177,6 +177,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 	/* Ensure that signals are serviced even if latch is already set */
 	pgwin32_dispatch_queued_signals();
 
+	pgstat_report_wait_start(WAIT_LATCH, 0);
+
 	do
 	{
 		/*
@@ -278,6 +280,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 		}
 	} while (result == 0);
 
+	pgstat_report_wait_end();
+
 	/* Clean up the event object we created for the socket */
 	if (sockevent != WSA_INVALID_EVENT)
 	{
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index e9fbc38..7cc48031 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -54,6 +54,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
+#include "storage/lwlock.h"
 #include "storage/pg_shmem.h"
 #include "storage/procsignal.h"
 #include "storage/sinvaladt.h"
@@ -99,7 +100,6 @@
 #define PGSTAT_TAB_HASH_SIZE	512
 #define PGSTAT_FUNCTION_HASH_SIZE	512
 
-
 /* ----------
  * GUC parameters
  * ----------
@@ -242,6 +242,16 @@ static volatile bool got_SIGHUP = false;
  */
 static instr_time total_func_time;
 
+/* Names of WAIT_CLASSES */
+static const char *WAIT_CLASS_NAMES[] =
+{
+	"",
+	"LWLocks",
+	"Locks",
+	"Storage",
+	"Latch",
+	"Network"
+};
 
 /* ----------
  * Local function forward declarations
@@ -2918,6 +2928,89 @@ pgstat_report_waiting(bool waiting)
 	beentry->st_waiting = waiting;
 }
 
+/*
+ * pgstat_get_wait_class_name() -
+ *
+ * Return wait class name for given class
+ */
+
+const char *
+pgstat_get_wait_class_name(uint8 classId)
+{
+	return WAIT_CLASS_NAMES[classId];
+}
+
+/*
+ * pgstat_get_wait_event_name() -
+ *
+ * Return wait event name for the given class and event
+ */
+const char *
+pgstat_get_wait_event_name(uint8 classId, uint8 eventId)
+{
+	static const char *eventsIO[] = {"READ", "WRITE"};
+	static const char *empty = "";
+
+	switch (classId)
+	{
+		case WAIT_LOCK: return LOCK_NAMES[eventId];
+		case WAIT_LWLOCK: return LWLockGroupName(eventId);
+		case WAIT_IO: /* fallthrough */;
+		case WAIT_NETWORK: return eventsIO[eventId];
+		case WAIT_LATCH: return WAIT_CLASS_NAMES[WAIT_LATCH];
+	};
+	return empty;
+}
+
+/* ----------
+ * pgstat_report_wait_start() -
+ *
+ *	Called from backends to report wait event type information.
+ *
+ * NB: this *must* be able to survive being called before MyBEEntry has been
+ * initialized.
+ * ----------
+ */
+void
+pgstat_report_wait_start(uint8 classId, uint8 eventId)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!pgstat_track_activities || !beentry)
+		return;
+
+	/* prevent nested waits */
+	if (beentry->st_wait_nested++ > 0)
+		return;
+
+	/*
+	 * Since this is a uint32 field in a struct that only this process
+	 * may modify, there seems no need to bother with the st_changecount
+	 * protocol.  The update must appear atomic in any case.
+	 */
+	beentry->st_wait_data = ((uint32)classId << 8) + eventId;
+}
+
+/* ----------
+ * pgstat_report_wait_end() -
+ *
+ *  Called from backends, indicates that wait was ended
+ * ---------
+ */
+void
+pgstat_report_wait_end()
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!pgstat_track_activities || !beentry)
+		return;
+
+	/* prevent nested waits */
+	if ((--beentry->st_wait_nested) > 0)
+		return;
+
+	beentry->st_wait_data = 0;
+}
 
 /* ----------
  * pgstat_read_current_status() -
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index f8544de..168df90 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -149,7 +149,7 @@ ReplicationSlotsShmemInit(void)
 
 			/* everything else is zeroed by the memset above */
 			SpinLockInit(&slot->mutex);
-			slot->io_in_progress_lock = LWLockAssign();
+			slot->io_in_progress_lock = LWLockAssign(LW_TRANCHE_REPLICATIONSLOT);
 		}
 	}
 }
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 3ae2848..1170cc8 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -110,8 +110,8 @@ InitBufferPool(void)
 			 */
 			buf->freeNext = i + 1;
 
-			buf->io_in_progress_lock = LWLockAssign();
-			buf->content_lock = LWLockAssign();
+			buf->io_in_progress_lock = LWLockAssign(LW_TRANCHE_BUFFER_MANAGER);
+			buf->content_lock = LWLockAssign(LW_TRANCHE_BUFFER_MANAGER);
 		}
 
 		/* Correct last entry of linked list */
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 1eb2d4b..c3a6621 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -54,6 +54,20 @@ int			max_locks_per_xact; /* set by guc.c */
 #define NLOCKENTS() \
 	mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
 
+/* Lock names. For monitoring purposes */
+const char *LOCK_NAMES[] =
+{
+	"Relation",
+	"RelationExtend",
+	"Page",
+	"Tuple",
+	"Transaction",
+	"VirtualTransaction",
+	"SpeculativeToken",
+	"Object",
+	"Userlock",
+	"Advisory"
+};
 
 /*
  * Data structures defining the semantics of the standard lock methods.
@@ -1591,6 +1605,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
 		new_status[len] = '\0'; /* truncate off " waiting" */
 	}
 	pgstat_report_waiting(true);
+	pgstat_report_wait_start(WAIT_LOCK, locallock->tag.lock.locktag_type);
 
 	awaitedLock = locallock;
 	awaitedOwner = owner;
@@ -1639,6 +1654,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
 
 		/* Report change to non-waiting status */
 		pgstat_report_waiting(false);
+		pgstat_report_wait_end();
 		if (update_process_title)
 		{
 			set_ps_display(new_status, false);
@@ -1654,6 +1670,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
 
 	/* Report change to non-waiting status */
 	pgstat_report_waiting(false);
+	pgstat_report_wait_end();
 	if (update_process_title)
 	{
 		set_ps_display(new_status, false);
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 46cab49..14c80d1 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -80,6 +80,7 @@
 #include "access/subtrans.h"
 #include "commands/async.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "pg_trace.h"
 #include "postmaster/postmaster.h"
 #include "replication/slot.h"
@@ -127,7 +128,6 @@ static int	LWLockTranchesAllocated = 0;
  * where we have special measures to pass it down).
  */
 LWLockPadded *MainLWLockArray = NULL;
-static LWLockTranche MainLWLockTranche;
 
 /*
  * We use this structure to keep track of locked LWLocks for release
@@ -152,6 +152,81 @@ static bool lock_addin_request_allowed = true;
 
 static inline bool LWLockAcquireCommon(LWLock *l, LWLockMode mode,
 					uint64 *valptr, uint64 val);
+static inline void lwlock_report_stat(LWLock *lock);
+
+/*
+ * We keep individual LWLock names here. Other names
+ * obtained from tranches
+ */
+const char *LWLOCK_INDIVIDUAL_NAMES[] =
+{
+	/* Individual LWLocks */
+	"", /* formely was BufFreelistLock */
+	"ShmemIndexLock",
+	"OidGenLock",
+	"XidGenLock",
+	"ProcArrayLock",
+	"SInvalReadLock",
+	"SInvalWriteLock",
+	"WALBufMappingLock",
+	"WALWriteLock",
+	"ControlFileLock",
+	"CheckpointLock",
+	"CLogControlLock",
+	"SubtransControlLock",
+	"MultiXactGenLock",
+	"MultiXactOffsetControlLock",
+	"MultiXactMemberControlLock",
+	"RelCacheInitLock",
+	"CheckpointerCommLock",
+	"TwoPhaseStateLock",
+	"TablespaceCreateLock",
+	"BtreeVacuumLock",
+	"AddinShmemInitLock",
+	"AutovacuumLock",
+	"AutovacuumScheduleLock",
+	"SyncScanLock",
+	"RelationMappingLock",
+	"AsyncCtlLock",
+	"AsyncQueueLock",
+	"SerializableXactHashLock",
+	"SerializableFinishedListLock",
+	"SerializablePredicateLockListLock",
+	"OldSerXidLock",
+	"SyncRepLock",
+	"BackgroundWorkerLock",
+	"DynamicSharedMemoryControlLock",
+	"AutoFileLock",
+	"ReplicationSlotAllocationLock",
+	"ReplicationSlotControlLock",
+	"CommitTsControlLock",
+	"CommitTsLock",
+	"ReplicationOriginLock"
+};
+
+/* Map of base tranches */
+static const struct tranche_map
+{
+	LWLockBaseTranche tranche_id;
+	const char *tranche_name;
+}
+
+baseTranchesMap[] = {
+	{LW_TRANCHE_INDIVIDUAL, "main"},
+	{LW_TRANCHE_BUFFER_MAPPING, "BufferMappingLocks"},
+	{LW_TRANCHE_LOCK_MANAGER, "LockManagerLocks"},
+	{LW_TRANCHE_PREDICATELOCK_MANAGER, "PredicateLockManagerLocks"},
+	{LW_TRANCHE_BUFFER_MANAGER, "BufferManagerLocks"},
+	{LW_TRANCHE_AUXILIARY_PROC, "AuxiliaryProcLocks"},
+	{LW_TRANCHE_CLOG_BUFFERS, "CLogBufferLocks"},
+	{LW_TRANCHE_COMMITTS_BUFFERS, "CommitTSBufferLocks"},
+	{LW_TRANCHE_SUBTRANS_BUFFERS, "SubtransBufferLocks"},
+	{LW_TRANCHE_MULTIXACT_BUFFERS, "MultixactBufferLocks"},
+	{LW_TRANCHE_ASYNC_BUFFERS, "AsyncBufferLocks"},
+	{LW_TRANCHE_OLDSERXID_BUFFERS, "OldSerXidBufferLocks"},
+	{LW_TRANCHE_REPLICATIONSLOT, "ReplicationSlotLocks"},
+	{LW_TRANCHE_USERDEFINED, "UserDefinedLocks"}
+};
 
 #ifdef LWLOCK_STATS
 typedef struct lwlock_stats_key
@@ -317,6 +392,33 @@ get_lwlock_stats_entry(LWLock *lock)
 }
 #endif   /* LWLOCK_STATS */
 
+/*
+ * Initiate base LWLock tranches. All these tranches point to one
+ * array, and used for identification LWLocks from main array
+ */
+static void
+init_base_tranches(void)
+{
+	int i;
+	int id = 0;
+
+	for (i = 0; i < lengthof(baseTranchesMap); i++)
+	{
+		LWLockTranche *tranche = (LWLockTranche *)MemoryContextAllocZero(
+			TopMemoryContext, sizeof(LWLockTranche));
+
+		/* We need to be sure that generated id is equal to map key */
+		Assert(id == baseTranchesMap[i].tranche_id);
+
+		tranche->array_base = MainLWLockArray;
+		tranche->array_stride = sizeof(LWLockPadded);
+		tranche->name = baseTranchesMap[i].tranche_name;
+
+		LWLockRegisterTranche(id, tranche);
+		id = LWLockNewTrancheId();
+	}
+}
+
 
 /*
  * Compute number of LWLocks to allocate in the main array.
@@ -374,7 +476,6 @@ NumLWLocks(void)
 	return numLocks;
 }
 
-
 /*
  * RequestAddinLWLocks
  *		Request that extra LWLocks be allocated for use by
@@ -448,6 +549,30 @@ CreateLWLocks(void)
 		for (id = 0, lock = MainLWLockArray; id < numLocks; id++, lock++)
 			LWLockInitialize(&lock->lock, 0);
 
+		/* Initialized tranche id for buffer mapping lwlocks */
+		for (id = 0; id < NUM_BUFFER_PARTITIONS; id++)
+		{
+			LWLock *lock;
+			lock = &MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET + id].lock;
+			lock->tranche = LW_TRANCHE_BUFFER_MAPPING;
+		}
+
+		/* Initialized tranche id for lock manager lwlocks */
+		for (id = 0; id < NUM_LOCK_PARTITIONS; id++)
+		{
+			LWLock *lock;
+			lock = &MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + id].lock;
+			lock->tranche = LW_TRANCHE_LOCK_MANAGER;
+		}
+
+		/* Initialized tranche id for predicate lock manager lwlocks */
+		for (id = 0; id < NUM_PREDICATELOCK_PARTITIONS; id++)
+		{
+			LWLock *lock;
+			lock = &MainLWLockArray[PREDICATELOCK_MANAGER_LWLOCK_OFFSET + id].lock;
+			lock->tranche = LW_TRANCHE_PREDICATELOCK_MANAGER;
+		}
+
 		/*
 		 * Initialize the dynamic-allocation counters, which are stored just
 		 * before the first LWLock.  LWLockCounter[0] is the allocation
@@ -469,10 +594,18 @@ CreateLWLocks(void)
 						  LWLockTranchesAllocated * sizeof(LWLockTranche *));
 	}
 
-	MainLWLockTranche.name = "main";
-	MainLWLockTranche.array_base = MainLWLockArray;
-	MainLWLockTranche.array_stride = sizeof(LWLockPadded);
-	LWLockRegisterTranche(0, &MainLWLockTranche);
+	init_base_tranches();
+}
+
+/* LWLockGroupName - return name of LWLock by its groupId */
+const char *
+LWLockGroupName(int groupId)
+{
+	Assert(groupId != NUM_INDIVIDUAL_LWLOCKS);
+	if (groupId > NUM_INDIVIDUAL_LWLOCKS)
+		return LWLockTrancheArray[groupId - NUM_INDIVIDUAL_LWLOCKS]->name;
+	else
+		return LWLOCK_INDIVIDUAL_NAMES[groupId];
 }
 
 /*
@@ -495,7 +628,7 @@ InitLWLockAccess(void)
  * LWLocks after startup.
  */
 LWLock *
-LWLockAssign(void)
+LWLockAssign(int tranche_id)
 {
 	LWLock	   *result;
 	int		   *LWLockCounter;
@@ -508,11 +641,23 @@ LWLockAssign(void)
 		elog(ERROR, "no more LWLocks available");
 	}
 	result = &MainLWLockArray[LWLockCounter[0]++].lock;
+	result->tranche = tranche_id;
+
 	SpinLockRelease(ShmemLock);
 	return result;
 }
 
 /*
+ * LWLockUserAssign - assign a dynamically-allocated user defined
+ * LWLock number
+ */
+LWLock *
+LWLockUserAssign(void)
+{
+	return LWLockAssign(LW_TRANCHE_USERDEFINED);
+}
+
+/*
  * Allocate a new tranche ID.
  */
 int
@@ -572,6 +717,18 @@ LWLockInitialize(LWLock *lock, int tranche_id)
 }
 
 /*
+ * Report wait event for light-weight locks.
+ *
+ * This function will be used by all the light-weight lock calls which
+ * needs to wait to acquire the lock. 
+ */
+static inline void
+lwlock_report_stat(LWLock *lock)
+{
+	pgstat_report_wait_start(WAIT_LWLOCK, LWLOCK_GET_GROUP(lock));
+}
+
+/*
  * Internal function that tries to atomically acquire the lwlock in the passed
  * in mode.
  *
@@ -1037,6 +1194,9 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
 
 		TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock), mode);
 
+		/* Report the wait */
+		lwlock_report_stat(lock);
+
 		for (;;)
 		{
 			PGSemaphoreLock(&proc->sem);
@@ -1057,6 +1217,7 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
 		}
 #endif
 
+		pgstat_report_wait_end();
 		TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock), mode);
 
 		LOG_LWDEBUG("LWLockAcquire", lock, "awakened");
@@ -1199,6 +1360,9 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 #endif
 			TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock), mode);
 
+			/* Report the wait */
+			lwlock_report_stat(lock);
+
 			for (;;)
 			{
 				PGSemaphoreLock(&proc->sem);
@@ -1215,6 +1379,8 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 				Assert(nwaiters < MAX_BACKENDS);
 			}
 #endif
+
+			pgstat_report_wait_end();
 			TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock), mode);
 
 			LOG_LWDEBUG("LWLockAcquireOrWait", lock, "awakened");
@@ -1401,6 +1567,9 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 		TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock),
 										   LW_EXCLUSIVE);
 
+		/* Report the wait */
+		lwlock_report_stat(lock);
+
 		for (;;)
 		{
 			PGSemaphoreLock(&proc->sem);
@@ -1418,6 +1587,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 		}
 #endif
 
+		pgstat_report_wait_end();
 		TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock),
 										  LW_EXCLUSIVE);
 
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index bad5618..60eb4d4 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -795,7 +795,8 @@ OldSerXidInit(void)
 	 */
 	OldSerXidSlruCtl->PagePrecedes = OldSerXidPagePrecedesLogically;
 	SimpleLruInit(OldSerXidSlruCtl, "OldSerXid SLRU Ctl",
-				  NUM_OLDSERXID_BUFFERS, 0, OldSerXidLock, "pg_serial");
+				  NUM_OLDSERXID_BUFFERS, 0, OldSerXidLock, "pg_serial",
+				  LW_TRANCHE_OLDSERXID_BUFFERS);
 	/* Override default assumption that writes should be fsync'd */
 	OldSerXidSlruCtl->do_fsync = false;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 455ad26..b7d6c97 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -225,7 +225,7 @@ InitProcGlobal(void)
 		{
 			PGSemaphoreCreate(&(procs[i].sem));
 			InitSharedLatch(&(procs[i].procLatch));
-			procs[i].backendLock = LWLockAssign();
+			procs[i].backendLock = LWLockAssign(LW_TRANCHE_AUXILIARY_PROC);
 		}
 		procs[i].pgprocno = i;
 
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 42a43bb..71661d3 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -37,6 +37,7 @@
 #include "utils/hsearch.h"
 #include "utils/memutils.h"
 #include "pg_trace.h"
+#include "pgstat.h"
 
 
 /* intervals for calling AbsorbFsyncRequests in mdsync and mdpostckpt */
@@ -674,6 +675,8 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
 	int			nbytes;
 	MdfdVec    *v;
 
+	pgstat_report_wait_start(WAIT_IO, WAIT_IO_READ);
+
 	TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
 										reln->smgr_rnode.node.spcNode,
 										reln->smgr_rnode.node.dbNode,
@@ -702,6 +705,8 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
 									   nbytes,
 									   BLCKSZ);
 
+	pgstat_report_wait_end();
+
 	if (nbytes != BLCKSZ)
 	{
 		if (nbytes < 0)
@@ -749,6 +754,8 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
 	Assert(blocknum < mdnblocks(reln, forknum));
 #endif
 
+	pgstat_report_wait_start(WAIT_IO, WAIT_IO_WRITE);
+
 	TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
 										 reln->smgr_rnode.node.spcNode,
 										 reln->smgr_rnode.node.dbNode,
@@ -777,6 +784,8 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
 										nbytes,
 										BLCKSZ);
 
+	pgstat_report_wait_end();
+
 	if (nbytes != BLCKSZ)
 	{
 		if (nbytes < 0)
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index f7c9bf6..bb67850 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -530,7 +530,7 @@ pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	22
+#define PG_STAT_GET_ACTIVITY_COLS	23
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -617,28 +617,28 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			nulls[3] = true;
 
 		if (TransactionIdIsValid(local_beentry->backend_xid))
-			values[14] = TransactionIdGetDatum(local_beentry->backend_xid);
+			values[15] = TransactionIdGetDatum(local_beentry->backend_xid);
 		else
-			nulls[14] = true;
+			nulls[15] = true;
 
 		if (TransactionIdIsValid(local_beentry->backend_xmin))
-			values[15] = TransactionIdGetDatum(local_beentry->backend_xmin);
+			values[16] = TransactionIdGetDatum(local_beentry->backend_xmin);
 		else
-			nulls[15] = true;
+			nulls[16] = true;
 
 		if (beentry->st_ssl)
 		{
-			values[16] = BoolGetDatum(true);	/* ssl */
-			values[17] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
-			values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
-			values[19] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
-			values[20] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
-			values[21] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
+			values[17] = BoolGetDatum(true);	/* ssl */
+			values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
+			values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
+			values[20] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
+			values[21] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
+			values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
 		}
 		else
 		{
-			values[16] = BoolGetDatum(false);	/* ssl */
-			nulls[17] = nulls[18] = nulls[19] = nulls[20] = nulls[21] = true;
+			values[17] = BoolGetDatum(false);	/* ssl */
+			nulls[18] = nulls[19] = nulls[20] = nulls[21] = nulls[22] = true;
 		}
 
 		/* Values only available to role member */
@@ -674,34 +674,58 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			values[5] = CStringGetTextDatum(beentry->st_activity);
 			values[6] = BoolGetDatum(beentry->st_waiting);
 
-			if (beentry->st_xact_start_timestamp != 0)
-				values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
+			if (beentry->st_wait_data > 0)
+			{
+				/*
+				 * Reassigning of value is important, because st_wait_data
+				 * can change if we read class and event separately
+				 */
+
+				uint16 wait_data = beentry->st_wait_data;
+				uint8 classId = (uint8)(wait_data >> 8);
+				uint8 eventId = (uint8)wait_data;
+				const char *class_name = pgstat_get_wait_class_name(classId);
+				const char *event_name = pgstat_get_wait_event_name(classId,
+					eventId);
+
+				int size = strlen(class_name) + strlen(event_name) + 3;
+				char *wait_name = (char *)palloc(size);
+				snprintf(wait_name, size, "%s: %s", class_name, event_name);
+
+				values[7] = CStringGetTextDatum(wait_name);
+				pfree(wait_name);
+			}
 			else
 				nulls[7] = true;
 
-			if (beentry->st_activity_start_timestamp != 0)
-				values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
+			if (beentry->st_xact_start_timestamp != 0)
+				values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
 			else
 				nulls[8] = true;
 
-			if (beentry->st_proc_start_timestamp != 0)
-				values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
+			if (beentry->st_activity_start_timestamp != 0)
+				values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
 			else
 				nulls[9] = true;
 
-			if (beentry->st_state_start_timestamp != 0)
-				values[10] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
+			if (beentry->st_proc_start_timestamp != 0)
+				values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
 			else
 				nulls[10] = true;
 
+			if (beentry->st_state_start_timestamp != 0)
+				values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
+			else
+				nulls[11] = true;
+
 			/* A zeroed client addr means we don't know */
 			memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
 			if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
 					   sizeof(zero_clientaddr)) == 0)
 			{
-				nulls[11] = true;
 				nulls[12] = true;
 				nulls[13] = true;
+				nulls[14] = true;
 			}
 			else
 			{
@@ -725,20 +749,20 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 					if (ret == 0)
 					{
 						clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
-						values[11] = DirectFunctionCall1(inet_in,
+						values[12] = DirectFunctionCall1(inet_in,
 											   CStringGetDatum(remote_host));
 						if (beentry->st_clienthostname &&
 							beentry->st_clienthostname[0])
-							values[12] = CStringGetTextDatum(beentry->st_clienthostname);
+							values[13] = CStringGetTextDatum(beentry->st_clienthostname);
 						else
-							nulls[12] = true;
-						values[13] = Int32GetDatum(atoi(remote_port));
+							nulls[13] = true;
+						values[14] = Int32GetDatum(atoi(remote_port));
 					}
 					else
 					{
-						nulls[11] = true;
 						nulls[12] = true;
 						nulls[13] = true;
+						nulls[14] = true;
 					}
 				}
 				else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
@@ -749,16 +773,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 					 * connections we have no permissions to view, or with
 					 * errors.
 					 */
-					nulls[11] = true;
 					nulls[12] = true;
-					values[13] = DatumGetInt32(-1);
+					nulls[13] = true;
+					values[14] = DatumGetInt32(-1);
 				}
 				else
 				{
 					/* Unknown address type, should never happen */
-					nulls[11] = true;
 					nulls[12] = true;
 					nulls[13] = true;
+					nulls[14] = true;
 				}
 			}
 		}
@@ -775,6 +799,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			nulls[11] = true;
 			nulls[12] = true;
 			nulls[13] = true;
+			nulls[14] = true;
 		}
 
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index 9c7f019..c574e1e 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -136,7 +136,7 @@ typedef SlruCtlData *SlruCtl;
 
 extern Size SimpleLruShmemSize(int nslots, int nlsns);
 extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
-			  LWLock *ctllock, const char *subdir);
+			  LWLock *ctllock, const char *subdir, int lwlocktranche);
 extern int	SimpleLruZeroPage(SlruCtl ctl, int pageno);
 extern int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
 				  TransactionId xid);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 1d68ad7..05bc0af 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2777,7 +2777,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 f
 DESCR("statistics: number of auto analyzes for a table");
 DATA(insert OID = 1936 (  pg_stat_get_backend_idset		PGNSP PGUID 12 1 100 0 0 f f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ ));
 DESCR("statistics: currently active backend IDs");
-DATA(insert OID = 2022 (  pg_stat_get_activity			PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23,28,28,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ ));
+DATA(insert OID = 2022 (  pg_stat_get_activity			PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,25,1184,1184,1184,1184,869,25,23,28,28,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ ));
 DESCR("statistics: information about currently active backends");
 DATA(insert OID = 3099 (  pg_stat_get_wal_senders	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{23,25,3220,3220,3220,3220,23,25}" "{o,o,o,o,o,o,o,o}" "{pid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
 DESCR("statistics: information about currently active replication");
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9ecc163..a73e047 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -67,6 +67,33 @@ typedef enum StatMsgType
 } StatMsgType;
 
 /* ----------
+ * Wait definitions
+ * ----------
+ */
+
+typedef enum WAIT_CLASSES
+{
+	WAIT_UNDEFINED,
+	WAIT_LWLOCK,
+	WAIT_LOCK,
+	WAIT_IO,
+	WAIT_LATCH,
+	WAIT_NETWORK
+} WAIT_CLASSES;
+
+typedef enum WAIT_EVENTS_IO
+{
+	WAIT_IO_READ,
+	WAIT_IO_WRITE
+} WAIT_EVENTS_IO;
+
+typedef enum WAIT_EVENTS_NETWORK
+{
+	WAIT_NETWORK_READ,
+	WAIT_NETWORK_WRITE
+} WAIT_EVENT_NETWORK;
+
+/* ----------
  * The data type used for counters.
  * ----------
  */
@@ -768,6 +795,14 @@ typedef struct PgBackendStatus
 	/* Is backend currently waiting on an lmgr lock? */
 	bool		st_waiting;
 
+	/* Contains class end event of wait. It's in one
+	 * variable because we need read it atomically
+	 */
+	volatile uint16 st_wait_data;
+
+	/* keep track of nested waits, and skip them */
+	int             st_wait_nested;
+
 	/* current state */
 	BackendState st_state;
 
@@ -932,6 +967,12 @@ extern void pgstat_report_tempfile(size_t filesize);
 extern void pgstat_report_appname(const char *appname);
 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
 extern void pgstat_report_waiting(bool waiting);
+
+extern void pgstat_report_wait_start(uint8 classId, uint8 eventId);
+extern void pgstat_report_wait_end(void);
+extern const char *pgstat_get_wait_class_name(uint8 classId);
+extern const char *pgstat_get_wait_event_name(uint8 classId, uint8 eventId);
+
 extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 									int buflen);
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 96fe3a6..e05bea4 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -39,6 +39,9 @@ extern int	Trace_lock_table;
 extern bool Debug_deadlocks;
 #endif   /* LOCK_DEBUG */
 
+/* Contains names of all heavyweight locks */
+extern PGDLLIMPORT const char *LOCK_NAMES[];
+
 
 /*
  * Top-level transactions are identified by VirtualTransactionIDs comprising
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index cff3b99..ffd5525 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -87,6 +87,9 @@ typedef union LWLockPadded
 } LWLockPadded;
 extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
 
+/* Individual LWLocks names */
+extern const char *LWLOCK_INDIVIDUAL_NAMES[];
+
 /*
  * Some commonly-used locks have predefined positions within MainLWLockArray;
  * defining macros here makes it much easier to keep track of these.  If you
@@ -173,6 +176,31 @@ typedef enum LWLockMode
 								 * to be used as LWLockAcquire argument */
 } LWLockMode;
 
+typedef enum LWLockBaseTranche
+{
+	LW_TRANCHE_INDIVIDUAL,
+	LW_TRANCHE_BUFFER_MAPPING,
+	LW_TRANCHE_LOCK_MANAGER,
+	LW_TRANCHE_PREDICATELOCK_MANAGER,
+	LW_TRANCHE_BUFFER_MANAGER,
+	LW_TRANCHE_AUXILIARY_PROC,
+	LW_TRANCHE_CLOG_BUFFERS,
+	LW_TRANCHE_COMMITTS_BUFFERS,
+	LW_TRANCHE_SUBTRANS_BUFFERS,
+	LW_TRANCHE_MULTIXACT_BUFFERS,
+	LW_TRANCHE_ASYNC_BUFFERS,
+	LW_TRANCHE_OLDSERXID_BUFFERS,
+	LW_TRANCHE_REPLICATIONSLOT,
+	LW_TRANCHE_USERDEFINED,
+} LWLockBaseTranche;
+
+/*
+ * Group for individual lwlocks equal to their index in main array,
+ * other LWLocks identified by their tranche number
+ */
+
+#define LWLOCK_GET_GROUP(lock) \
+	((lock)->tranche>0? NUM_INDIVIDUAL_LWLOCKS + (lock)->tranche : T_ID(lock))
 
 #ifdef LOCK_DEBUG
 extern bool Trace_lwlocks;
@@ -192,6 +220,7 @@ extern void LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 value);
 extern Size LWLockShmemSize(void);
 extern void CreateLWLocks(void);
 extern void InitLWLockAccess(void);
+extern const char *LWLockGroupName(int groupId);
 
 /*
  * The traditional method for obtaining an lwlock for use by an extension is
@@ -200,7 +229,10 @@ extern void InitLWLockAccess(void);
  * a lock can be allocated using LWLockAssign.
  */
 extern void RequestAddinLWLocks(int n);
-extern LWLock *LWLockAssign(void);
+extern LWLock *LWLockAssign(int tranche_id);
+
+/* Allocates LWLock in UserDefinedLocks tranche */
+extern LWLock *LWLockUserAssign(void);
 
 /*
  * There is another, more flexible method of obtaining lwlocks. First, call
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index cd53375..1bafb75 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1647,12 +1647,13 @@ pg_stat_activity| SELECT s.datid,
     s.query_start,
     s.state_change,
     s.waiting,
+    s.wait_event,
     s.state,
     s.backend_xid,
     s.backend_xmin,
     s.query
    FROM pg_database d,
-    pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn),
+    pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn),
     pg_authid u
   WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1758,7 +1759,7 @@ pg_stat_replication| SELECT s.pid,
     w.replay_location,
     w.sync_priority,
     w.sync_state
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn),
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn),
     pg_authid u,
     pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state)
   WHERE ((s.usesysid = u.oid) AND (s.pid = w.pid));
@@ -1769,7 +1770,7 @@ pg_stat_ssl| SELECT s.pid,
     s.sslbits AS bits,
     s.sslcompression AS compression,
     s.sslclientdn AS clientdn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn);
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn);
 pg_stat_sys_indexes| SELECT pg_stat_all_indexes.relid,
     pg_stat_all_indexes.indexrelid,
     pg_stat_all_indexes.schemaname,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to