Fixed MSVC build by explicitly providing "ssize_t".
[mono.git] / mono / utils / mono-mmap.c
index 8108028db5bc9cf4d34ca996bcdf7ad3310cf236..60ef156b15af7ed752361b70a36a625aee3fabbc 100644 (file)
@@ -62,6 +62,14 @@ malloc_shared_area (int pid)
        return sarea;
 }
 
+static char*
+aligned_address (char *mem, size_t size, size_t alignment)
+{
+       char *aligned = (char*)((size_t)(mem + (alignment - 1)) & ~(alignment - 1));
+       g_assert (aligned >= mem && aligned + size <= mem + size + alignment && !((size_t)aligned & (alignment - 1)));
+       return aligned;
+}
+
 #ifdef HOST_WIN32
 
 int
@@ -99,7 +107,7 @@ void*
 mono_valloc (void *addr, size_t length, int flags)
 {
        void *ptr;
-       int mflags = MEM_COMMIT;
+       int mflags = MEM_RESERVE|MEM_COMMIT;
        int prot = prot_from_flags (flags);
        /* translate the flags */
 
@@ -107,10 +115,36 @@ mono_valloc (void *addr, size_t length, int flags)
        return ptr;
 }
 
+void*
+mono_valloc_aligned (size_t length, size_t alignment, int flags)
+{
+       int prot = prot_from_flags (flags);
+       char *mem = VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot);
+       char *aligned;
+
+       if (!mem)
+               return NULL;
+
+       aligned = aligned_address (mem, length, alignment);
+
+       aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot);
+       g_assert (aligned);
+
+       return aligned;
+}
+
+#define HAVE_VALLOC_ALIGNED
+
 int
 mono_vfree (void *addr, size_t length)
 {
-       int res = VirtualFree (addr, 0, MEM_RELEASE);
+       MEMORY_BASIC_INFORMATION mbi;
+       SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi));
+       BOOL res;
+
+       g_assert (query_result);
+
+       res = VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE);
 
        g_assert (res);
 
@@ -178,8 +212,10 @@ mono_mprotect (void *addr, size_t length, int flags)
 void*
 mono_shared_area (void)
 {
+       if (!malloced_shared_area)
+               malloced_shared_area = malloc_shared_area (0);
        /* get the pid here */
-       return malloc_shared_area (0);
+       return malloced_shared_area;
 }
 
 void
@@ -187,6 +223,7 @@ mono_shared_area_remove (void)
 {
        if (malloced_shared_area)
                g_free (malloced_shared_area);
+       malloced_shared_area = NULL;
 }
 
 void*
@@ -271,13 +308,13 @@ mono_valloc (void *addr, size_t length, int flags)
        mflags |= MAP_PRIVATE;
 
        ptr = mmap (addr, length, prot, mflags, -1, 0);
-       if (ptr == (void*)-1) {
+       if (ptr == MAP_FAILED) {
                int fd = open ("/dev/zero", O_RDONLY);
                if (fd != -1) {
                        ptr = mmap (addr, length, prot, mflags, fd, 0);
                        close (fd);
                }
-               if (ptr == (void*)-1)
+               if (ptr == MAP_FAILED)
                        return NULL;
        }
        return ptr;
@@ -331,7 +368,7 @@ mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_hand
                mflags |= MAP_32BIT;
 
        ptr = mmap (0, length, prot, mflags, fd, offset);
-       if (ptr == (void*)-1)
+       if (ptr == MAP_FAILED)
                return NULL;
        *ret_handle = (void*)length;
        return ptr;
@@ -368,6 +405,20 @@ mono_file_unmap (void *addr, void *handle)
  *
  * Returns: 0 on success.
  */
+#if defined(__native_client__)
+int
+mono_mprotect (void *addr, size_t length, int flags)
+{
+       int prot = prot_from_flags (flags);
+       void *new_addr;
+
+       if (flags & MONO_MMAP_DISCARD) memset (addr, 0, length);
+
+       new_addr = mmap(addr, length, prot, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+       if (new_addr == addr) return 0;
+        return -1;
+}
+#else
 int
 mono_mprotect (void *addr, size_t length, int flags)
 {
@@ -390,6 +441,7 @@ mono_mprotect (void *addr, size_t length, int flags)
        }
        return mprotect (addr, length, prot);
 }
+#endif // __native_client__
 
 #else
 
@@ -431,29 +483,21 @@ mono_mprotect (void *addr, size_t length, int flags)
 }
 #endif // HAVE_MMAP
 
