From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Subject: immutable: Implement on native Windows
Date: Mon, 18 Jan 2021 05:09:10 +0100 [thread overview]
Message-ID: <2508354.J8lELeYisT@omega> (raw)
In-Reply-To: <40258955.UtLViUJvzv@omega>
The 'immutable' module, so far, worked only on platforms with mmap() and
mprotect(). With this patch, it also works on native Windows.
2021-01-17 Bruno Haible <bruno@clisp.org>
immutable: Implement on native Windows.
* lib/immutable.h (IMMUTABLE_EFFECTIVE): Set to 1 on native Windows.
* lib/immutable.c: Include <windows.h>.
(CreateFileMapping): New macro.
(init_pagesize, init_mmap_file, alloc_pages, free_pages): Add
implementation for native Windows.
diff --git a/lib/immutable.c b/lib/immutable.c
index 089ad17..35f7397 100644
--- a/lib/immutable.c
+++ b/lib/immutable.c
@@ -37,27 +37,42 @@
# include <stdio.h>
+# if defined _WIN32 && !defined __CYGWIN__
+
+/* Declare VirtualAlloc(), GetSystemInfo. */
+# define WIN32_LEAN_AND_MEAN
+# define WIN32_EXTRA_LEAN
+# include <windows.h>
+
+/* Don't assume that UNICODE is not defined. */
+# undef CreateFileMapping
+# define CreateFileMapping CreateFileMappingA
+
+# else
+
/* Declare getpagesize(). */
-# include <unistd.h>
+# include <unistd.h>
/* On HP-UX, getpagesize exists, but it is not declared in <unistd.h> even if
the compiler options -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 are used. */
-# ifdef __hpux
+# ifdef __hpux
extern
-# ifdef __cplusplus
+# ifdef __cplusplus
"C"
-# endif
+# endif
int getpagesize (void);
-# endif
+# endif
/* Declare mmap(), mprotect(). */
-# include <sys/types.h>
-# include <sys/mman.h>
+# include <sys/types.h>
+# include <sys/mman.h>
/* Declare open(). */
-# include <unistd.h>
-# include <fcntl.h>
+# include <unistd.h>
+# include <fcntl.h>
-# include "glthread/lock.h"
+# include "glthread/lock.h"
+
+# endif
/* ================= Back end of the malloc implementation ================= */
@@ -71,10 +86,28 @@ static void
init_pagesize (void)
{
/* Simultaneous execution of this initialization in multiple threads is OK. */
+# if defined _WIN32 && !defined __CYGWIN__
+ /* GetSystemInfo
+ <https://msdn.microsoft.com/en-us/library/ms724381.aspx>
+ <https://msdn.microsoft.com/en-us/library/ms724958.aspx> */
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ pagesize = info.dwPageSize;
+# else
pagesize = getpagesize ();
+# endif
}
+# if defined _WIN32 && !defined __CYGWIN__
+
+static inline void
+init_mmap_file (void)
+{
+}
+
+# else
+
/* Variables needed for obtaining memory pages via mmap(). */
static int file_fd;
static long file_length;
@@ -109,6 +142,8 @@ init_mmap_file (void)
gl_once (for_mmap_once, do_init_mmap_file);
}
+# endif
+
/* Size of the (page-aligned) header that links the writable mapping
and the read-only mapping together. */
@@ -121,6 +156,44 @@ init_mmap_file (void)
static uintptr_t
alloc_pages (size_t size)
{
+# if defined _WIN32 && !defined __CYGWIN__
+ /* Allocate pages from the system paging file.
+ CreateFileMapping
+ <https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga> */
+ HANDLE h =
+ CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT,
+ size >> 16 >> 16, size & 0xFFFFFFFFU, NULL);
+ if (h == NULL)
+ {
+ fprintf (stderr,
+ "glimm: Cannot allocate file mapping. GetLastError() = 0x%08X\n",
+ (unsigned int) GetLastError ());
+ return 0;
+ }
+ /* MapViewOfFile
+ <https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile> */
+ char *mem_w = (char *) MapViewOfFile (h, FILE_MAP_WRITE, 0, 0, size);
+ char *mem_r = (char *) MapViewOfFile (h, FILE_MAP_READ, 0, 0, size);
+ if (mem_w == NULL || mem_r == NULL)
+ {
+ /* UnmapViewOfFile
+ <https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-unmapviewoffile> */
+ if (mem_w != NULL)
+ UnmapViewOfFile (mem_w);
+ if (mem_r != NULL)
+ UnmapViewOfFile (mem_r);
+ return 0;
+ }
+ /* It is OK to call CloseHandle before UnmapViewOfFile. The file mapping
+ object gets really closed only once all its views are unmapped. */
+ if (!CloseHandle (h))
+ {
+ UnmapViewOfFile (mem_w);
+ UnmapViewOfFile (mem_r);
+ CloseHandle (h);
+ return 0;
+ }
+# else
/* Extend the file by size/pagesize pages. */
long new_file_length = file_length + size;
if (ftruncate (file_fd, new_file_length) < 0)
@@ -142,6 +215,7 @@ alloc_pages (size_t size)
return 0;
}
file_length = new_file_length;
+# endif
/* Link the two memory areas together. */
((intptr_t *) mem_w)[0] = mem_r - mem_w;
@@ -158,10 +232,17 @@ free_pages (uintptr_t pages, size_t size)
abort ();
char *mem_w = (char *) pages;
char *mem_r = mem_w + ((intptr_t *) mem_w)[0];
+# if defined _WIN32 && !defined __CYGWIN__
+ if (!UnmapViewOfFile (mem_w))
+ abort ();
+ if (!UnmapViewOfFile (mem_r))
+ abort ();
+# else
if (munmap (mem_w, size) < 0)
abort ();
if (munmap (mem_r, size) < 0)
abort ();
+# endif
}
/* Cygwin defines PAGESIZE in <limits.h>. */
diff --git a/lib/immutable.h b/lib/immutable.h
index 75a2f5a..5f9f435 100644
--- a/lib/immutable.h
+++ b/lib/immutable.h
@@ -58,7 +58,7 @@ extern "C" {
/* This macro tells whether the implementation effectively rejects writes to
immutable data. */
-#if !NO_IMMUTABLE && HAVE_WORKING_MPROTECT
+#if !NO_IMMUTABLE && ((defined _WIN32 && !defined __CYGWIN__) || HAVE_WORKING_MPROTECT)
# define IMMUTABLE_EFFECTIVE 1
#else
# define IMMUTABLE_EFFECTIVE 0
next prev parent reply other threads:[~2021-01-18 4:09 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-10 0:23 new module 'immutable' Bruno Haible
2021-01-18 4:09 ` Bruno Haible [this message]
2021-01-18 16:52 ` immutable: Implement on native Windows Gisle Vanem
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2508354.J8lELeYisT@omega \
--to=bruno@clisp.org \
--cc=bug-gnulib@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).