diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 9673fe0..ade38d4 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -109,6 +109,9 @@ static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
 
 #define JUMBLE_SIZE				1024	/* query serialization buffer size */
 
+#define NUM_LWLOCKS				1		/* number of lwlocks required by this
+										 * module */
+
 /*
  * Extension version number, for supporting older extension versions' objects
  */
@@ -404,7 +407,7 @@ _PG_init(void)
 	 * resources in pgss_shmem_startup().
 	 */
 	RequestAddinShmemSpace(pgss_memsize());
-	RequestAddinLWLocks(1);
+	RequestAddinLWLockTranche("pg_stat_statements locks", NUM_LWLOCKS);
 
 	/*
 	 * Install hooks.
@@ -479,8 +482,14 @@ pgss_shmem_startup(void)
 
 	if (!found)
 	{
+		LWLockPadded *RequestedLockArray;
+		int			lwlock_count = 0;
+
 		/* First time through ... */
-		pgss->lock = LWLockAssign();
+		RequestedLockArray = GetLWLockAddinTranche("pg_stat_statements locks");
+		pgss->lock = &RequestedLockArray[lwlock_count++].lock;
+		/* can't assign more than requested number of lwlocks */
+		Assert(lwlock_count <= NUM_LWLOCKS);
 		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 1186d9c..aa7ac82 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3335,9 +3335,14 @@ void RequestAddinShmemSpace(int size)
     <para>
      LWLocks are reserved by calling:
 <programlisting>
-void RequestAddinLWLocks(int n)
+  void RequestAddinLWLockTranche(const char *tranche_name, int num_lwlocks)
 </programlisting>
-     from <function>_PG_init</>.
+     from <function>_PG_init</>.  Tranche repersents an array of LWLocks and
+     can be accessed by it's name.  First parameter <literal>tranche_name</>
+     repersents the name of tranche which will be used to repersent the
+     LWLocks of Add-in from which this function will be called.  Second
+     parameter <literal>num_lwlocks</> repersents the number of LWLocks that
+     needs to be allocated from this tranche.
     </para>
     <para>
      To avoid possible race-conditions, each backend should use the LWLock
@@ -3354,9 +3359,16 @@ if (!ptr)
         ptr = ShmemInitStruct("my struct name", size, &amp;found);
         if (!found)
         {
+                LWLockPadded *RequestedLockArray;
+                int          lwlock_count = 0;
+
                 initialize contents of shmem area;
                 acquire any requested LWLocks using:
-                ptr->mylockid = LWLockAssign();
+                RequestedLockArray = GetLWLockAddinTranche("pg_stat_statements locks");
+                ptr->mylockid = &amp;RequestedLockArray[lwlock_count++].lock;
+  
+                after allocating LWLocks, verify that the number of allocated
+                LWLocks is same as requested;
         }
         LWLockRelease(AddinShmemInitLock);
 }
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 27e3745..189e073 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -481,6 +481,8 @@ typedef struct
 #ifndef HAVE_SPINLOCKS
 	PGSemaphore SpinlockSemaArray;
 #endif
+	int			LWLockTrancheRequestsCount;
+	LWLockAddInTranche *LWLockAddInTrancheArray;
 	LWLockPadded *MainLWLockArray;
 	slock_t    *ProcStructLock;
 	PROC_HDR   *ProcGlobal;
@@ -5772,6 +5774,8 @@ save_backend_variables(BackendParameters *param, Port *port,
 #ifndef HAVE_SPINLOCKS
 	param->SpinlockSemaArray = SpinlockSemaArray;
 #endif
+	param->LWLockTrancheRequestsCount = LWLockTrancheRequestsCount;
+	param->LWLockAddInTrancheArray = LWLockAddInTrancheArray;
 	param->MainLWLockArray = MainLWLockArray;
 	param->ProcStructLock = ProcStructLock;
 	param->ProcGlobal = ProcGlobal;
@@ -6003,6 +6007,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
 #ifndef HAVE_SPINLOCKS
 	SpinlockSemaArray = param->SpinlockSemaArray;
 #endif
+	LWLockTrancheRequestsCount = param->LWLockTrancheRequestsCount;
+	LWLockAddInTrancheArray = param->LWLockAddInTrancheArray;
 	MainLWLockArray = param->MainLWLockArray;
 	ProcStructLock = param->ProcStructLock;
 	ProcGlobal = param->ProcGlobal;
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 36a04fc..053e5aa 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -125,6 +125,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 		size = add_size(size, BackgroundWorkerShmemSize());
 		size = add_size(size, MultiXactShmemSize());
 		size = add_size(size, LWLockShmemSize());
+		size = add_size(size, LWLockAddInTrancheShmemSize());
 		size = add_size(size, ProcArrayShmemSize());
 		size = add_size(size, BackendStatusShmemSize());
 		size = add_size(size, SInvalShmemSize());
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index ac61be2..b7e969d 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -144,7 +144,19 @@ typedef struct LWLockHandle
 static int	num_held_lwlocks = 0;
 static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS];
 
