* Mono Team (mono-list@lists.ximian.com)
*
* Copyright 2001-2008 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
-#include "config.h"
+#include <config.h>
-#ifdef HOST_WIN32
-#include <windows.h>
-#include <io.h>
-#else
+#ifndef HOST_WIN32
#include <sys/types.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
-#endif
+#endif /* !HOST_WIN32 */
#include "mono-mmap.h"
#include "mono-mmap-internals.h"
#include "mono-proclib.h"
#include <mono/utils/mono-threads.h>
-
+#include <mono/utils/atomic.h>
+#include <mono/utils/mono-counters.h>
#define BEGIN_CRITICAL_SECTION do { \
MonoThreadInfo *__info = mono_thread_info_current_unchecked (); \
short stats_end;
} SAreaHeader;
-static void* malloced_shared_area = NULL;
-
-static void*
+void*
malloc_shared_area (int pid)
{
int size = mono_pagesize ();
return sarea;
}
-static char*
+char*
aligned_address (char *mem, size_t size, size_t alignment)
{
char *aligned = (char*)((size_t)(mem + (alignment - 1)) & ~(alignment - 1));
return aligned;
}
-#ifdef HOST_WIN32
-
-int
-mono_pagesize (void)
-{
- SYSTEM_INFO info;
- static int saved_pagesize = 0;
- if (saved_pagesize)
- return saved_pagesize;
- GetSystemInfo (&info);
- saved_pagesize = info.dwAllocationGranularity;
- return saved_pagesize;
-}
-
-static int
-prot_from_flags (int flags)
-{
- int prot = flags & (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC);
- switch (prot) {
- case 0: prot = PAGE_NOACCESS; break;
- case MONO_MMAP_READ: prot = PAGE_READONLY; break;
- case MONO_MMAP_READ|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READ; break;
- case MONO_MMAP_READ|MONO_MMAP_WRITE: prot = PAGE_READWRITE; break;
- case MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break;
- case MONO_MMAP_WRITE: prot = PAGE_READWRITE; break;
- case MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break;
- case MONO_MMAP_EXEC: prot = PAGE_EXECUTE; break;
- default:
- g_assert_not_reached ();
- }
- return prot;
-}
-
-void*
-mono_valloc (void *addr, size_t length, int flags)
-{
- void *ptr;
- int mflags = MEM_RESERVE|MEM_COMMIT;
- int prot = prot_from_flags (flags);
- /* translate the flags */
-
- ptr = VirtualAlloc (addr, length, mflags, prot);
- 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)
-{
- 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);
-
- return 0;
-}
-
-void*
-mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle)
-{
- void *ptr;
- int mflags = 0;
- HANDLE file, mapping;
- int prot = prot_from_flags (flags);
- /* translate the flags */
- /*if (flags & MONO_MMAP_PRIVATE)
- mflags |= MAP_PRIVATE;
- if (flags & MONO_MMAP_SHARED)
- mflags |= MAP_SHARED;
- if (flags & MONO_MMAP_ANON)
- mflags |= MAP_ANONYMOUS;
- if (flags & MONO_MMAP_FIXED)
- mflags |= MAP_FIXED;
- if (flags & MONO_MMAP_32BIT)
- mflags |= MAP_32BIT;*/
-
- mflags = FILE_MAP_READ;
- if (flags & MONO_MMAP_WRITE)
- mflags = FILE_MAP_COPY;
-
- file = (HANDLE) _get_osfhandle (fd);
- mapping = CreateFileMapping (file, NULL, prot, 0, 0, NULL);
- if (mapping == NULL)
- return NULL;
- ptr = MapViewOfFile (mapping, mflags, 0, offset, length);
- if (ptr == NULL) {
- CloseHandle (mapping);
- return NULL;
- }
- *ret_handle = (void*)mapping;
- return ptr;
-}
-
-int
-mono_file_unmap (void *addr, void *handle)
-{
- UnmapViewOfFile (addr);
- CloseHandle ((HANDLE)handle);
- return 0;
-}
-
-int
-mono_mprotect (void *addr, size_t length, int flags)
-{
- DWORD oldprot;
- int prot = prot_from_flags (flags);
-
- if (flags & MONO_MMAP_DISCARD) {
- VirtualFree (addr, length, MEM_DECOMMIT);
- VirtualAlloc (addr, length, MEM_COMMIT, prot);
- return 0;
- }
- return VirtualProtect (addr, length, prot, &oldprot) == 0;
-}
-
-void*
-mono_shared_area (void)
-{
- if (!malloced_shared_area)
- malloced_shared_area = malloc_shared_area (0);
- /* get the pid here */
- return malloced_shared_area;
-}
+static volatile size_t allocation_count [MONO_MEM_ACCOUNT_MAX];
void
-mono_shared_area_remove (void)
+account_mem (MonoMemAccountType type, ssize_t size)
{
- if (malloced_shared_area)
- g_free (malloced_shared_area);
- malloced_shared_area = NULL;
+#if SIZEOF_VOID_P == 4
+ InterlockedAdd ((volatile gint32*)&allocation_count [type], (gint32)size);
+#else
+ InterlockedAdd64 ((volatile gint64*)&allocation_count [type], (gint64)size);
+#endif
}
-void*
-mono_shared_area_for_pid (void *pid)
+const char*
+mono_mem_account_type_name (MonoMemAccountType type)
{
- return NULL;
+ static const char *names[] = {
+ "code",
+ "hazard pointers",
+ "domain",
+ "SGen internal",
+ "SGen nursery",
+ "SGen LOS",
+ "SGen mark&sweep",
+ "SGen card table",
+ "SGen shadow card table",
+ "SGen debugging",
+ "SGen binary protocol",
+ "exceptions",
+ "profiler",
+ "other"
+ };
+
+ return names [type];
}
void
-mono_shared_area_unload (void *area)
-{
+mono_mem_account_register_counters (void)
+{
+ for (int i = 0; i < MONO_MEM_ACCOUNT_MAX; ++i) {
+ const char *prefix = "Valloc ";
+ const char *name = mono_mem_account_type_name (i);
+ char descr [128];
+ g_assert (strlen (prefix) + strlen (name) < sizeof (descr));
+ sprintf (descr, "%s%s", prefix, name);
+ mono_counters_register (descr, MONO_COUNTER_WORD | MONO_COUNTER_RUNTIME | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, (void*)&allocation_count [i]);
+ }
}
-int
-mono_shared_area_instances (void **array, int count)
-{
- return 0;
-}
+#ifdef HOST_WIN32
+// Windows specific implementation in mono-mmap-windows.c
+#define HAVE_VALLOC_ALIGNED
#else
+
+static void* malloced_shared_area = NULL;
#if defined(HAVE_MMAP)
/**
return saved_pagesize;
}
+int
+mono_valloc_granule (void)
+{
+ return mono_pagesize ();
+}
+
static int
prot_from_flags (int flags)
{
* Returns: NULL on failure, the address of the memory area otherwise
*/
void*
-mono_valloc (void *addr, size_t length, int flags)
+mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
{
void *ptr;
int mflags = 0;
if (ptr == MAP_FAILED)
return NULL;
+
+ account_mem (type, (ssize_t)length);
+
return ptr;
}
* Returns: 0 on success.
*/
int
-mono_vfree (void *addr, size_t length)
+mono_vfree (void *addr, size_t length, MonoMemAccountType type)
{
int res;
BEGIN_CRITICAL_SECTION;
res = munmap (addr, length);
END_CRITICAL_SECTION;
+
+ account_mem (type, -(ssize_t)length);
+
return res;
}
return 4096;
}
+int
+mono_valloc_granule (void)
+{
+ return mono_pagesize ();
+}
+
void*
-mono_valloc (void *addr, size_t length, int flags)
+mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
{
- return malloc (length);
+ return g_malloc (length);
}
void*
-mono_valloc_aligned (size_t length, size_t alignment, int flags)
+mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
{
g_assert_not_reached ();
}
#define HAVE_VALLOC_ALIGNED
int
-mono_vfree (void *addr, size_t length)
+mono_vfree (void *addr, size_t length, MonoMemAccountType type)
{
- free (addr);
+ g_free (addr);
return 0;
}
#ifndef HAVE_VALLOC_ALIGNED
void*
-mono_valloc_aligned (size_t size, size_t alignment, int flags)
+mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
{
/* Allocate twice the memory to be able to put the block on an aligned address */
- char *mem = (char *) mono_valloc (NULL, size + alignment, flags);
+ char *mem = (char *) mono_valloc (NULL, size + alignment, flags, type);
char *aligned;
if (!mem)
aligned = aligned_address (mem, size, alignment);
if (aligned > mem)
- mono_vfree (mem, aligned - mem);
+ mono_vfree (mem, aligned - mem, type);
if (aligned + size < mem + size + alignment)
- mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size));
+ mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size), type);
return aligned;
}