-#ifndef HAVE_VALLOC_ALIGNED
-void*
-mono_valloc_aligned (size_t size, size_t alignment, int flags)
-{
-       /* Allocate twice the memory to be able to put the block on an aligned address */
-       char *mem = mono_valloc (NULL, size + alignment, flags);
-       char *aligned;
-
-       g_assert (mem);
-
-       aligned = (char*)((gulong)(mem + (alignment - 1)) & ~(alignment - 1));
-       g_assert (aligned >= mem && aligned + size <= mem + size + alignment && !((gulong)aligned & (alignment - 1)));
+#if defined(HAVE_SHM_OPEN) && !defined (DISABLE_SHARED_PERFCOUNTERS)
 
-       if (aligned > mem)
-               mono_vfree (mem, aligned - mem);
-       if (aligned + size < mem + size + alignment)
-               mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size));
+static int use_shared_area;
 
-       return aligned;
+static gboolean
+shared_area_disabled (void)
+{
+       if (!use_shared_area) {
+               if (g_getenv ("MONO_DISABLE_SHARED_AREA"))
+                       use_shared_area = -1;
+               else
+                       use_shared_area = 1;
+       }
+       return use_shared_area == -1;
 }
-#endif
-
-#if defined(HAVE_SHM_OPEN) && !defined (DISABLE_SHARED_PERFCOUNTERS)
 
 static int
 mono_shared_area_instances_slow (void **array, int count, gboolean cleanup)
@@ -522,6 +566,13 @@ mono_shared_area (void)
        void *res;
        SAreaHeader *header;
 
+       if (shared_area_disabled ()) {
+               if (!malloced_shared_area)
+                       malloced_shared_area = malloc_shared_area (0);
+               /* get the pid here */
+               return malloced_shared_area;
+       }
+
        /* perform cleanup of segments left over from dead processes */
        mono_shared_area_instances_helper (NULL, 0, TRUE);
 
@@ -564,6 +615,13 @@ void
 mono_shared_area_remove (void)
 {
        char buf [128];
+
+       if (shared_area_disabled ()) {
+               if (malloced_shared_area)
+                       g_free (malloced_shared_area);
+               return;
+       }
+
        g_snprintf (buf, sizeof (buf), "/mono.%d", getpid ());
        shm_unlink (buf);
        if (malloced_shared_area)
@@ -579,6 +637,9 @@ mono_shared_area_for_pid (void *pid)
        char buf [128];
        void *res;
 
+       if (shared_area_disabled ())
+               return NULL;
+
        g_snprintf (buf, sizeof (buf), "/mono.%d", GPOINTER_TO_INT (pid));
 
        fd = shm_open (buf, O_RDONLY, S_IRUSR|S_IRGRP);
@@ -611,7 +672,10 @@ mono_shared_area_instances (void **array, int count)
 void*
 mono_shared_area (void)
 {
-       return malloc_shared_area (getpid ());
+       if (!malloced_shared_area)
+               malloced_shared_area = malloc_shared_area (getpid ());
+       /* get the pid here */
+       return malloced_shared_area;
 }
 
 void
@@ -642,3 +706,25 @@ mono_shared_area_instances (void **array, int count)
 #endif // HAVE_SHM_OPEN
 
 #endif // HOST_WIN32
+
+#ifndef HAVE_VALLOC_ALIGNED
+void*
+mono_valloc_aligned (size_t size, size_t alignment, int flags)
+{
+       /* Allocate twice the memory to be able to put the block on an aligned address */
+       char *mem = mono_valloc (NULL, size + alignment, flags);
+       char *aligned;
+
+       if (!mem)
+               return NULL;
+
+       aligned = aligned_address (mem, size, alignment);
+
+       if (aligned > mem)
+               mono_vfree (mem, aligned - mem);
+       if (aligned + size < mem + size + alignment)
+               mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size));
+
+       return aligned;
+}
+#endif