-static int	lock_addin_request = 0;
+/* struct representing the LWLock tranche request by loadable module */
+typedef struct LWLockTrancheRequest
+{
+	char		tranche_name[NAMEDATALEN];
+	int			num_lwlocks;
+} LWLockTrancheRequest;
+
+LWLockTrancheRequest *LWLockTrancheRequestArray = NULL;
+static int	LWLockTrancheRequestsAllocated = 0;
+int			LWLockTrancheRequestsCount = 0;
+
+LWLockAddInTranche *LWLockAddInTrancheArray = NULL;
+
 static bool lock_addin_request_allowed = true;
 
 #ifdef LWLOCK_STATS
@@ -336,6 +348,22 @@ get_lwlock_stats_entry(LWLock *lock)
 
 
 /*
+ * Compute number of LWLocks required by loadable modules to be allocated
+ * in the main array.
+ */
+static int
+NumLWLocksByLoadableModules(void)
+{
+	int			numLocks = 0;
+	int			i;
+
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+		numLocks += LWLockTrancheRequestArray[i].num_lwlocks;
+
+	return numLocks;
+}
+
+/*
  * Compute number of LWLocks to allocate in the main array.
  */
 static int
@@ -359,38 +387,12 @@ NumLWLocks(void)
 	/* slot.c needs one for each slot */
 	numLocks += max_replication_slots;
 
-	/*
-	 * Add any requested by loadable modules; for backwards-compatibility
-	 * reasons, allocate at least NUM_USER_DEFINED_LWLOCKS of them even if
-	 * there are no explicit requests.
-	 */
+	/* Disallow LWLocks' requests for use by extensions after startup */
 	lock_addin_request_allowed = false;
-	numLocks += Max(lock_addin_request, NUM_USER_DEFINED_LWLOCKS);
 
 	return numLocks;
 }
 
-
-/*
- * RequestAddinLWLocks
- *		Request that extra LWLocks be allocated for use by
- *		a loadable module.
- *
- * This is only useful if called from the _PG_init hook of a library that
- * is loaded into the postmaster via shared_preload_libraries.  Once
- * shared memory has been allocated, calls will be ignored.  (We could
- * raise an error, but it seems better to make it a no-op, so that
- * libraries containing such calls can be reloaded if needed.)
- */
-void
-RequestAddinLWLocks(int n)
-{
-	if (IsUnderPostmaster || !lock_addin_request_allowed)
-		return;					/* too late */
-	lock_addin_request += n;
-}
-
-
 /*
  * Compute shmem space needed for LWLocks.
  */
@@ -400,6 +402,8 @@ LWLockShmemSize(void)
 	Size		size;
 	int			numLocks = NumLWLocks();
 
+	numLocks += NumLWLocksByLoadableModules();
+
 	/* Space for the LWLock array. */
 	size = mul_size(numLocks, sizeof(LWLockPadded));
 
@@ -409,6 +413,24 @@ LWLockShmemSize(void)
 	return size;
 }
 
+/*
+ * Compute shmem space needed for tranches requested by loadable modules.
+ */
+Size
+LWLockAddInTrancheShmemSize(void)
+{
+	Size		size;
+	int			i;
+
+	/* space for tranches requested by extensions. */
+	size = mul_size(LWLockTrancheRequestsCount, sizeof(LWLockAddInTranche));
+
+	/* space for name of each tranche. */
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+		size = add_size(size, strlen(LWLockTrancheRequestArray[i].tranche_name) + 1);
+
+	return size;
+}
 
 /*
  * Allocate shmem space for the main LWLock array and initialize it.  We also
@@ -417,6 +439,8 @@ LWLockShmemSize(void)
 void
 CreateLWLocks(void)
 {
+	int			i;
+
 	StaticAssertExpr(LW_VAL_EXCLUSIVE > (uint32) MAX_BACKENDS,
 					 "MAX_BACKENDS too big for lwlock.c");
 
@@ -432,6 +456,7 @@ CreateLWLocks(void)
 		int		   *LWLockCounter;
 		char	   *ptr;
 		int			id;
+		int			j;
 
 		/* Allocate space */
 		ptr = (char *) ShmemAlloc(spaceLocks);
@@ -444,7 +469,7 @@ CreateLWLocks(void)
 
 		MainLWLockArray = (LWLockPadded *) ptr;
 
-		/* Initialize all LWLocks in main array */
+		/* Initialize all fixed LWLocks in main array */
 		for (id = 0, lock = MainLWLockArray; id < numLocks; id++, lock++)
 			LWLockInitialize(&lock->lock, LWTRANCHE_MAIN);
 
