On Mon, Dec 15, 2025 at 05:32:36PM -0500, Andres Freund wrote:
> On 2025-12-15 15:38:49 -0600, Nathan Bossart wrote:
>> - if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd
>> without -march=armv8-a+crc',
>> + if (host_cpu == 'aarch64' and cc.get_id() == 'msvc') or \
>> + cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and
>> __crc32cd without -march=armv8-a+crc',
>> args: test_c_args)
>> # Use ARM CRC Extension unconditionally
>> cdata.set('USE_ARMV8_CRC32C', 1)
>
> I still think this should have a comment explaining that we can
> unconditionally rely on crc32 support due to window's baseline requirements.
Done.
>> +#ifdef _M_ARM64
>> +static __forceinline void
>> +spin_delay(void)
>> +{
>> + /* Research indicates ISB is better than __yield() on AArch64. */
>> + __isb(_ARM64_BARRIER_SY);
>
> It'd be good to link the research in some form or another. Otherwise it's
> harder to evolve the code in the future, because we don't know if the research
> was "I liked the color better" or "one is catastrophically slower than the
> other".
Done.
>> #include <intrin.h>
>> +#ifdef _M_ARM64
>> +#pragma intrinsic(_InterlockedExchange)
>> +
>> +/* _ReadWriteBarrier() is insufficient on non-TSO architectures. */
>> +#define S_UNLOCK(lock) _InterlockedExchange(lock, 0)
>> +#else
>> #pragma intrinsic(_ReadWriteBarrier)
>>
>> #define S_UNLOCK(lock) \
>> do { _ReadWriteBarrier(); (*(lock)) = 0; } while (0)
>>
>> #endif
>> +#endif
>
> The newline placement looks odd here. I'd add newlines around the #else.
Done.
--
nathan
>From 6c421307ddcd519718a35acc7e2952ea055feeb5 Mon Sep 17 00:00:00 2001
From: Dave Cramer <[email protected]>
Date: Sun, 13 Jul 2025 06:33:17 -0400
Subject: [PATCH v11 1/1] Enable the Microsoft Windows ARM64/MSVC platform
Add support for the ARM64 architecture on Windows 11 using MSVC compiler
addressing build issues and implementing proper memory synchronization
semantics for this platform.
* Implement spin_delay() with __isb(_ARM64_BARRIER_SY) intrinsic to emit
the "ISB SY" instruction which matches the GCC/Clang approach to
spinloop delay and emperical evidence that it out-scales the YIELD
instruction in practice.
* Unconditionally choose to use the MSVC supplied intrinsic
for CRC32 on ARM64.
* Implement the S_UNLOCK() macro using the InterlockedExchange()
intrinsic on ARM64.
Author: Greg Burd <[email protected]>
Author: Dave Cramer <[email protected]>
Discussion:
https://postgr.es/m/3c576ad7-d2da-4137-b791-5821da7cc370%40app.fastmail.com
---
doc/src/sgml/installation.sgml | 3 ++-
meson.build | 6 +++++-
src/include/storage/s_lock.h | 30 +++++++++++++++++++++++++-----
src/port/pg_crc32c_armv8.c | 4 ++++
src/tools/msvc_gendef.pl | 8 ++++----
5 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index fe8d73e1f8c..c903ccff988 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3967,7 +3967,8 @@ configure ... LDFLAGS="-R
/usr/sfw/lib:/opt/sfw/lib:/usr/local/lib"
<sect3 id="install-windows-full-64-bit">
<title>Special Considerations for 64-Bit Windows</title>
<para>
- PostgreSQL will only build for the x64 architecture on 64-bit Windows.
+ PostgreSQL will only build for the x64 and AArch64 architectures on 64-bit
+ Windows.
</para>
<para>
Mixing 32- and 64-bit versions in the same build tree is not supported.
diff --git a/meson.build b/meson.build
index d7c5193d4ce..d521e13690c 100644
--- a/meson.build
+++ b/meson.build
@@ -2523,7 +2523,11 @@ int main(void)
}
'''
- if cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd
without -march=armv8-a+crc',
+ # Vendor-supported versions of Windows for AArch64 require at least ARMv8.1,
+ # which is where CRC extension support became mandatory. Thus, use it
+ # unconditionally on MSVC/AArch64.
+ if (host_cpu == 'aarch64' and cc.get_id() == 'msvc') or \
+ cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd
without -march=armv8-a+crc',
args: test_c_args)
# Use ARM CRC Extension unconditionally
cdata.set('USE_ARMV8_CRC32C', 1)
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 7f8f566bd40..20badae8e41 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -602,13 +602,24 @@ typedef LONG slock_t;
#define SPIN_DELAY() spin_delay()
-/* If using Visual C++ on Win64, inline assembly is unavailable.
- * Use a _mm_pause intrinsic instead of rep nop.
- */
-#if defined(_WIN64)
+#ifdef _M_ARM64
+static __forceinline void
+spin_delay(void)
+{
+ /*
+ * Research indicates ISB is better than __yield() on AArch64. See
+ *
https://postgr.es/m/1c2a29b8-5b1e-44f7-a871-71ec5fefc120%40app.fastmail.com.
+ */
+ __isb(_ARM64_BARRIER_SY);
+}
+#elif defined(_WIN64)
static __forceinline void
spin_delay(void)
{
+ /*
+ * If using Visual C++ on Win64, inline assembly is unavailable.
+ * Use a _mm_pause intrinsic instead of rep nop.
+ */
_mm_pause();
}
#else
@@ -621,12 +632,21 @@ spin_delay(void)
#endif
#include <intrin.h>
-#pragma intrinsic(_ReadWriteBarrier)
+#ifdef _M_ARM64
+
+/* _ReadWriteBarrier() is insufficient on non-TSO architectures. */
+#pragma intrinsic(_InterlockedExchange)
+#define S_UNLOCK(lock) _InterlockedExchange(lock, 0)
+
+#else
+
+#pragma intrinsic(_ReadWriteBarrier)
#define S_UNLOCK(lock) \
do { _ReadWriteBarrier(); (*(lock)) = 0; } while (0)
#endif
+#endif
#endif /* !defined(HAS_TEST_AND_SET) */
diff --git a/src/port/pg_crc32c_armv8.c b/src/port/pg_crc32c_armv8.c
index 5ba070bb99d..e49b383b26a 100644
--- a/src/port/pg_crc32c_armv8.c
+++ b/src/port/pg_crc32c_armv8.c
@@ -14,7 +14,11 @@
*/
#include "c.h"
+#ifdef _MSC_VER
+#include <intrin.h>
+#else
#include <arm_acle.h>
+#endif
#include "port/pg_crc32c.h"
diff --git a/src/tools/msvc_gendef.pl b/src/tools/msvc_gendef.pl
index 868aad51b09..c92c94c4775 100644
--- a/src/tools/msvc_gendef.pl
+++ b/src/tools/msvc_gendef.pl
@@ -118,9 +118,9 @@ sub writedef
{
my $isdata = $def->{$f} eq 'data';
- # Strip the leading underscore for win32, but not x64
+ # Strip the leading underscore for win32, but not x64 and
aarch64
$f =~ s/^_//
- unless ($arch eq "x86_64");
+ unless ($arch eq "x86_64" || $arch eq "aarch64");
# Emit just the name if it's a function symbol, or emit the name
# decorated with the DATA option for variables.
@@ -141,7 +141,7 @@ sub writedef
sub usage
{
die("Usage: msvc_gendef.pl --arch <arch> --deffile <deffile> --tempdir
<tempdir> files-or-directories\n"
- . " arch: x86 | x86_64\n"
+ . " arch: x86 | x86_64 | aarch64\n"
. " deffile: path of the generated file\n"
. " tempdir: directory for temporary files\n"
. " files or directories: object files or directory
containing object files\n"
@@ -158,7 +158,7 @@ GetOptions(
'tempdir:s' => \$tempdir,) or usage();
usage("arch: $arch")
- unless ($arch eq 'x86' || $arch eq 'x86_64');
+ unless ($arch eq 'x86' || $arch eq 'x86_64' || $arch eq 'aarch64');
my @files;
--
2.39.5 (Apple Git-154)