Implement mremap(2) usage on NetBSD
authorKamil Rytarowski <n54@gmx.com>
Sun, 17 Apr 2016 00:46:57 +0000 (02:46 +0200)
committerKamil Rytarowski <n54@gmx.com>
Sun, 17 Apr 2016 00:46:57 +0000 (02:46 +0200)
The NetBSD version of mremap takes additional argument "newp" to hint
new position of a mapped range.

     void *
     mremap(void *oldp, size_t oldsize, void *newp, size_t newsize,
         int flags);

  -- NetBSD's mremap(2)

While Linux by default sets old_address and fails if the resize
operation cannot be finished for the original address.

       void *mremap(void *old_address, size_t old_size,
                    size_t new_size, int flags, ... /* void *new_address */);

  -- Linux's mremap(2)

NetBSD offers inversed logic with the MAP_FIXED flag to Linux's MREMAP_MAYMOVE:

     MAP_FIXED          newp is tried and mremap() fails if that address can't
                        be used as new base address for the range.  Otherwise,
                        oldp and newp are used as hints for the position,
                        factoring in the given alignment.

  -- NetBSD's mremap(2)

       MREMAP_MAYMOVE
              By default, if there is not sufficient space to expand a mapping
              at its current location, then mremap() fails.  If this flag is
              specified, then  the  kernel  is permitted to relocate the
              mapping to a new virtual address, if necessary.  If the mapping
              is relocated, then absolute pointers into the old mapping
              location become invalid (offsets relative to the starting address
              of the mapping should be employed).

  -- Linux's mremap(2)

The thing that bothers is calling mremap(2) syntax from Linux "posix", but we
cannot do anything with it, for now just simulate the Linux behavior on NetBSD.

mono/utils/dlmalloc.c
support/map.c
support/sys-mman.c

index 2ce2a6ea95e4afb928e2bb91d7bd0df263c936ae..3177f2d17a1194f5ebc59fbea7382990120a4db5 100644 (file)
@@ -342,7 +342,7 @@ HAVE_MMAP                 default: 1 (true)
   able to unmap memory that may have be allocated using multiple calls
   to MMAP, so long as they are adjacent.
 
-HAVE_MREMAP               default: 1 on linux, else 0
+HAVE_MREMAP               default: 1 on linux and NetBSD, else 0
   If true realloc() uses mremap() to re-allocate large blocks and
   extend or shrink allocation spaces.
 
@@ -536,11 +536,11 @@ DEFAULT_MMAP_THRESHOLD       default: 256K
 #define MMAP_CLEARS 1
 #endif  /* MMAP_CLEARS */
 #ifndef HAVE_MREMAP
-#ifdef linux
+#if defined(linux) || defined(__NetBSD__)
 #define HAVE_MREMAP 1
-#else   /* linux */
+#else   /* linux || __NetBSD__ */
 #define HAVE_MREMAP 0
-#endif  /* linux */
+#endif  /* linux || __NetBSD__ */
 #endif  /* HAVE_MREMAP */
 #ifndef MALLOC_FAILURE_ACTION
 #define MALLOC_FAILURE_ACTION  errno = ENOMEM;
@@ -1375,7 +1375,13 @@ static int win32munmap(void* ptr, size_t size) {
 #endif /* HAVE_MMAP */
 
 #if HAVE_MMAP && HAVE_MREMAP
+#if defined(linux)
 #define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
+#elif defined(__NetBSD__)
+#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (addr), (nsz), (mv))
+#else
+#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
+#endif
 #else  /* HAVE_MMAP && HAVE_MREMAP */
 #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
 #endif /* HAVE_MMAP && HAVE_MREMAP */
index 136f2b71878105b87fdcb5ccb5faa0f1cc943646..92fca755371d09ab6336dd25c5c131d014c47d7d 100644 (file)
@@ -3922,12 +3922,17 @@ int Mono_Posix_ToMountFlags (guint64 x, guint64 *r)
 int Mono_Posix_FromMremapFlags (guint64 x, guint64 *r)
 {
        *r = 0;
+#ifndef __NetBSD__
        if ((x & Mono_Posix_MremapFlags_MREMAP_MAYMOVE) == Mono_Posix_MremapFlags_MREMAP_MAYMOVE)
 #ifdef MREMAP_MAYMOVE
                *r |= MREMAP_MAYMOVE;
 #else /* def MREMAP_MAYMOVE */
                {errno = EINVAL; return -1;}
 #endif /* ndef MREMAP_MAYMOVE */
+#else /* def __NetBSD__ */
+       if ((x & Mono_Posix_MremapFlags_MREMAP_MAYMOVE) != Mono_Posix_MremapFlags_MREMAP_MAYMOVE)
+               *r = MAP_FIXED;
+#endif /* def __NetBSD__ */
        if (x == 0)
                return 0;
        return 0;
@@ -3936,12 +3941,17 @@ int Mono_Posix_FromMremapFlags (guint64 x, guint64 *r)
 int Mono_Posix_ToMremapFlags (guint64 x, guint64 *r)
 {
        *r = 0;
+#ifndef __NetBSD__
        if (x == 0)
                return 0;
 #ifdef MREMAP_MAYMOVE
        if ((x & MREMAP_MAYMOVE) == MREMAP_MAYMOVE)
                *r |= Mono_Posix_MremapFlags_MREMAP_MAYMOVE;
 #endif /* ndef MREMAP_MAYMOVE */
+#else /* def __NetBSD__ */
+       if ((x & MAP_FIXED) != MAP_FIXED)
+               *r |= Mono_Posix_MremapFlags_MREMAP_MAYMOVE;
+#endif
        return 0;
 }
 
@@ -9314,4 +9324,3 @@ int Mono_Posix_ToXattrFlags (int x, int *r)
 #endif /* ndef XATTR_REPLACE */
        return 0;
 }
-
index 3973bd6614f7199b3e4585bbf367c89301219a64..15e125621d2d03b1596d3ed737dcab38019d8430 100644 (file)
@@ -109,8 +109,15 @@ Mono_Posix_Syscall_mremap (void *old_address, mph_size_t old_size,
        if (Mono_Posix_FromMremapFlags (flags, &_flags) == -1)
                return MAP_FAILED;
 
+#if defined(linux)
        return mremap (old_address, (size_t) old_size, (size_t) new_size,
                        (unsigned long) _flags);
+#elif defined(__NetBSD__)
+       return mremap (old_address, (size_t) old_size, old_address,
+                       (size_t) new_size, (unsigned long) _flags);
+#else
+#error Port me
+#endif
 }
 #endif /* def HAVE_MREMAP */