@@ -459,6 +484,57 @@ CreateLWLocks(void)
 		LWLockCounter[0] = NUM_FIXED_LWLOCKS;
 		LWLockCounter[1] = numLocks;
 		LWLockCounter[2] = LWTRANCHE_FIRST_USER_DEFINED;
+
+		/* Allocate and initialize separate tranche for each loadable module. */
+		if (LWLockTrancheRequestsCount > 0)
+		{
+			Size		spaceTranche = LWLockAddInTrancheShmemSize();
+			char	   *ptr;
+			char	   *trancheNames;
+
+			ptr = (char *) ShmemAlloc(spaceTranche);
+
+			LWLockAddInTrancheArray = (LWLockAddInTranche *) ptr;
+
+			trancheNames = (char *) LWLockAddInTrancheArray + (LWLockTrancheRequestsCount * sizeof(LWLockAddInTranche));
+
+			/*
+			 * Ensure tranche names point to the shared memory location
+			 * allocated for them.
+			 */
+			i = 0;
+			do
+			{
+				LWLockAddInTrancheArray[i].lwLockTranche.name = (char *) trancheNames;
+				trancheNames += strlen(LWLockTrancheRequestArray[i].tranche_name) + 1;
+			} while (++i < LWLockTrancheRequestsCount);
+
+			/* Initialize the tranches requested by loadable modules. */
+			i = 0;
+			lock = MainLWLockArray + numLocks;
+			do
+			{
+				LWLockAddInTrancheArray[i].trancheId = LWLockNewTrancheId();
+				StrNCpy((char *) LWLockAddInTrancheArray[i].lwLockTranche.name,
+						LWLockTrancheRequestArray[i].tranche_name,
+					  strlen(LWLockTrancheRequestArray[i].tranche_name) + 1);
+				LWLockAddInTrancheArray[i].lwLockTranche.array_base = lock;
+				LWLockAddInTrancheArray[i].lwLockTranche.array_stride = sizeof(LWLockPadded);
+
+				lock += LWLockTrancheRequestArray[i].num_lwlocks;
+			} while (++i < LWLockTrancheRequestsCount);
+
+			/*
+			 * Initialize the LWLocks in the main array that belong to
+			 * loadable modules.
+			 */
+			lock = MainLWLockArray + numLocks;
+			for (i = 0; i < LWLockTrancheRequestsCount; i++)
+			{
+				for (j = 0; j < LWLockTrancheRequestArray[i].num_lwlocks; j++, lock++)
+					LWLockInitialize(&lock->lock, LWLockAddInTrancheArray[i].trancheId);
+			}
+		}
 	}
 
 	if (LWLockTrancheArray == NULL)
@@ -474,6 +550,11 @@ CreateLWLocks(void)
 	MainLWLockTranche.array_base = MainLWLockArray;
 	MainLWLockTranche.array_stride = sizeof(LWLockPadded);
 	LWLockRegisterTranche(LWTRANCHE_MAIN, &MainLWLockTranche);
+
+	/* Register separate tranche for loadable modules. */
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+		LWLockRegisterTranche(LWLockAddInTrancheArray[i].trancheId,
+							  &LWLockAddInTrancheArray[i].lwLockTranche);
 }
 
 /*
@@ -514,6 +595,49 @@ LWLockAssign(void)
 }
 
 /*
+ * GetLWLockAddinTranche - returns the base address of LWLock from the
+ *		specified tranche.
+ *
+ * Caller needs to retrieve the requested number of LWLocks starting from
+ * the base lock address returned by this API.  This can be used for
+ * tranches that are requested by using RequestAddinLWLockTranche() API.
+ */
+LWLockPadded *
+GetLWLockAddinTranche(const char *tranche_name)
+{
+	int			lock_pos;
+	int			i,
+				j;
+	LWLockTrancheRequest *request_tranche;
+	int		   *LWLockCounter;
+
+	LWLockCounter = (int *) ((char *) MainLWLockArray - 3 * sizeof(int));
+
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+	{
+		if (strcmp(tranche_name, LWLockTrancheRequestArray[i].tranche_name) == 0)
+		{
+			request_tranche = &LWLockTrancheRequestArray[i];
+			break;
+		}
+	}
+
+	if (i >= LWLockTrancheRequestsCount)
+		elog(ERROR, "requested tranche is not registered");
+
+	/*
+	 * Obtain the position of base address of LWLock belonging to this tranche
+	 * in MainLWLockArray.  LWLocks for loadable modules tranche are placed in
+	 * MainLWLockArray after LWLocks specified by LWLockCounter[1].
+	 */
+	lock_pos = LWLockCounter[1];
+	for (j = 0; j < i; j++)
+		lock_pos += LWLockTrancheRequestArray[j].num_lwlocks;
+
+	return &MainLWLockArray[lock_pos];
+}
+
+/*
  * Allocate a new tranche ID.
  */
 int
