Hi,
This patch set tries to add loongarch64 native spin lock to postgresql.
- [PATCH 1/2] implements a loongarch64 native spin lock.
- [PATCH 2/2] fixes s_lock_test to make it runnable via `make check'.
The patch set is tested on my Loongson 3A5000 machine with Loong Arch
Linux and GCC 13.1.0 with default ./configure with no options.
Output of `make check' in src/backend/storage/lmgr is attached.
See:
[1]:
https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#atomic-memory-access-instructions
[2]:
https://github.com/torvalds/linux/blob/f1fcbaa18b28dec10281551dfe6ed3a3ed80e3d6/arch/loongarch/include/asm/cmpxchg.h#L12
----
YANG Xudong
From fe4fb3c9b8027a3e9664e8e99ac78dec4c4ef83d Mon Sep 17 00:00:00 2001
From: YANG Xudong <yangxud...@ymatrix.cn>
Date: Wed, 17 May 2023 16:21:45 +0800
Subject: [PATCH 1/2] Implement loongarch64 native spinlock with TAS.
---
src/include/storage/s_lock.h | 39 ++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index c9fa84cc43..3656595270 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -596,6 +596,45 @@ tas(volatile slock_t *lock)
#endif /* __hppa || __hppa__ */
+#if defined(__loongarch__) && defined(__linux__) /* loongarch64 */
+
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ /*
+ * The following implementation is based on the implementation of
cmpxchg
+ * in linux kernel source code tree.
+ * See: arch/loongarch/include/asm/cmpxchg.h in linux for more details.
+ */
+ register slock_t _res = 1;
+
+ __asm__ __volatile__ ( \
+ " amswap_db.w %1, %z2, %0 \n" \
+ : "+ZB" (*lock), "=&r" (_res) \
+ : "Jr" (_res) \
+ : "memory");
+
+ return (int) _res;
+}
+
+#define SPIN_DELAY() spin_delay()
+
+static __inline__ void
+spin_delay(void)
+{
+ __asm__ __volatile__(
+ " nop \n");
+}
+
+#endif /* __loongarch__ */
+
+
/*
* If we have no platform-specific knowledge, but we found that the compiler
* provides __sync_lock_test_and_set(), use that. Prefer the int-width
--
2.40.1
From 1e5d6ed9b54c264d539c84ead7513845ad1349ed Mon Sep 17 00:00:00 2001
From: YANG Xudong <yangxud...@ymatrix.cn>
Date: Wed, 17 May 2023 16:22:06 +0800
Subject: [PATCH 2/2] Make s_lock_test work.
---
src/backend/storage/lmgr/Makefile | 2 +-
src/backend/storage/lmgr/s_lock.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/backend/storage/lmgr/Makefile
b/src/backend/storage/lmgr/Makefile
index b25b7ee421..3b04561d6f 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -33,7 +33,7 @@ endif
s_lock_test: s_lock.c $(top_builddir)/src/common/libpgcommon.a
$(top_builddir)/src/port/libpgport.a
$(CC) $(CPPFLAGS) $(CFLAGS) -DS_LOCK_TEST=1 $(srcdir)/s_lock.c \
$(TASPATH) -L $(top_builddir)/src/common -lpgcommon \
- -L $(top_builddir)/src/port -lpgport -o s_lock_test
+ -L $(top_builddir)/src/port -lpgport -lm -o s_lock_test
# see notes in src/backend/parser/Makefile
lwlocknames.c: lwlocknames.h
diff --git a/src/backend/storage/lmgr/s_lock.c
b/src/backend/storage/lmgr/s_lock.c
index 327ac64f7c..1d674840b4 100644
--- a/src/backend/storage/lmgr/s_lock.c
+++ b/src/backend/storage/lmgr/s_lock.c
@@ -145,9 +145,13 @@ perform_spin_delay(SpinDelayStatus *status)
* We might want to report something more granular at some
point, but
* this is better than nothing.
*/
+#if !defined(S_LOCK_TEST)
pgstat_report_wait_start(WAIT_EVENT_SPIN_DELAY);
+#endif
pg_usleep(status->cur_delay);
+#if !defined(S_LOCK_TEST)
pgstat_report_wait_end();
+#endif
#if defined(S_LOCK_TEST)
fprintf(stdout, "*");
--
2.40.1
make -C ../../../../src/backend generated-headers
make[1]: Entering directory '/home/yxd/playspace/postgres/src/backend'
make -C catalog distprep generated-header-symlinks
make[2]: Entering directory '/home/yxd/playspace/postgres/src/backend/catalog'
make[2]: Nothing to be done for 'distprep'.
make[2]: Nothing to be done for 'generated-header-symlinks'.
make[2]: Leaving directory '/home/yxd/playspace/postgres/src/backend/catalog'
make -C nodes distprep generated-header-symlinks
make[2]: Entering directory '/home/yxd/playspace/postgres/src/backend/nodes'
make[2]: Nothing to be done for 'distprep'.
make[2]: Nothing to be done for 'generated-header-symlinks'.
make[2]: Leaving directory '/home/yxd/playspace/postgres/src/backend/nodes'
make -C utils distprep generated-header-symlinks
make[2]: Entering directory '/home/yxd/playspace/postgres/src/backend/utils'
make[2]: Nothing to be done for 'distprep'.
make[2]: Nothing to be done for 'generated-header-symlinks'.
make[2]: Leaving directory '/home/yxd/playspace/postgres/src/backend/utils'
make[1]: Leaving directory '/home/yxd/playspace/postgres/src/backend'
rm -rf '/home/yxd/playspace/postgres'/tmp_install
/usr/bin/mkdir -p '/home/yxd/playspace/postgres'/tmp_install/log
make -C '../../../..' DESTDIR='/home/yxd/playspace/postgres'/tmp_install
install >'/home/yxd/playspace/postgres'/tmp_install/log/install.log 2>&1
make -j1 checkprep
>>'/home/yxd/playspace/postgres'/tmp_install/log/install.log 2>&1
./s_lock_test
S_LOCK_TEST: this will print 1000 stars and then
exit with a 'stuck spinlock' message
if S_LOCK() and TAS() are working.
****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
Stuck spinlock detected at main, ./s_lock.c:322.
make: *** [Makefile:46: check] Error 1