diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
new file mode 100644
index 2ebd4a9..32c0209
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
*************** PinBuffer(BufferDesc *buf, BufferAccessS
*** 1503,1540 ****
  
  	if (ref == NULL)
  	{
! 		uint32 state;
! 		uint32 oldstate;
  
  		ReservePrivateRefCountEntry();
  		ref = NewPrivateRefCountEntry(b);
  
- 
  		state = pg_atomic_read_u32(&buf->state);
! 		oldstate = state;
! 
! 		while (true)
! 		{
! 			/* spin-wait till lock is free */
! 			while (state & BM_LOCKED)
! 			{
! 				pg_spin_delay();
! 				state = pg_atomic_read_u32(&buf->state);
! 				oldstate = state;
! 			}
! 
! 			/* increase refcount */
! 			state += BUF_REFCOUNT_ONE;
! 
! 			/* increase usagecount unless already max */
! 			if (BUF_STATE_GET_USAGECOUNT(state) != BM_MAX_USAGE_COUNT)
! 				state += BUF_USAGECOUNT_ONE;
  
! 			if (pg_atomic_compare_exchange_u32(&buf->state, &oldstate, state))
! 				break;
  
! 			/* get ready for next loop, oldstate has been updated by cas */
! 			state = oldstate;
  		}
  		result = (state & BM_VALID) != 0;
  	}
--- 1503,1524 ----
  
  	if (ref == NULL)
  	{
! 		uint32	state,
! 				increment = 1;
  
  		ReservePrivateRefCountEntry();
  		ref = NewPrivateRefCountEntry(b);
  
  		state = pg_atomic_read_u32(&buf->state);
! 		if (BUF_STATE_GET_USAGECOUNT(state) < BM_MAX_USAGE_COUNT)
! 			increment += BUF_USAGECOUNT_ONE;
  
! 		state = pg_atomic_add_fetch_u32(&buf->state, increment);
  
! 		while (state & BM_LOCKED)
! 		{
! 			pg_spin_delay();
! 			state = pg_atomic_read_u32(&buf->state);
  		}
  		result = (state & BM_VALID) != 0;
  	}
*************** UnpinBuffer(BufferDesc *buf, bool fixOwn
*** 1632,1638 ****
  		 * currently all manipulation of ->state for shared buffers is through
  		 * atomics.
  		 */
! 		state = pg_atomic_fetch_sub_u32(&buf->state, BUF_REFCOUNT_ONE);
  		Assert(BUF_STATE_GET_REFCOUNT(state) > 0);
  
  		/* Support LockBufferForCleanup() */
--- 1616,1622 ----
  		 * currently all manipulation of ->state for shared buffers is through
  		 * atomics.
  		 */
! 		state = pg_atomic_fetch_sub_u32(&buf->state, 1);
  		Assert(BUF_STATE_GET_REFCOUNT(state) > 0);
  
  		/* Support LockBufferForCleanup() */
diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
new file mode 100644
index 8b64855..9331f21
*** a/src/backend/storage/buffer/freelist.c
--- b/src/backend/storage/buffer/freelist.c
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 314,320 ****
  		{
  			if (BUF_STATE_GET_USAGECOUNT(state) != 0)
  			{
! 				pg_atomic_fetch_sub_u32(&buf->state, BUF_USAGECOUNT_ONE);
  
  				trycounter = NBuffers;
  			}
--- 314,324 ----
  		{
  			if (BUF_STATE_GET_USAGECOUNT(state) != 0)
  			{
! 				if (BUF_STATE_GET_USAGECOUNT(state) > BM_MAX_USAGE_COUNT)
! 					pg_atomic_fetch_sub_u32(&buf->state,
! 						BUF_USAGECOUNT_ONE * (BM_MAX_USAGE_COUNT - BUF_STATE_GET_USAGECOUNT(state) + 1));
! 				else
! 					pg_atomic_fetch_sub_u32(&buf->state, BUF_USAGECOUNT_ONE);
  
  				trycounter = NBuffers;
  			}
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
new file mode 100644
index 3d3e0d5..bc61f19
*** a/src/include/storage/buf_internals.h
--- b/src/include/storage/buf_internals.h
***************
*** 31,44 ****
   * 4 bit usage count
   * 18 bit refcount
   */
! #define BUF_REFCOUNT_ONE 1
! #define BUF_REFCOUNT_MASK ((1U << 18) - 1)
  #define BUF_STATE_GET_REFCOUNT(state) ((state) & BUF_REFCOUNT_MASK)
- #define BUF_USAGECOUNT_MASK 0x003C0000U
- #define BUF_USAGECOUNT_ONE (1U << 18)
- #define BUF_USAGECOUNT_SHIFT 18
  #define BUF_STATE_GET_USAGECOUNT(state) (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)
- #define BUF_FLAG_MASK 0xFFC00000U
  
  /*
   * Flags for buffer descriptors
--- 31,43 ----
   * 4 bit usage count
   * 18 bit refcount
   */
! #define BUF_REFCOUNT_MASK ((1U << 16) - 1)
! #define BUF_FLAG_MASK 0x3FF0000U
! #define BUF_USAGECOUNT_MASK 0xFC000000U
! #define BUF_USAGECOUNT_ONE (1U << 26)
! #define BUF_USAGECOUNT_SHIFT 26
  #define BUF_STATE_GET_REFCOUNT(state) ((state) & BUF_REFCOUNT_MASK)
  #define BUF_STATE_GET_USAGECOUNT(state) (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)
  
  /*
   * Flags for buffer descriptors
***************
*** 46,61 ****
   * Note: TAG_VALID essentially means that there is a buffer hashtable
   * entry associated with the buffer's tag.
   */
! #define BM_LOCKED				(1U << 22)		/* buffer header is locked */
! #define BM_DIRTY				(1U << 23)		/* data needs writing */
! #define BM_VALID				(1U << 24)		/* data is valid */
! #define BM_TAG_VALID			(1U << 25)		/* tag is assigned */
! #define BM_IO_IN_PROGRESS		(1U << 26)		/* read or write in progress */
! #define BM_IO_ERROR				(1U << 27)		/* previous I/O failed */
! #define BM_JUST_DIRTIED			(1U << 28)		/* dirtied since write started */
! #define BM_PIN_COUNT_WAITER		(1U << 29)		/* have waiter for sole pin */
! #define BM_CHECKPOINT_NEEDED	(1U << 30)		/* must write for checkpoint */
! #define BM_PERMANENT			(1U << 31)		/* permanent relation (not
  												 * unlogged) */
  /*
   * The maximum allowed value of usage_count represents a tradeoff between
--- 45,60 ----
   * Note: TAG_VALID essentially means that there is a buffer hashtable
   * entry associated with the buffer's tag.
   */
! #define BM_LOCKED				(1U << 16)		/* buffer header is locked */
! #define BM_DIRTY				(1U << 17)		/* data needs writing */
! #define BM_VALID				(1U << 18)		/* data is valid */
! #define BM_TAG_VALID			(1U << 19)		/* tag is assigned */
! #define BM_IO_IN_PROGRESS		(1U << 20)		/* read or write in progress */
! #define BM_IO_ERROR				(1U << 21)		/* previous I/O failed */
! #define BM_JUST_DIRTIED			(1U << 22)		/* dirtied since write started */
! #define BM_PIN_COUNT_WAITER		(1U << 23)		/* have waiter for sole pin */
! #define BM_CHECKPOINT_NEEDED	(1U << 24)		/* must write for checkpoint */
! #define BM_PERMANENT			(1U << 25)		/* permanent relation (not
  												 * unlogged) */
  /*
   * The maximum allowed value of usage_count represents a tradeoff between
