I wrote:
> So at this point I'm not sure what to do.  I could back out the back-patch
> of 44cd47c1d49655c5, which would mean accepting that 9.2/9.3 are broken
> and will never be fixed for HPPA, as well as any other architectures that
> use the same fallback memory barrier implementation.  The lack of
> complaints from the field suggests that nobody would care.  Or I could
> push forward by back-patching daa7527afc227443 (and a couple of minor
> follow-on cleanups).  That doesn't seem particularly risky, now that
> 9.4's been out for awhile, but it's kind of a large back-patch to benefit
> architectures that apparently no actual users care about.

I went ahead and prepared and tested such a patch; the version for 9.3
is attached.  (9.2 is identical modulo some pgindent-induced whitespace
difference.)  This doesn't look too hazardous to me, so I'm thinking
we should apply it.

                        regards, tom lane

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3808836..fc4abbc 100644
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
*************** typedef struct
*** 500,505 ****
--- 500,508 ----
  	slock_t    *ShmemLock;
  	VariableCache ShmemVariableCache;
  	Backend    *ShmemBackendArray;
+ #ifndef HAVE_SPINLOCKS
+ 	PGSemaphore	SpinlockSemaArray;
+ #endif
  	LWLock	   *LWLockArray;
  	slock_t    *ProcStructLock;
  	PROC_HDR   *ProcGlobal;
*************** save_backend_variables(BackendParameters
*** 6050,6055 ****
--- 6053,6061 ----
  	param->ShmemVariableCache = ShmemVariableCache;
  	param->ShmemBackendArray = ShmemBackendArray;
  
+ #ifndef HAVE_SPINLOCKS
+ 	param->SpinlockSemaArray = SpinlockSemaArray;
+ #endif
  	param->LWLockArray = LWLockArray;
  	param->ProcStructLock = ProcStructLock;
  	param->ProcGlobal = ProcGlobal;
*************** restore_backend_variables(BackendParamet
*** 6278,6283 ****
--- 6284,6292 ----
  	ShmemVariableCache = param->ShmemVariableCache;
  	ShmemBackendArray = param->ShmemBackendArray;
  
+ #ifndef HAVE_SPINLOCKS
+ 	SpinlockSemaArray = param->SpinlockSemaArray;
+ #endif
  	LWLockArray = param->LWLockArray;
  	ProcStructLock = param->ProcStructLock;
  	ProcGlobal = param->ProcGlobal;
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 918ac51..ec8e4f6 100644
*** a/src/backend/storage/ipc/ipci.c
--- b/src/backend/storage/ipc/ipci.c
*************** CreateSharedMemoryAndSemaphores(bool mak
*** 103,108 ****
--- 103,109 ----
  		 * need to be so careful during the actual allocation phase.
  		 */
  		size = 100000;
+ 		size = add_size(size, SpinlockSemaSize());
  		size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
  												 sizeof(ShmemIndexEnt)));
  		size = add_size(size, BufferShmemSize());
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 129d9f8..4194db6 100644
*** a/src/backend/storage/ipc/shmem.c
--- b/src/backend/storage/ipc/shmem.c
*************** InitShmemAllocation(void)
*** 116,124 ****
  	Assert(shmhdr != NULL);
  
  	/*
! 	 * Initialize the spinlock used by ShmemAlloc.  We have to do the space
! 	 * allocation the hard way, since obviously ShmemAlloc can't be called
! 	 * yet.
  	 */
  	ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset);
  	shmhdr->freeoffset += MAXALIGN(sizeof(slock_t));
--- 116,139 ----
  	Assert(shmhdr != NULL);
  
  	/*
! 	 * If spinlocks are disabled, initialize emulation layer.  We have to do
! 	 * the space allocation the hard way, since obviously ShmemAlloc can't be
! 	 * called yet.
! 	 */
! #ifndef HAVE_SPINLOCKS
! 	{
! 		PGSemaphore spinsemas;
! 
! 		spinsemas = (PGSemaphore) (((char *) shmhdr) + shmhdr->freeoffset);
! 		shmhdr->freeoffset += MAXALIGN(SpinlockSemaSize());
! 		SpinlockSemaInit(spinsemas);
! 		Assert(shmhdr->freeoffset <= shmhdr->totalsize);
! 	}
! #endif
! 
! 	/*
! 	 * Initialize the spinlock used by ShmemAlloc; we have to do this the hard
! 	 * way, too, for the same reasons as above.
  	 */
  	ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset);
  	shmhdr->freeoffset += MAXALIGN(sizeof(slock_t));
diff --git a/src/backend/storage/lmgr/spin.c b/src/backend/storage/lmgr/spin.c
index 2864790..874e313 100644
*** a/src/backend/storage/lmgr/spin.c
--- b/src/backend/storage/lmgr/spin.c
***************
*** 25,33 ****
--- 25,48 ----
  #include "miscadmin.h"
  #include "replication/walsender.h"
  #include "storage/lwlock.h"
+ #include "storage/pg_sema.h"
  #include "storage/spin.h"
  
  
