experimental_linux_pthread_mutex_instead_of_spinlick.patch

text/plain

Filename: experimental_linux_pthread_mutex_instead_of_spinlick.patch
Type: text/plain
Part: 0
Message: experimental: replace s_lock spinlock code with pthread_mutex on linux

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/storage/lmgr/s_lock.c 89 0
src/include/storage/s_lock.h 29 2
diff --git a/src/backend/storage/lmgr/s_lock.c b/src/backend/storage/lmgr/s_lock.c
index bc8d89f..a45fdf6 100644
--- a/src/backend/storage/lmgr/s_lock.c
+++ b/src/backend/storage/lmgr/s_lock.c
@@ -20,6 +20,8 @@
 
 #include "storage/s_lock.h"
 
+#ifndef USE_PTHREAD_SLOCK
+
 slock_t		dummy_spinlock;
 
 static int	spins_per_delay = DEFAULT_SPINS_PER_DELAY;
@@ -200,9 +202,95 @@ update_spins_per_delay(int shared_spins_per_delay)
  * because the definitions for these are split between this file and s_lock.h.
  */
 
+#endif /* !USE_PTHREAD_SLOCK */
 
 #ifdef HAVE_SPINLOCKS			/* skip spinlocks if requested */
 
+#ifdef USE_PTHREAD_SLOCK
+#include <pthread.h>
+void
+posix_lock(volatile slock_t *lock, const char *file, int line)
+{
+	struct slock *s_lock = (slock_t *)lock;
+	int ret;
+
+	/* XXX error recovery ! */
+
+	do {
+		ret = pthread_mutex_lock(&s_lock->mutex);
+	} while (ret != 0);
+	s_lock->held = 1;
+}
+
+void
+posix_unlock(volatile slock_t *lock, const char *file, int line)
+{
+	struct slock *s_lock = (slock_t *)lock;
+	int ret;
+
+	/* XXX error recovery ! */
+
+	s_lock->held = 0;
+	do {
+		ret = pthread_mutex_unlock(&s_lock->mutex);
+	} while (ret != 0);
+}
+
+void
+posix_init(volatile slock_t *lock)
+{
+	struct slock *s_lock = (slock_t *)lock;
+	pthread_mutexattr_t attr;
+	int ret;
+
+	ret = pthread_mutexattr_init(&attr);
+	Assert(ret == 0);
+
+#ifdef PTHREAD_MUTEX_ADAPTIVE_NP
+	(void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
+#else
+	(void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+#endif
+
+#ifdef USE_PRIO_INHERIT
+	/*
+	 * looks like this incurs significant syscall overhead on linux
+	 */
+	(void)pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+#endif
+
+	ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+	Assert(ret == 0);
+
+	s_lock->held = 0;
+
+	ret = pthread_mutex_init(&s_lock->mutex, &attr);
+	Assert(ret == 0);
+
+	pthread_mutexattr_destroy(&attr);
+}
+
+int
+posix_lock_free(volatile slock_t *lock)
+{
+	struct slock *s_lock = (slock_t *)lock;
+
+	return (s_lock->held == 0);
+}
+
+#if 0
+void
+posix_lock_free(slock_t *lock)
+{
+	struct slock *s_lock = lock;
+	int ret;
+
+	ret = pthread_mutex_destroy(&s_lock->mutex);
+	Assert(ret == 0);
+}
+#endif
+
+#else /* !USE_PTHREAD_SLOCK */
 
 #if defined(__GNUC__)
 
@@ -282,6 +370,7 @@ tas_dummy()						/* really means: extern int tas(slock_t
 }
 #endif   /* sun3 */
 #endif   /* not __GNUC__ */
+#endif   /* USE_PTHREAD_SLOCK */
 #endif   /* HAVE_SPINLOCKS */
 
 
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index d4a783f..200af8f 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -97,6 +97,30 @@
 
 #ifdef HAVE_SPINLOCKS	/* skip spinlocks if requested */
 
+#ifdef USE_PTHREAD_SLOCK
+#include <pthread.h>
+struct slock {
+	pthread_mutex_t		mutex;
+	int			held;
+};
+
+typedef struct slock slock_t;
+
+extern void posix_lock(volatile slock_t *lock, const char *file, int line);
+extern void posix_unlock(volatile slock_t *lock, const char *file, int line);
+extern void posix_init(volatile slock_t *lock);
+extern int posix_lock_free(volatile slock_t *lock);
+
+#define S_LOCK(lock)		posix_lock((lock), __FILE__, __LINE__)
+#define S_UNLOCK(lock)		posix_unlock((lock), __FILE__, __LINE__)
+#define S_INIT_LOCK(lock)	posix_init(lock)
+#define S_LOCK_FREE(lock)	posix_lock_free(lock)
+#define SPIN_DELAY()		((void) 0)
+
+#define set_spins_per_delay(s)		((void) 0)
+#define update_spins_per_delay(s)	(0)
+#define DEFAULT_SPINS_PER_DELAY		0
+#else /* !USE_PTHREAD_SLOCK */
 
 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
 /*************************************************************************
@@ -947,7 +971,7 @@ spin_delay(void)
 #error PostgreSQL does not have native spinlock support on this platform.  To continue the compilation, rerun configure using --disable-spinlocks.  However, performance will be poor.  Please report this to pgsql-bugs@postgresql.org.
 #endif
 
-
+#endif  /* USE_PTHREAD_SLOCK */
 #else	/* !HAVE_SPINLOCKS */
 
 
@@ -968,7 +992,6 @@ extern int	tas_sema(volatile slock_t *lock);
 #define S_INIT_LOCK(lock)	s_init_lock_sema(lock)
 #define TAS(lock)	tas_sema(lock)
 
-
 #endif	/* HAVE_SPINLOCKS */
 
 
@@ -996,6 +1019,8 @@ extern int	tas_sema(volatile slock_t *lock);
 #define S_INIT_LOCK(lock)	S_UNLOCK(lock)
 #endif	 /* S_INIT_LOCK */
 
+#ifndef USE_PTHREAD_SLOCK
+
 #if !defined(SPIN_DELAY)
 #define SPIN_DELAY()	((void) 0)
 #endif	 /* SPIN_DELAY */
@@ -1004,6 +1029,7 @@ extern int	tas_sema(volatile slock_t *lock);
 extern int	tas(volatile slock_t *lock);		/* in port/.../tas.s, or
 												 * s_lock.c */
 
+
 #define TAS(lock)		tas(lock)
 #endif	 /* TAS */
 
@@ -1022,5 +1048,6 @@ extern void s_lock(volatile slock_t *lock, const char *file, int line);
 
 extern void set_spins_per_delay(int shared_spins_per_delay);
 extern int	update_spins_per_delay(int shared_spins_per_delay);
+#endif /* !USE_PTHREAD_SLOCK */
 
 #endif	 /* S_LOCK_H */