@@ -558,6 +682,48 @@ LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
 }
 
 /*
+ * RequestAddinLWLockTranche
+ *		Request that extra LWLocks be allocated for use by
+ *		a loadable module.
+ *
+ * This is only useful if called from the _PG_init hook of a library that
+ * is loaded into the postmaster via shared_preload_libraries.  Once
+ * shared memory has been allocated, calls will be ignored.  (We could
+ * raise an error, but it seems better to make it a no-op, so that
+ * libraries containing such calls can be reloaded if needed.)
+ */
+void
+RequestAddinLWLockTranche(const char *tranche_name, int num_lwlocks)
+{
+	if (IsUnderPostmaster || !lock_addin_request_allowed)
+		return;					/* too late */
+
+	if (LWLockTrancheRequestArray == NULL)
+	{
+		LWLockTrancheRequestsAllocated = 16;
+		LWLockTrancheRequestArray = (LWLockTrancheRequest *)
+			MemoryContextAlloc(TopMemoryContext,
+			  LWLockTrancheRequestsAllocated * sizeof(LWLockTrancheRequest));
+	}
+
+	if (LWLockTrancheRequestsCount >= LWLockTrancheRequestsAllocated)
+	{
+		int			i = LWLockTrancheRequestsAllocated;
+
+		while (i <= LWLockTrancheRequestsCount)
+			i *= 2;
+
+		LWLockTrancheRequestArray = (LWLockTrancheRequest *)
+			repalloc(LWLockTrancheRequestArray,
+					 i * sizeof(LWLockTrancheRequest));
+		LWLockTrancheRequestsAllocated = i;
+	}
+
+	StrNCpy(LWLockTrancheRequestArray[LWLockTrancheRequestsCount].tranche_name, tranche_name, strlen(tranche_name) + 1);
+	LWLockTrancheRequestArray[LWLockTrancheRequestsCount++].num_lwlocks = num_lwlocks;
+}
+
+/*
  * LWLockInitialize - initialize a new lwlock; it's initially unlocked
  */
 void
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index 383809b..ef89521 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -52,11 +52,6 @@
 #define SEQ_MINVALUE	(-SEQ_MAXVALUE)
 
 /*
- * Number of spare LWLocks to allocate for user-defined add-on code.
- */
-#define NUM_USER_DEFINED_LWLOCKS	4
-
-/*
  * When we don't have native spinlocks, we use semaphores to simulate them.
  * Decreasing this value reduces consumption of OS resources; increasing it
  * may improve performance, but supplying a real spinlock implementation is
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 5e8825e..5860700 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -119,6 +119,16 @@ typedef union LWLockMinimallyPadded
 extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
 extern char *MainLWLockNames[];
 
+/* struct for storing tranche information of loadable modules (extensions) */
+typedef struct LWLockAddInTranche
+{
+	LWLockTranche lwLockTranche;
+	int			trancheId;
+} LWLockAddInTranche;
+
+extern PGDLLIMPORT LWLockAddInTranche *LWLockAddInTrancheArray;
+extern PGDLLIMPORT int LWLockTrancheRequestsCount;
+
 /* Names for fixed lwlocks */
 #include "storage/lwlocknames.h"
 
@@ -178,12 +188,16 @@ extern void CreateLWLocks(void);
 extern void InitLWLockAccess(void);
 
 /*
- * The traditional method for obtaining an lwlock for use by an extension is
- * to call RequestAddinLWLocks() during postmaster startup; this will reserve
+ * The method for obtaining an lwlock for use by an extension is to call
+ * RequestAddinLWLockTranche() during postmaster startup; this will reserve
  * space for the indicated number of locks in MainLWLockArray.  Subsequently,
- * a lock can be allocated using LWLockAssign.
+ * the base address for lwlocks can be obtained using GetLWLockAddinTranche()
+ * and from there it can allocate the requested number of lwlocks.
  */
-extern void RequestAddinLWLocks(int n);
+extern void RequestAddinLWLockTranche(const char *tranche_name, int num_lwlocks);
+extern LWLockPadded *GetLWLockAddinTranche(const char *tranche_name);
+extern Size LWLockAddInTrancheShmemSize(void);
+
 extern LWLock *LWLockAssign(void);
 
 /*
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 963d865..1f48229 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1008,10 +1008,12 @@ LSEG
 LVRelStats
 LWLock
 LWLockHandle
+LWLockAddInTranche
 LWLockMinimallyPadded
 LWLockMode
 LWLockPadded
 LWLockTranche
+LWLockTrancheRequest
 LabelProvider
 LargeObjectDesc
 Latch