+ #ifndef HAVE_SPINLOCKS
+ PGSemaphore SpinlockSemaArray;
+ #endif
+ 
+ /*
+  * Report the amount of shared memory needed to store semaphores for spinlock
+  * support.
+  */
+ Size
+ SpinlockSemaSize(void)
+ {
+ 	return SpinlockSemas() * sizeof(PGSemaphoreData);
+ }
+ 
  #ifdef HAVE_SPINLOCKS
  
  /*
*************** SpinlockSemas(void)
*** 51,71 ****
  int
  SpinlockSemas(void)
  {
! 	int			nsemas;
  
! 	/*
! 	 * It would be cleaner to distribute this logic into the affected modules,
! 	 * similar to the way shmem space estimation is handled.
! 	 *
! 	 * For now, though, there are few enough users of spinlocks that we just
! 	 * keep the knowledge here.
! 	 */
! 	nsemas = NumLWLocks();		/* one for each lwlock */
! 	nsemas += NBuffers;			/* one for each buffer header */
! 	nsemas += max_wal_senders;	/* one for each wal sender process */
! 	nsemas += 30;				/* plus a bunch for other small-scale use */
  
! 	return nsemas;
  }
  
  /*
--- 66,85 ----
  int
  SpinlockSemas(void)
  {
! 	return NUM_SPINLOCK_SEMAPHORES;
! }
  
! /*
!  * Initialize semaphores.
!  */
! extern void
! SpinlockSemaInit(PGSemaphore spinsemas)
! {
! 	int			i;
  
! 	for (i = 0; i < NUM_SPINLOCK_SEMAPHORES; ++i)
! 		PGSemaphoreCreate(&spinsemas[i]);
! 	SpinlockSemaArray = spinsemas;
  }
  
  /*
*************** SpinlockSemas(void)
*** 75,87 ****
  void
  s_init_lock_sema(volatile slock_t *lock)
  {
! 	PGSemaphoreCreate((PGSemaphore) lock);
  }
  
  void
  s_unlock_sema(volatile slock_t *lock)
  {
! 	PGSemaphoreUnlock((PGSemaphore) lock);
  }
  
  bool
--- 89,103 ----
  void
  s_init_lock_sema(volatile slock_t *lock)
  {
! 	static int	counter = 0;
! 
! 	*lock = (++counter) % NUM_SPINLOCK_SEMAPHORES;
  }
  
  void
  s_unlock_sema(volatile slock_t *lock)
  {
! 	PGSemaphoreUnlock(&SpinlockSemaArray[*lock]);
  }
  
  bool
*************** int
*** 96,102 ****
  tas_sema(volatile slock_t *lock)
  {
  	/* Note that TAS macros return 0 if *success* */
! 	return !PGSemaphoreTryLock((PGSemaphore) lock);
  }
  
  #endif   /* !HAVE_SPINLOCKS */
--- 112,118 ----
  tas_sema(volatile slock_t *lock)
  {
  	/* Note that TAS macros return 0 if *success* */
! 	return !PGSemaphoreTryLock(&SpinlockSemaArray[*lock]);
  }
  
  #endif   /* !HAVE_SPINLOCKS */
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index 24c5069..74d7ba2 100644
*** a/src/include/pg_config_manual.h
--- b/src/include/pg_config_manual.h
***************
*** 57,62 ****
--- 57,70 ----
  #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
+  * probably far better.
+  */
+ #define	NUM_SPINLOCK_SEMAPHORES		1024
+ 
+ /*
   * Define this if you want to allow the lo_import and lo_export SQL
   * functions to be executed by ordinary users.  By default these
   * functions are only available to the Postgres superuser.  CAUTION:
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index f869cb0..b2605f9 100644
*** a/src/include/storage/s_lock.h
--- b/src/include/storage/s_lock.h
***************
*** 94,104 ****
  #ifndef S_LOCK_H
  #define S_LOCK_H
  
- #include "storage/pg_sema.h"
- 
  #ifdef HAVE_SPINLOCKS	/* skip spinlocks if requested */
  
- 
  #if defined(__GNUC__) || defined(__INTEL_COMPILER)
  /*************************************************************************
   * All the gcc inlines
--- 94,101 ----
*************** spin_delay(void)
*** 1032,1038 ****
   * to fall foul of kernel limits on number of semaphores, so don't use this
   * unless you must!  The subroutines appear in spin.c.
   */
! typedef PGSemaphoreData slock_t;
  
  extern bool s_lock_free_sema(volatile slock_t *lock);
  extern void s_unlock_sema(volatile slock_t *lock);
--- 1029,1035 ----
   * to fall foul of kernel limits on number of semaphores, so don't use this
   * unless you must!  The subroutines appear in spin.c.
   */
! typedef int slock_t;
  
  extern bool s_lock_free_sema(volatile slock_t *lock);
  extern void s_unlock_sema(volatile slock_t *lock);
diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h
index f459b90..b2b1339 100644
*** a/src/include/storage/spin.h
--- b/src/include/storage/spin.h
***************
*** 57,62 ****
--- 57,65 ----
  #define SPIN_H
  
  #include "storage/s_lock.h"
+ #ifndef HAVE_SPINLOCKS
+ #include "storage/pg_sema.h"
+ #endif
  
  
  #define SpinLockInit(lock)	S_INIT_LOCK(lock)
***************
*** 69,73 ****
--- 72,82 ----
  
  
  extern int	SpinlockSemas(void);
+ extern Size SpinlockSemaSize(void);
+ 
+ #ifndef HAVE_SPINLOCKS
+ extern void SpinlockSemaInit(PGSemaphore);
+ extern PGSemaphore SpinlockSemaArray;
+ #endif
  
  #endif   /* SPIN_H */
-- 
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