Attached is a patch against guile master (at 3.0.4),
commit 5e1748f75128107e3a0707b66df5adb95d98437e
It is a incomplete, but functional, implementation of a mmap-api, including
1) mmap : low-level mmap, returns a bytevector, not searched for roots
2) mmap/search : like mmap, but not marked w/ GC_exclude_static_roots
3) mmap-file: high-level, easy-to-use mmap (e.g., (mmap-file "foo.dat"))
The above are coded in libguile/filesys.[ch].
Also included is test-suite/tests/mmap-api.test.
Build:
$ ./configure --enable-mmap-api
$ make
$ make check
...
Running mmap-api.test
...
Since implementation of mmap may be not simple, I propose a
git branch (e.g., wip-mmap-api) be created to invite group review,
update, test the update.
Matt
diff --git a/configure.ac b/configure.ac
index 3e96094f6..382d7d528 100644
--- a/configure.ac
+++ b/configure.ac
@@ -170,6 +170,10 @@ AC_ARG_ENABLE(tmpnam,
AS_HELP_STRING([--disable-tmpnam],[omit POSIX tmpnam]),,
enable_tmpnam=yes)
+AC_ARG_ENABLE(mmap-api,
+ AS_HELP_STRING([--enable-mmap-api],[enable MMAP interface]),,
+ enable_mmap_api=no)
+
AC_ARG_ENABLE([deprecated],
AS_HELP_STRING([--disable-deprecated],[omit deprecated features]))
@@ -917,6 +921,10 @@ if test "$enable_tmpnam" = yes; then
AC_DEFINE([ENABLE_TMPNAM], 1, [Define when tmpnam support is enabled.])
fi
+if test "$enable_mmap_api" = yes; then
+ AC_DEFINE([ENABLE_MMAP_API], 1, [Define when MMAP API is enabled.])
+fi
+
AC_REPLACE_FUNCS([strerror memmove])
# Reasons for testing:
diff --git a/libguile/filesys.c b/libguile/filesys.c
index 39bfd38cc..04e5dfd4d 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -79,11 +79,22 @@
# include
#endif
+#ifdef ENABLE_MMAP_API
+#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MAP_ANONYMOUS)
+# include
+# include
+# include
+#endif
+#endif
+
#include "async.h"
#include "boolean.h"
+#include "bytevectors.h"/* mmap */
#include "dynwind.h"
#include "fdes-finalizers.h"
#include "feature.h"
+#include "finalizers.h" /* mmap */
+#include "foreign.h"/* mmap */
#include "fports.h"
#include "gsubr.h"
#include "iselect.h"
@@ -1880,6 +1891,314 @@ scm_dir_free (SCM p)
+#ifdef ENABLE_MMAP_API
+#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MAP_ANONYMOUS)
+
+/* FiXME
+ * rlb says add msync()
+ * Windows : look for MapViewOfFile
+ */
+
+/* undefined, string or int acceptable */
+static int
+mm_flags (SCM prot, int def)
+{
+ if (SCM_UNBNDP (prot))
+return def;
+ else
+scm_misc_error("mmap", "bad prot option", SCM_EOL);
+ return -1;
+}
+
+static int
+mm_prot (SCM prot, int def)
+{
+ if (SCM_UNBNDP (prot))
+return def;
+ else
+scm_misc_error("mmap", "bad prot option", SCM_EOL);
+ return -1;
+}
+
+static void
+mmap_finalizer (void *ptr, void *data)
+{
+ SCM bvec;
+ void *c_addr;
+ size_t c_len;
+ int res;
+
+ bvec = SCM_PACK_POINTER (ptr);
+ if (!SCM_BYTEVECTOR_P (bvec))
+abort();
+
+ c_addr = SCM_BYTEVECTOR_CONTENTS (bvec);
+ c_len = (size_t) data;
+ res = munmap(c_addr, c_len);
+ if (res != 0)
+scm_misc_error ("mmap", "failed to munmap memory", SCM_EOL);
+}
+
+SCM_DEFINE (scm_mmap_search, "mmap/search", 2, 4, 0,
+(SCM addr, SCM len, SCM prot, SCM flags, SCM fd, SCM offset),
+ "mmap addr len [prot [flags [fd [offset"
+ "See the unix man page for mmap. Returns a bytevector."
+ "Note that the region allocated will be searched by the garbage"
+ "collector for pointers. \n"
+ "Defaults:\n"
+ " prot (logior PROT_READ PROT_WRITE)\n"
+ " flags (logior MAP_ANON MAP_PRIVATE)\n"
+ " fd -1\n"
+ " offset 0\n"
+ "E.g., @code{(define reg (mmap/search %null-pointer #x1000)}\n")
+#define FUNC_NAME s_scm_mmap_search
+{
+ void *c_mem, *c_addr;
+ size_t c_len;
+ int c_prot, c_flags, c_fd;
+ scm_t_off c_offset;
+ SCM pointer, bvec;
+
+ if (SCM_POINTER_P (addr))
+c_addr = SCM_POINTER_VALUE (addr);
+ else if (scm_is_integer (addr))
+c_addr = (void*) scm_to_uintptr_t (addr);
+ else
+SCM_MISC_ERROR("bad addr", addr);
+
+ c_len = scm_to_size_t (len);
+
+ if (SCM_UNBNDP (prot))
+c_prot = PROT_READ | PROT_WRITE;
+ else
+c_prot = scm_to_int (prot);
+
+ if (SCM_UNBNDP (flags))
+c_flags = MAP_ANON | MAP_PRIVATE;
+ else
+c_flags = scm_to_int (flags);
+
+ if (SCM_UNBNDP (fd))
+c_fd = -1;
+ else
+c_fd = scm_to_int (fd);
+
+ if (SCM_UNBNDP (fd))
+c_offset = 0;
+ else
+c_offset = scm_to_off_t (offset);
+
+ c_mem = mmap(c_addr, c_len, c_prot, c_flags, c_fd, c_offset);
+ if (c_mem == MAP_FAILED)
+SCM_SYSERROR; /* errno set */
+
+ pointer = scm_cell (scm_tc7_pointer, (scm_t_bits) c_mem);
+ bvec = scm_c_take_typed_bytevector((signed char *) c_mem + c_offset, c_len,
+ SCM_ARRAY_ELEMENT_TYPE_VU8, pointer);
+ assert(sizeof(void*) <= sizeof(size_t));
+ scm_i_set_finalizer (SCM2PTR (bvec), mmap_finalizer, (void*) c_len);
+ return bvec;
+}
+#unde