"Fossies" - the Fresh Open Source Software Archive

Member "mono-6.12.0.122/mono/utils/mono-mmap.c" (22 Feb 2021, 18340 Bytes) of package /linux/misc/mono-sources/mono/mono-6.12.0.122.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "mono-mmap.c": 6.12.0.107_vs_6.12.0.122.

    1 /**
    2  * \file
    3  * Support for mapping code into the process address space
    4  *
    5  * Author:
    6  *   Mono Team (mono-list@lists.ximian.com)
    7  *
    8  * Copyright 2001-2008 Novell, Inc.
    9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
   10  */
   11 
   12 #include <config.h>
   13 
   14 #ifndef HOST_WIN32
   15 #include <sys/types.h>
   16 #if HAVE_SYS_STAT_H
   17 #include <sys/stat.h>
   18 #endif
   19 #if HAVE_SYS_MMAN_H
   20 #include <sys/mman.h>
   21 #endif
   22 #ifdef HAVE_SYS_SYSCTL_H
   23 #include <sys/sysctl.h>
   24 #endif
   25 #include <signal.h>
   26 #include <fcntl.h>
   27 #include <string.h>
   28 #include <unistd.h>
   29 #include <stdlib.h>
   30 #include <errno.h>
   31 #endif /* !HOST_WIN32 */
   32 
   33 #include "mono-mmap.h"
   34 #include "mono-mmap-internals.h"
   35 #include "mono-proclib.h"
   36 #include <mono/utils/mono-threads.h>
   37 #include <mono/utils/atomic.h>
   38 #include <mono/utils/mono-counters.h>
   39 
   40 #define BEGIN_CRITICAL_SECTION do { \
   41     MonoThreadInfo *__info = mono_thread_info_current_unchecked (); \
   42     if (__info) __info->inside_critical_region = TRUE;  \
   43 
   44 #define END_CRITICAL_SECTION \
   45     if (__info) __info->inside_critical_region = FALSE; \
   46 } while (0) \
   47 
   48 #ifndef MAP_ANONYMOUS
   49 #define MAP_ANONYMOUS MAP_ANON
   50 #endif
   51 
   52 #if !defined(__APPLE__)  // returning virtual addresses <4G requires entitlement on Apple platforms, do not use it
   53 #ifndef MAP_32BIT
   54 #define MAP_32BIT 0
   55 #endif
   56 #endif
   57 
   58 typedef struct {
   59     int size;
   60     int pid;
   61     int reserved;
   62     short stats_start;
   63     short stats_end;
   64 } SAreaHeader;
   65 
   66 void*
   67 mono_malloc_shared_area (int pid)
   68 {
   69     int size = mono_pagesize ();
   70     SAreaHeader *sarea = (SAreaHeader *) g_malloc0 (size);
   71     sarea->size = size;
   72     sarea->pid = pid;
   73     sarea->stats_start = sizeof (SAreaHeader);
   74     sarea->stats_end = sizeof (SAreaHeader);
   75 
   76     return sarea;
   77 }
   78 
   79 char*
   80 mono_aligned_address (char *mem, size_t size, size_t alignment)
   81 {
   82     char *aligned = (char*)((size_t)(mem + (alignment - 1)) & ~(alignment - 1));
   83     g_assert (aligned >= mem && aligned + size <= mem + size + alignment && !((size_t)aligned & (alignment - 1)));
   84     return aligned;
   85 }
   86 
   87 static size_t allocation_count [MONO_MEM_ACCOUNT_MAX];
   88 static size_t total_allocation_count;
   89 static size_t alloc_limit;
   90 
   91 void
   92 mono_account_mem (MonoMemAccountType type, ssize_t size)
   93 {
   94     mono_atomic_fetch_add_word (&allocation_count [type], size);
   95     mono_atomic_fetch_add_word (&total_allocation_count, size);
   96 }
   97 
   98 void
   99 mono_valloc_set_limit (size_t size)
  100 {
  101     alloc_limit = size;
  102 }
  103 
  104 gboolean
  105 mono_valloc_can_alloc (size_t size)
  106 {
  107     if (alloc_limit)
  108         return (total_allocation_count + size) < alloc_limit;
  109     return TRUE;
  110 }
  111 
  112 const char*
  113 mono_mem_account_type_name (MonoMemAccountType type)
  114 {
  115     static const char *names[] = {
  116         "code",
  117         "hazard pointers",
  118         "domain",
  119         "SGen internal",
  120         "SGen nursery",
  121         "SGen LOS",
  122         "SGen mark&sweep",
  123         "SGen card table",
  124         "SGen shadow card table",
  125         "SGen debugging",
  126         "SGen binary protocol",
  127         "exceptions",
  128         "profiler",
  129         "other"
  130     };
  131 
  132     return names [type];
  133 }
  134 
  135 void
  136 mono_mem_account_register_counters (void)
  137 {
  138     for (int i = 0; i < MONO_MEM_ACCOUNT_MAX; ++i) {
  139         const char *prefix = "Valloc ";
  140         const char *name = mono_mem_account_type_name ((MonoMemAccountType)i);
  141         char descr [128];
  142         g_assert (strlen (prefix) + strlen (name) < sizeof (descr));
  143         sprintf (descr, "%s%s", prefix, name);
  144         mono_counters_register (descr, MONO_COUNTER_WORD | MONO_COUNTER_RUNTIME | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, (void*)&allocation_count [i]);
  145     }
  146 }
  147 
  148 #ifdef HOST_WIN32
  149 // Windows specific implementation in mono-mmap-windows.c
  150 #define HAVE_VALLOC_ALIGNED
  151 
  152 #elif defined(HOST_WASM)
  153 // WebAssembly implementation in mono-mmap-wasm.c
  154 #define HAVE_VALLOC_ALIGNED
  155 
  156 #else
  157 
  158 static void* malloced_shared_area = NULL;
  159 #if defined(HAVE_MMAP)
  160 
  161 /**
  162  * mono_pagesize:
  163  * Get the page size in use on the system. Addresses and sizes in the
  164  * mono_mmap(), mono_munmap() and mono_mprotect() calls must be pagesize
  165  * aligned.
  166  *
  167  * Returns: the page size in bytes.
  168  */
  169 int
  170 mono_pagesize (void)
  171 {
  172     static int saved_pagesize = 0;
  173 
  174     if (saved_pagesize)
  175         return saved_pagesize;
  176 
  177     // Prefer sysconf () as it's signal safe.
  178 #if defined (HAVE_SYSCONF) && defined (_SC_PAGESIZE)
  179     saved_pagesize = sysconf (_SC_PAGESIZE);
  180 #else
  181     saved_pagesize = getpagesize ();
  182 #endif
  183 
  184 
  185     // While this could not happen in any of the Mono supported
  186     // systems, this ensures this function never returns -1, and
  187     // reduces the number of false positives
  188     // that Coverity finds in consumer code.
  189 
  190     if (saved_pagesize == -1)
  191         return 64*1024;
  192 
  193     return saved_pagesize;
  194 }
  195 
  196 int
  197 mono_valloc_granule (void)
  198 {
  199     return mono_pagesize ();
  200 }
  201 
  202 static int
  203 prot_from_flags (int flags)
  204 {
  205     int prot = PROT_NONE;
  206     /* translate the protection bits */
  207     if (flags & MONO_MMAP_READ)
  208         prot |= PROT_READ;
  209     if (flags & MONO_MMAP_WRITE)
  210         prot |= PROT_WRITE;
  211     if (flags & MONO_MMAP_EXEC)
  212         prot |= PROT_EXEC;
  213     return prot;
  214 }
  215 
  216 #if defined(__APPLE__)
  217 
  218 #define DARWIN_VERSION_MOJAVE 18
  219 
  220 static guint32
  221 get_darwin_version (void)
  222 {
  223     static guint32 version;
  224 
  225     /* This doesn't need locking */
  226     if (!version) {
  227         char str[256] = {0};
  228         size_t size = sizeof(str);
  229         int err = sysctlbyname("kern.osrelease", str, &size, NULL, 0);
  230         g_assert (err == 0);
  231         err = sscanf (str, "%d", &version);
  232         g_assert (err == 1);
  233         g_assert (version > 0);
  234     }
  235     return version;
  236 }
  237 #endif
  238 
  239 static int use_mmap_jit;
  240 
  241 /**
  242  * mono_setmmapjit:
  243  * \param flag indicating whether to enable or disable the use of MAP_JIT in mmap
  244  *
  245  * Call this method to enable or disable the use of MAP_JIT to create the pages
  246  * for the JIT to use.   This is only needed for scenarios where Mono is bundled
  247  * as an App in MacOS
  248  */
  249 void
  250 mono_setmmapjit (int flag)
  251 {
  252     use_mmap_jit = flag;
  253 }
  254 
  255 /**
  256  * mono_valloc:
  257  * \param addr memory address
  258  * \param length memory area size
  259  * \param flags protection flags
  260  * Allocates \p length bytes of virtual memory with the \p flags
  261  * protection. \p addr can be a preferred memory address or a
  262  * mandatory one if MONO_MMAP_FIXED is set in \p flags.
  263  * \p addr must be pagesize aligned and can be NULL.
  264  * \p length must be a multiple of pagesize.
  265  * \returns NULL on failure, the address of the memory area otherwise
  266  */
  267 void*
  268 mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
  269 {
  270     void *ptr;
  271     int mflags = 0;
  272     int prot = prot_from_flags (flags);
  273 
  274     if (!mono_valloc_can_alloc (length))
  275         return NULL;
  276 
  277     /* translate the flags */
  278     if (flags & MONO_MMAP_FIXED)
  279         mflags |= MAP_FIXED;
  280 #if !defined(__APPLE__)  // returning virtual addresses <4G requires entitlement on Apple platforms, do not use it
  281     if (flags & MONO_MMAP_32BIT)
  282         mflags |= MAP_32BIT;
  283 #endif
  284 
  285 #ifdef HOST_WASM
  286     if (length == 0)
  287         /* emscripten throws an exception on 0 length */
  288         return NULL;
  289 #endif
  290 
  291 #if defined(__APPLE__) && defined(MAP_JIT) && defined(TARGET_OSX)
  292     if (get_darwin_version () >= DARWIN_VERSION_MOJAVE) {
  293         /* Check for hardened runtime */
  294         static int is_hardened_runtime;
  295 
  296         if (is_hardened_runtime == 0 && !use_mmap_jit) {
  297             ptr = mmap (NULL, getpagesize (), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  298             if (ptr == MAP_FAILED) {
  299                 is_hardened_runtime = 1;
  300             } else {
  301                 is_hardened_runtime = 2;
  302                 munmap (ptr, getpagesize ());
  303             }
  304         }
  305         if ((flags & MONO_MMAP_JIT) && (use_mmap_jit || is_hardened_runtime == 1))
  306             mflags |= MAP_JIT;
  307     }
  308 #endif
  309 
  310     mflags |= MAP_ANONYMOUS;
  311     mflags |= MAP_PRIVATE;
  312 
  313     BEGIN_CRITICAL_SECTION;
  314     ptr = mmap (addr, length, prot, mflags, -1, 0);
  315     if (ptr == MAP_FAILED) {
  316         int fd = open ("/dev/zero", O_RDONLY);
  317         if (fd != -1) {
  318             ptr = mmap (addr, length, prot, mflags, fd, 0);
  319             close (fd);
  320         }
  321     }
  322     END_CRITICAL_SECTION;
  323 
  324     if (ptr == MAP_FAILED)
  325         return NULL;
  326 
  327     mono_account_mem (type, (ssize_t)length);
  328 
  329     return ptr;
  330 }
  331 
  332 /**
  333  * mono_vfree:
  334  * \param addr memory address returned by mono_valloc ()
  335  * \param length size of memory area
  336  * Remove the memory mapping at the address \p addr.
  337  * \returns \c 0 on success.
  338  */
  339 int
  340 mono_vfree (void *addr, size_t length, MonoMemAccountType type)
  341 {
  342     int res;
  343     BEGIN_CRITICAL_SECTION;
  344     res = munmap (addr, length);
  345     END_CRITICAL_SECTION;
  346 
  347     mono_account_mem (type, -(ssize_t)length);
  348 
  349     return res;
  350 }
  351 
  352 /**
  353  * mono_file_map:
  354  * \param length size of data to map
  355  * \param flags protection flags
  356  * \param fd file descriptor
  357  * \param offset offset in the file
  358  * \param ret_handle pointer to storage for returning a handle for the map
  359  * Map the area of the file pointed to by the file descriptor \p fd, at offset
  360  * \p offset and of size \p length in memory according to the protection flags
  361  * \p flags.
  362  * \p offset and \p length must be multiples of the page size.
  363  * \p ret_handle must point to a void*: this value must be used when unmapping
  364  * the memory area using \c mono_file_unmap().
  365  */
  366 void*
  367 mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle)
  368 {
  369     return mono_file_map_error (length, flags, fd, offset, ret_handle, NULL, NULL);
  370 }
  371 
  372 void*
  373 mono_file_map_error (size_t length, int flags, int fd, guint64 offset, void **ret_handle,
  374     const char *filepath, char **error_message)
  375 {
  376     void *ptr;
  377     int mflags = 0;
  378     int prot = prot_from_flags (flags);
  379     /* translate the flags */
  380     if (flags & MONO_MMAP_PRIVATE)
  381         mflags |= MAP_PRIVATE;
  382     if (flags & MONO_MMAP_SHARED)
  383         mflags |= MAP_SHARED;
  384     if (flags & MONO_MMAP_FIXED)
  385         mflags |= MAP_FIXED;
  386 #if !defined(__APPLE__)  // returning virtual addresses <4G requires entitlement on Apple platforms, do not use it
  387     if (flags & MONO_MMAP_32BIT)
  388         mflags |= MAP_32BIT;
  389 #endif
  390 
  391 #ifdef HOST_WASM
  392     if (length == 0)
  393         /* emscripten throws an exception on 0 length */
  394         *error_message = g_stdrup_printf ("%s failed file:%s length:0x%" G_GSIZE_FORMAT "x offset:0x%" PRIu64 "X error:%s\n",
  395             __func__, filepath ? filepath : "", length, (guint64)offset, "mmaps of zero length are not permitted with emscripten");
  396         return NULL;
  397 #endif
  398 
  399     // No GC safe transition because this is called early in main.c
  400     BEGIN_CRITICAL_SECTION;
  401     ptr = mmap (0, length, prot, mflags, fd, offset);
  402     END_CRITICAL_SECTION;
  403     if (ptr == MAP_FAILED) {
  404         if (error_message) {
  405             *error_message = g_strdup_printf ("%s failed file:%s length:0x%" G_GSIZE_FORMAT "X offset:0x%" PRIu64 "X error:%s(0x%X)\n",
  406                 __func__, filepath ? filepath : "", length, (guint64)offset, g_strerror (errno), errno);
  407         }
  408         return NULL;
  409     }
  410     *ret_handle = (void*)length;
  411     return ptr;
  412 }
  413 
  414 /**
  415  * mono_file_unmap:
  416  * \param addr memory address returned by mono_file_map ()
  417  * \param handle handle of memory map
  418  * Remove the memory mapping at the address \p addr.
  419  * \p handle must be the value returned in ret_handle by \c mono_file_map().
  420  * \returns \c 0 on success.
  421  */
  422 int
  423 mono_file_unmap (void *addr, void *handle)
  424 {
  425     int res;
  426 
  427     // No GC safe transition because this is called early in driver.c via mono_debug_init (with a few layers of indirection)
  428     BEGIN_CRITICAL_SECTION;
  429     res = munmap (addr, (size_t)handle);
  430     END_CRITICAL_SECTION;
  431 
  432     return res;
  433 }
  434 
  435 /**
  436  * mono_mprotect:
  437  * \param addr memory address
  438  * \param length size of memory area
  439  * \param flags new protection flags
  440  * Change the protection for the memory area at \p addr for \p length bytes
  441  * to matche the supplied \p flags.
  442  * If \p flags includes MON_MMAP_DISCARD the pages are discarded from memory
  443  * and the area is cleared to zero.
  444  * \p addr must be aligned to the page size.
  445  * \p length must be a multiple of the page size.
  446  * \returns \c 0 on success.
  447  */
  448 int
  449 mono_mprotect (void *addr, size_t length, int flags)
  450 {
  451     int prot = prot_from_flags (flags);
  452 
  453     if (flags & MONO_MMAP_DISCARD) {
  454         /* on non-linux the pages are not guaranteed to be zeroed (*bsd, osx at least) */
  455 #ifdef __linux__
  456         if (madvise (addr, length, MADV_DONTNEED))
  457             memset (addr, 0, length);
  458 #else
  459         memset (addr, 0, length);
  460 /* some OSes (like AIX) have madvise but no MADV_FREE */
  461 #if defined(HAVE_MADVISE) && defined(MADV_FREE)
  462         madvise (addr, length, MADV_DONTNEED);
  463         madvise (addr, length, MADV_FREE);
  464 #else
  465         posix_madvise (addr, length, POSIX_MADV_DONTNEED);
  466 #endif
  467 #endif
  468     }
  469     // No GC safe transition because this is called early in mini_init via mono_arch_init (with a few layers of indirection)
  470     return mprotect (addr, length, prot);
  471 }
  472 
  473 #else
  474 
  475 /* dummy malloc-based implementation */
  476 int
  477 mono_pagesize (void)
  478 {
  479     return 4096;
  480 }
  481 
  482 int
  483 mono_valloc_granule (void)
  484 {
  485     return mono_pagesize ();
  486 }
  487 
  488 void*
  489 mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
  490 {
  491     g_assert (addr == NULL);
  492     return mono_valloc_aligned (length, mono_pagesize (), flags, type);
  493 }
  494 
  495 void*
  496 mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
  497 {
  498     void *res = NULL;
  499     if (posix_memalign (&res, alignment, size))
  500         return NULL;
  501 
  502     memset (res, 0, size);
  503     return res;
  504 }
  505 
  506 #define HAVE_VALLOC_ALIGNED
  507 
  508 int
  509 mono_vfree (void *addr, size_t length, MonoMemAccountType type)
  510 {
  511     g_free (addr);
  512     return 0;
  513 }
  514 
  515 int
  516 mono_mprotect (void *addr, size_t length, int flags)
  517 {
  518     if (flags & MONO_MMAP_DISCARD) {
  519         memset (addr, 0, length);
  520     }
  521     return 0;
  522 }
  523 
  524 #endif // HAVE_MMAP
  525 
  526 #if defined(HAVE_SHM_OPEN) && !defined (DISABLE_SHARED_PERFCOUNTERS)
  527 
  528 static int use_shared_area;
  529 
  530 static gboolean
  531 shared_area_disabled (void)
  532 {
  533     if (!use_shared_area) {
  534         if (g_hasenv ("MONO_DISABLE_SHARED_AREA"))
  535             use_shared_area = -1;
  536         else
  537             use_shared_area = 1;
  538     }
  539     return use_shared_area == -1;
  540 }
  541 
  542 static int
  543 mono_shared_area_instances_slow (void **array, int count, gboolean cleanup)
  544 {
  545     int i, j = 0;
  546     int num;
  547     void *data;
  548     gpointer *processes = mono_process_list (&num);
  549     for (i = 0; i < num; ++i) {
  550         data = mono_shared_area_for_pid (processes [i]);
  551         if (!data)
  552             continue;
  553         mono_shared_area_unload (data);
  554         if (!cleanup) {
  555             if (j < count)
  556                 array [j++] = processes [i];
  557             else
  558                 break;
  559         }
  560     }
  561     g_free (processes);
  562     return j;
  563 }
  564 
  565 static int
  566 mono_shared_area_instances_helper (void **array, int count, gboolean cleanup)
  567 {
  568     const char *name;
  569     int i = 0;
  570     int curpid = getpid ();
  571     GDir *dir = g_dir_open ("/dev/shm/", 0, NULL);
  572     if (!dir)
  573         return mono_shared_area_instances_slow (array, count, cleanup);
  574     while ((name = g_dir_read_name (dir))) {
  575         int pid;
  576         char *nend;
  577         if (strncmp (name, "mono.", 5))
  578             continue;
  579         pid = strtol (name + 5, &nend, 10);
  580         if (pid <= 0 || nend == name + 5 || *nend)
  581             continue;
  582         if (!cleanup) {
  583             if (i < count)
  584                 array [i++] = GINT_TO_POINTER (pid);
  585             else
  586                 break;
  587         }
  588         if (curpid != pid && kill (pid, 0) == -1 && (errno == ESRCH || errno == ENOMEM)) {
  589             char buf [128];
  590             g_snprintf (buf, sizeof (buf), "/mono.%d", pid);
  591             shm_unlink (buf);
  592         }
  593     }
  594     g_dir_close (dir);
  595     return i;
  596 }
  597 
  598 void*
  599 mono_shared_area (void)
  600 {
  601     int fd;
  602     int pid = getpid ();
  603     /* we should allow the user to configure the size */
  604     int size = mono_pagesize ();
  605     char buf [128];
  606     void *res;
  607     SAreaHeader *header;
  608 
  609     if (shared_area_disabled ()) {
  610         if (!malloced_shared_area)
  611             malloced_shared_area = mono_malloc_shared_area (0);
  612         /* get the pid here */
  613         return malloced_shared_area;
  614     }
  615 
  616     /* perform cleanup of segments left over from dead processes */
  617     mono_shared_area_instances_helper (NULL, 0, TRUE);
  618 
  619     g_snprintf (buf, sizeof (buf), "/mono.%d", pid);
  620 
  621     fd = shm_open (buf, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP);
  622     if (fd == -1 && errno == EEXIST) {
  623         /* leftover */
  624         shm_unlink (buf);
  625         fd = shm_open (buf, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP);
  626     }
  627     /* in case of failure we try to return a memory area anyway,
  628      * even if it means the data can't be read by other processes
  629      */
  630     if (fd == -1)
  631         return mono_malloc_shared_area (pid);
  632     if (ftruncate (fd, size) != 0) {
  633         shm_unlink (buf);
  634         close (fd);
  635     }
  636     BEGIN_CRITICAL_SECTION;
  637     res = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  638     END_CRITICAL_SECTION;
  639 
  640     if (res == MAP_FAILED) {
  641         shm_unlink (buf);
  642         close (fd);
  643         return mono_malloc_shared_area (pid);
  644     }
  645     /* we don't need the file descriptor anymore */
  646     close (fd);
  647     header = (SAreaHeader *) res;
  648     header->size = size;
  649     header->pid = pid;
  650     header->stats_start = sizeof (SAreaHeader);
  651     header->stats_end = sizeof (SAreaHeader);
  652 
  653     mono_atexit (mono_shared_area_remove);
  654     return res;
  655 }
  656 
  657 void
  658 mono_shared_area_remove (void)
  659 {
  660     char buf [128];
  661 
  662     if (shared_area_disabled ()) {
  663         if (malloced_shared_area)
  664             g_free (malloced_shared_area);
  665         return;
  666     }
  667 
  668     g_snprintf (buf, sizeof (buf), "/mono.%d", getpid ());
  669     shm_unlink (buf);
  670     if (malloced_shared_area)
  671         g_free (malloced_shared_area);
  672 }
  673 
  674 void*
  675 mono_shared_area_for_pid (void *pid)
  676 {
  677     int fd;
  678     /* we should allow the user to configure the size */
  679     int size = mono_pagesize ();
  680     char buf [128];
  681     void *res;
  682 
  683     if (shared_area_disabled ())
  684         return NULL;
  685 
  686     g_snprintf (buf, sizeof (buf), "/mono.%d", GPOINTER_TO_INT (pid));
  687 
  688     fd = shm_open (buf, O_RDONLY, S_IRUSR|S_IRGRP);
  689     if (fd == -1)
  690         return NULL;
  691     BEGIN_CRITICAL_SECTION;
  692     res = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
  693     END_CRITICAL_SECTION;
  694 
  695     if (res == MAP_FAILED) {
  696         close (fd);
  697         return NULL;
  698     }
  699     /* FIXME: validate the area */
  700     /* we don't need the file descriptor anymore */
  701     close (fd);
  702     return res;
  703 }
  704 
  705 void
  706 mono_shared_area_unload  (void *area)
  707 {
  708     /* FIXME: currently we load only a page */
  709     BEGIN_CRITICAL_SECTION;
  710     munmap (area, mono_pagesize ());
  711     END_CRITICAL_SECTION;
  712 }
  713 
  714 int
  715 mono_shared_area_instances (void **array, int count)
  716 {
  717     return mono_shared_area_instances_helper (array, count, FALSE);
  718 }
  719 #else
  720 void*
  721 mono_shared_area (void)
  722 {
  723     if (!malloced_shared_area)
  724         malloced_shared_area = mono_malloc_shared_area (getpid ());
  725     /* get the pid here */
  726     return malloced_shared_area;
  727 }
  728 
  729 void
  730 mono_shared_area_remove (void)
  731 {
  732     if (malloced_shared_area)
  733         g_free (malloced_shared_area);
  734     malloced_shared_area = NULL;
  735 }
  736 
  737 void*
  738 mono_shared_area_for_pid (void *pid)
  739 {
  740     return NULL;
  741 }
  742 
  743 void
  744 mono_shared_area_unload (void *area)
  745 {
  746 }
  747 
  748 int
  749 mono_shared_area_instances (void **array, int count)
  750 {
  751     return 0;
  752 }
  753 
  754 #endif // HAVE_SHM_OPEN
  755 
  756 #endif // HOST_WIN32
  757 
  758 #ifndef HAVE_VALLOC_ALIGNED
  759 void*
  760 mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
  761 {
  762     /* Allocate twice the memory to be able to put the block on an aligned address */
  763     char *mem = (char *) mono_valloc (NULL, size + alignment, flags, type);
  764     char *aligned;
  765 
  766     if (!mem)
  767         return NULL;
  768 
  769     aligned = mono_aligned_address (mem, size, alignment);
  770 
  771     if (aligned > mem)
  772         mono_vfree (mem, aligned - mem, type);
  773     if (aligned + size < mem + size + alignment)
  774         mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size), type);
  775 
  776     return aligned;
  777 }
  778 #endif