diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
new file mode 100755
index 1c41428..699b0ec
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
*************** SyncOneBuffer(int buf_id, bool skip_rece
*** 1665,1671 ****
  	 */
  	LockBufHdr(bufHdr);
  
! 	if (bufHdr->refcount == 0 && bufHdr->usage_count == 0)
  		result |= BUF_REUSABLE;
  	else if (skip_recently_used)
  	{
--- 1665,1671 ----
  	 */
  	LockBufHdr(bufHdr);
  
! 	if (bufHdr->refcount == 0 && bufHdr->usage_count <= 0)
  		result |= BUF_REUSABLE;
  	else if (skip_recently_used)
  	{
diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
new file mode 100755
index c76aaf7..a081069
*** a/src/backend/storage/buffer/freelist.c
--- b/src/backend/storage/buffer/freelist.c
*************** typedef struct
*** 28,34 ****
  	int			nextVictimBuffer;
  
  	int			firstFreeBuffer;	/* Head of list of unused buffers */
! 	int			lastFreeBuffer; /* Tail of list of unused buffers */
  
  	/*
  	 * NOTE: lastFreeBuffer is undefined when firstFreeBuffer is -1 (that is,
--- 28,35 ----
  	int			nextVictimBuffer;
  
  	int			firstFreeBuffer;	/* Head of list of unused buffers */
! 	int			lastFreeBuffer;		 /* Tail of list of unused buffers */
! 	slock_t			mutex;			/* Protects all of these, except sometimes not nextVictimBuffer */
  
  	/*
  	 * NOTE: lastFreeBuffer is undefined when firstFreeBuffer is -1 (that is,
*************** typedef struct
*** 49,55 ****
  } BufferStrategyControl;
  
  /* Pointers to shared state */
! static BufferStrategyControl *StrategyControl = NULL;
  
  /*
   * Private (non-shared) state for managing a ring of shared buffers to re-use.
--- 50,56 ----
  } BufferStrategyControl;
  
  /* Pointers to shared state */
! static volatile BufferStrategyControl *StrategyControl = NULL;
  
  /*
   * Private (non-shared) state for managing a ring of shared buffers to re-use.
*************** static void AddBufferToRing(BufferAccess
*** 101,112 ****
   *	strategy is a BufferAccessStrategy object, or NULL for default strategy.
   *
   *	To ensure that no one else can pin the buffer before we do, we must
!  *	return the buffer with the buffer header spinlock still held.  If
!  *	*lock_held is set on exit, we have returned with the BufFreelistLock
!  *	still held, as well; the caller must release that lock once the spinlock
!  *	is dropped.  We do it that way because releasing the BufFreelistLock
!  *	might awaken other processes, and it would be bad to do the associated
!  *	kernel calls while holding the buffer header spinlock.
   */
  volatile BufferDesc *
  StrategyGetBuffer(BufferAccessStrategy strategy, bool *lock_held)
--- 102,113 ----
   *	strategy is a BufferAccessStrategy object, or NULL for default strategy.
   *
   *	To ensure that no one else can pin the buffer before we do, we must
!  *	return the buffer with the buffer header spinlock still held.  To avoid
!  *  excessive spinning during the clock sweep loop on highly contended
!  *  buffers, the buffer header lock is aquired without spinning.  Also, all
!  *  manipulation of usage_count is done without holding the buffer header
!  *  spinlock on the basis that it advisory; this avoids excessive cache line
!  *  locking while sweeping.
   */
  volatile BufferDesc *
  StrategyGetBuffer(BufferAccessStrategy strategy, bool *lock_held)
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 114,119 ****
--- 115,121 ----
  	volatile BufferDesc *buf;
  	Latch	   *bgwriterLatch;
  	int			trycounter;
+ 	*lock_held = false;
  
  	/*
  	 * If given a strategy object, see whether it can select a buffer. We
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 124,143 ****
  		buf = GetBufferFromRing(strategy);
  		if (buf != NULL)
  		{
- 			*lock_held = false;
  			return buf;
  		}
  	}
  
- 	/* Nope, so lock the freelist */
- 	*lock_held = true;
- 	LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
- 
  	/*
  	 * We count buffer allocation requests so that the bgwriter can estimate
  	 * the rate of buffer consumption.	Note that buffers recycled by a
  	 * strategy object are intentionally not counted here.
  	 */
  	StrategyControl->numBufferAllocs++;
  
  	/*
--- 126,142 ----
  		buf = GetBufferFromRing(strategy);
  		if (buf != NULL)
  		{
  			return buf;
  		}
  	}
  
  	/*
  	 * We count buffer allocation requests so that the bgwriter can estimate
  	 * the rate of buffer consumption.	Note that buffers recycled by a
  	 * strategy object are intentionally not counted here.
+ 	 * This is now done without a lock, and so updates can be lost
  	 */
+ 
  	StrategyControl->numBufferAllocs++;
  
  	/*
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 150,158 ****
  	if (bgwriterLatch)
  	{
  		StrategyControl->bgwriterLatch = NULL;
- 		LWLockRelease(BufFreelistLock);
  		SetLatch(bgwriterLatch);
- 		LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
  	}
  
  	/*
--- 149,155 ----
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 163,168 ****
--- 160,171 ----
  	 */
  	while (StrategyControl->firstFreeBuffer >= 0)
  	{
+ 		SpinLockAcquire(&StrategyControl->mutex);
+ 		if (StrategyControl->firstFreeBuffer<0)
+ 		{
+ 			SpinLockRelease(&StrategyControl->mutex);
+ 			break;
+ 		}
  		buf = &BufferDescriptors[StrategyControl->firstFreeBuffer];
  		Assert(buf->freeNext != FREENEXT_NOT_IN_LIST);
  
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 170,175 ****
--- 173,180 ----
  		StrategyControl->firstFreeBuffer = buf->freeNext;
  		buf->freeNext = FREENEXT_NOT_IN_LIST;
  
+ 		SpinLockRelease(&StrategyControl->mutex);
+ 
  		/*
  		 * If the buffer is pinned or has a nonzero usage_count, we cannot use
  		 * it; discard it and retry.  (This can only happen if VACUUM put a
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 178,184 ****
  		 * we'd better check anyway.)
  		 */
  		LockBufHdr(buf);
! 		if (buf->refcount == 0 && buf->usage_count == 0)
  		{
  			if (strategy != NULL)
  				AddBufferToRing(strategy, buf);
--- 183,189 ----
  		 * we'd better check anyway.)
  		 */
  		LockBufHdr(buf);
! 		if (buf->refcount == 0 && buf->usage_count <= 0)
  		{
  			if (strategy != NULL)
  				AddBufferToRing(strategy, buf);
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 191,209 ****
  	trycounter = NBuffers;
  	for (;;)
  	{
! 		buf = &BufferDescriptors[StrategyControl->nextVictimBuffer];
  
  		if (++StrategyControl->nextVictimBuffer >= NBuffers)
  		{
! 			StrategyControl->nextVictimBuffer = 0;
! 			StrategyControl->completePasses++;
  		}
  
  		/*
  		 * If the buffer is pinned or has a nonzero usage_count, we cannot use
  		 * it; decrement the usage_count (unless pinned) and keep scanning.
  		 */
- 		LockBufHdr(buf);
  		if (buf->refcount == 0)
  		{
  			if (buf->usage_count > 0)
--- 196,222 ----
  	trycounter = NBuffers;
  	for (;;)
  	{
! 
! 		int localVictim=StrategyControl->nextVictimBuffer;
! 		if (localVictim >= NBuffers) localVictim=0;
! 
! 		buf = &BufferDescriptors[localVictim];
  
  		if (++StrategyControl->nextVictimBuffer >= NBuffers)
  		{
! 			SpinLockAcquire(&StrategyControl->mutex);
! 			if (StrategyControl->nextVictimBuffer >= NBuffers)
! 			{
! 				StrategyControl->nextVictimBuffer = 0;
! 				StrategyControl->completePasses++;
! 			};
! 			SpinLockRelease(&StrategyControl->mutex);
  		}
  
  		/*
  		 * If the buffer is pinned or has a nonzero usage_count, we cannot use
  		 * it; decrement the usage_count (unless pinned) and keep scanning.
  		 */
  		if (buf->refcount == 0)
  		{
  			if (buf->usage_count > 0)
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 213,222 ****
  			}
  			else
  			{
! 				/* Found a usable buffer */
! 				if (strategy != NULL)
! 					AddBufferToRing(strategy, buf);
! 				return buf;
  			}
  		}
  		else if (--trycounter == 0)
--- 226,238 ----
  			}
  			else
  			{
! 				/* Found a usable buffer.  But is it truly unpinned? */
! 				if (TryLockBufHdr(buf))
! 				{
! 					if (strategy != NULL)
! 						AddBufferToRing(strategy, buf);
! 					return buf;
! 				}
  			}
  		}
  		else if (--trycounter == 0)
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 228,237 ****
  			 * probably better to fail than to risk getting stuck in an
  			 * infinite loop.
  			 */
- 			UnlockBufHdr(buf);
  			elog(ERROR, "no unpinned buffers available");
  		}
- 		UnlockBufHdr(buf);
  	}
  }
  
--- 244,251 ----
*************** StrategyGetBuffer(BufferAccessStrategy s
*** 241,247 ****
  void
  StrategyFreeBuffer(volatile BufferDesc *buf)
  {
! 	LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
  
  	/*
  	 * It is possible that we are told to put something in the freelist that
--- 255,261 ----
  void
  StrategyFreeBuffer(volatile BufferDesc *buf)
  {
! 	SpinLockAcquire(&StrategyControl->mutex);
  
  	/*
  	 * It is possible that we are told to put something in the freelist that
*************** StrategyFreeBuffer(volatile BufferDesc *
*** 255,261 ****
  		StrategyControl->firstFreeBuffer = buf->buf_id;
  	}
  
! 	LWLockRelease(BufFreelistLock);
  }
  
  /*
--- 269,275 ----
  		StrategyControl->firstFreeBuffer = buf->buf_id;
  	}
  
! 	SpinLockRelease(&StrategyControl->mutex);
  }
  
  /*
*************** StrategySyncStart(uint32 *complete_passe
*** 274,281 ****
  {
  	int			result;
  
! 	LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
  	result = StrategyControl->nextVictimBuffer;
  	if (complete_passes)
  		*complete_passes = StrategyControl->completePasses;
  	if (num_buf_alloc)
--- 288,296 ----
  {
  	int			result;
  
! 	SpinLockAcquire(&StrategyControl->mutex);
  	result = StrategyControl->nextVictimBuffer;
+ 	if (result >= NBuffers) result=0;
  	if (complete_passes)
  		*complete_passes = StrategyControl->completePasses;
  	if (num_buf_alloc)
*************** StrategySyncStart(uint32 *complete_passe
*** 283,289 ****
  		*num_buf_alloc = StrategyControl->numBufferAllocs;
  		StrategyControl->numBufferAllocs = 0;
  	}
! 	LWLockRelease(BufFreelistLock);
  	return result;
  }
  
--- 298,304 ----
  		*num_buf_alloc = StrategyControl->numBufferAllocs;
  		StrategyControl->numBufferAllocs = 0;
  	}
! 	SpinLockRelease(&StrategyControl->mutex);
  	return result;
  }
  
*************** StrategyInitialize(bool init)
*** 376,381 ****
--- 391,397 ----
  		 */
  		StrategyControl->firstFreeBuffer = 0;
  		StrategyControl->lastFreeBuffer = NBuffers - 1;
+ 		SpinLockInit(&StrategyControl->mutex);
  
  		/* Initialize the clock sweep pointer */
  		StrategyControl->nextVictimBuffer = 0;
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
new file mode 100755
index f0e5144..943215c
*** a/src/include/storage/buf_internals.h
--- b/src/include/storage/buf_internals.h
*************** typedef struct sbufdesc
*** 168,173 ****
--- 168,174 ----
   */
  #define LockBufHdr(bufHdr)		SpinLockAcquire(&(bufHdr)->buf_hdr_lock)
  #define UnlockBufHdr(bufHdr)	SpinLockRelease(&(bufHdr)->buf_hdr_lock)
+ #define TryLockBufHdr(bufHdr)	TrySpinLockAcquire(&(bufHdr)->buf_hdr_lock)
  
  
  /* in buf_init.c */
diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h
new file mode 100755
index f459b90..909ecd5
*** a/src/include/storage/spin.h
--- b/src/include/storage/spin.h
***************
*** 63,68 ****
--- 63,70 ----
  
  #define SpinLockAcquire(lock) S_LOCK(lock)
  
+ #define TrySpinLockAcquire(lock) !(TAS_SPIN(lock))
+ 
  #define SpinLockRelease(lock) S_UNLOCK(lock)
  
  #define SpinLockFree(lock)	S_LOCK_FREE(lock)
