From 965ac3c8142a5b8afdd7410f930c23fa9d5657a9 Mon Sep 17 00:00:00 2001
From: Tsutomu Yamada <tsutomu@sraoss.co.jp>
Date: Fri, 28 Aug 2009 18:39:49 +0900
Subject: [PATCH 2/3] fix for Windows x64

* add defines for WIN64
* support over 4GB shared memory
* fix API portablity
---
 src/backend/port/win32_shmem.c      |   29 +++++++++++++++++++----------
 src/backend/postmaster/postmaster.c |    4 ++++
 src/backend/postmaster/syslogger.c  |    2 +-
 src/include/pg_config.h.win32       |    8 ++++++++
 src/include/storage/pg_shmem.h      |    4 ++++
 src/include/storage/s_lock.h        |   12 ++++++++++++
 src/port/open.c                     |    2 +-
 7 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index fc8e51b..6a31b1c 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -16,7 +16,7 @@
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
 
-unsigned long UsedShmemSegID = 0;
+HANDLE		UsedShmemSegID = 0;
 void	   *UsedShmemSegAddr = NULL;
 static Size UsedShmemSegSize = 0;
 
@@ -125,6 +125,8 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 				hmap2;
 	char	   *szShareMem;
 	int			i;
+	DWORD		size_high;
+	DWORD		size_low;
 
 	/* Room for a header? */
 	Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
@@ -133,6 +135,13 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 
 	UsedShmemSegAddr = NULL;
 
+#ifdef _WIN64
+	size_high = size >> 32;
+#else
+	size_high = 0;
+#endif
+	size_low = (DWORD) size;
+
 	/*
 	 * When recycling a shared memory segment, it may take a short while
 	 * before it gets dropped from the global namespace. So re-try after
@@ -147,11 +156,11 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 		 */
 		SetLastError(0);
 
-		hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF,	/* Use the pagefile */
+		hmap = CreateFileMapping(INVALID_HANDLE_VALUE,	/* Use the pagefile */
 								 NULL,	/* Default security attrs */
 								 PAGE_READWRITE,		/* Memory is Read/Write */
-								 0L,	/* Size Upper 32 Bits	*/
-								 (DWORD) size,	/* Size Lower 32 bits */
+								 size_high,	/* Size Upper 32 Bits	*/
+								 size_low,	/* Size Lower 32 bits */
 								 szShareMem);
 
 		if (!hmap)
@@ -203,7 +212,7 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 
 
 	/* Register on-exit routine to delete the new segment */
-	on_shmem_exit(pgwin32_SharedMemoryDelete, Int32GetDatum((unsigned long) hmap2));
+	on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
 
 	/*
 	 * Get a pointer to the new shared memory segment. Map the whole segment
@@ -235,7 +244,7 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
 	/* Save info for possible future use */
 	UsedShmemSegAddr = memAddress;
 	UsedShmemSegSize = size;
-	UsedShmemSegID = (unsigned long) hmap2;
+	UsedShmemSegID = hmap2;
 
 	return hdr;
 }
@@ -266,10 +275,10 @@ PGSharedMemoryReAttach(void)
 		elog(FATAL, "failed to release reserved memory region (addr=%p): %lu",
 			 UsedShmemSegAddr, GetLastError());
 
-	hdr = (PGShmemHeader *) MapViewOfFileEx((HANDLE) UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
+	hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
 	if (!hdr)
-		elog(FATAL, "could not reattach to shared memory (key=%d, addr=%p): %lu",
-			 (int) UsedShmemSegID, UsedShmemSegAddr, GetLastError());
+		elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): %lu",
+			 UsedShmemSegID, UsedShmemSegAddr, GetLastError());
 	if (hdr != origUsedShmemSegAddr)
 		elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
 			 hdr, origUsedShmemSegAddr);
@@ -308,7 +317,7 @@ static void
 pgwin32_SharedMemoryDelete(int status, Datum shmId)
 {
 	PGSharedMemoryDetach();
-	if (!CloseHandle((HANDLE) DatumGetInt32(shmId)))
+	if (!CloseHandle(DatumGetPointer(shmId)))
 		elog(LOG, "could not close handle to shared memory: %lu", GetLastError());
 }
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index e94181a..d1e52d1 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -402,7 +402,11 @@ typedef struct
 	int			ListenSocket[MAXLISTEN];
 	long		MyCancelKey;
 	int			MyPMChildSlot;
+#ifndef WIN32
 	unsigned long UsedShmemSegID;
+#else
+	 HANDLE		UsedShmemSegID;
+#endif
 	void	   *UsedShmemSegAddr;
 	slock_t    *ShmemLock;
 	VariableCache ShmemVariableCache;
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 96865e1..ebc4388 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -573,7 +573,7 @@ SysLogger_Start(void)
 				 * chunking protocol.
 				 */
 				fflush(stderr);
-				fd = _open_osfhandle((long) syslogPipe[1],
+				fd = _open_osfhandle((intptr_t) syslogPipe[1],
 									 _O_APPEND | _O_BINARY);
 				if (dup2(fd, _fileno(stderr)) < 0)
 					ereport(FATAL,
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index b1981fd..0621c15 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -590,13 +590,21 @@
 /* #undef PTHREAD_CREATE_JOINABLE */
 
 /* The size of a `size_t', as computed by sizeof. */
+#ifdef _WIN64
+#define SIZEOF_SIZE_T 8
+#else
 #define SIZEOF_SIZE_T 4
+#endif
 
 /* The size of a `unsigned long', as computed by sizeof. */
 #define SIZEOF_UNSIGNED_LONG 4
 
 /* The size of `void *', as computed by sizeof. */
+#ifdef _WIN64
+#define SIZEOF_VOID_P 8
+#else
 #define SIZEOF_VOID_P 4
+#endif
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 37fae22..bc23c1d 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -40,7 +40,11 @@ typedef struct PGShmemHeader	/* standard header for all Postgres shmem */
 
 
 #ifdef EXEC_BACKEND
+#ifndef WIN32
 extern unsigned long UsedShmemSegID;
+#else
+extern HANDLE UsedShmemSegID;
+#endif
 extern void *UsedShmemSegAddr;
 
 extern void PGSharedMemoryReAttach(void);
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 48208b9..74c6dd7 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -836,12 +836,24 @@ typedef LONG slock_t;
 
 #define SPIN_DELAY() spin_delay()
 
+/* If using Visual C 2005 or 2008 on Win64, inline assembly is unavailable.
+ * Use a __noop instrinsic instead of rep nop.
+ * Might be slightly less efficient on EMT64, but its the same for AMD.
+ */
+#if defined(_WIN64) && defined(_MSC_VER) && (_MSC_VER == 1400 || _MSC_VER == 1500)
+static __forceinline void
+spin_delay(void)
+{
+	__noop();
+}
+#else
 static __forceinline void
 spin_delay(void)
 {
 	/* See comment for gcc code. Same code, MASM syntax */
 	__asm rep nop;
 }
+#endif
 
 #endif
 
diff --git a/src/port/open.c b/src/port/open.c
index f3a0a15..74edc99 100644
--- a/src/port/open.c
+++ b/src/port/open.c
@@ -124,7 +124,7 @@ pgwin32_open(const char *fileName, int fileFlags,...)
 	}
 
 	/* _open_osfhandle will, on error, set errno accordingly */
-	if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0)
+	if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
 		CloseHandle(h);			/* will not affect errno */
 	else if (fileFlags & (O_TEXT | O_BINARY) &&
 			 _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
-- 
1.6.4

